diff --git a/CHANGELOG.md b/CHANGELOG.md index 6981d49..16555c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `var()` and `calc()` css builtin function autocomplete support +- color picker support, to fix [#51](https://github.com/d4rkr00t/language-stylus/issues/51) ### Changed - Change `css function` automplete behavior, set cursor into the position between parens diff --git a/README.md b/README.md index 134b660..897dbb3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # vscode-stylus [![VSCode Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/sysoev.language-stylus?label=VSCode%20Marketplace)](https://marketplace.visualstudio.com/items?itemName=sysoev.language-stylus) -[![VSCode Marketplace Downloads](https://img.shields.io/visual-studio-marketplace/i/sysoev.language-stylus)](https://marketplace.visualstudio.com/items?itemName=sysoev.language-stylus) +[![VSCode Marketplace Installs](https://img.shields.io/visual-studio-marketplace/i/sysoev.language-stylus)](https://marketplace.visualstudio.com/items?itemName=sysoev.language-stylus) +[![VSCode Marketplace Downloads](https://img.shields.io/visual-studio-marketplace/d/sysoev.language-stylus)](https://marketplace.visualstudio.com/items?itemName=sysoev.language-stylus) [![VSCode Marketplace Stars](https://img.shields.io/visual-studio-marketplace/r/sysoev.language-stylus)](https://marketplace.visualstudio.com/items?itemName=sysoev.language-stylus) [![github-issues](https://img.shields.io/github/issues/d4rkr00t/language-stylus.svg)](https://github.com/d4rkr00t/language-stylus/issues) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/d4rkr00t/language-stylus/pulls) @@ -27,8 +28,6 @@ Adds syntax highlighting and code completion to `Stylus` files in Visual Studio "languageStylus.useSeparator": true, // default value // Toggle matches for Stylus Builtin Functions on autocomplete "languageStylus.useBuiltinFunctions": true, // default value - // Toggle colors preview - "editor.colorDecorators": true // default value } ``` diff --git a/package.json b/package.json index 2c4148b..cc2620a 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,10 @@ "main": "./out/src/extension", "icon": "assets/icon.png", "keywords": [ - "vscode", - "stylus", "styl", + "stylus", "language-stylus", "vscode-stylus", - "language-support", "stylus-intellisense" ], "activationEvents": [ diff --git a/src/color-decorators.ts b/src/color-decorators.ts deleted file mode 100644 index d1ceb06..0000000 --- a/src/color-decorators.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { Disposable, DecorationRenderOptions, DecorationOptions, Position, Range, window, workspace, TextDocument } from 'vscode'; -import { - StylusNode, - StylusValue, - buildAst, flattenAndFilterAst, - isColor -} from './parser'; - -import { debounce } from './utils'; - -const MAX_DECORATORS = 500; -const DEBOUNCE_TIME = 400; - -let decorationType: any = { - before: { - contentText: ' ', - border: 'solid 0.1em #000', - margin: '0.1em 0.2em 0 0.2em', - width: '0.8em', - height: '0.8em' - }, - dark: { - before: { - border: 'solid 0.1em #eee' - } - } -}; - -export function extractColorsFromExpression(node:StylusValue) { - let result = []; - - if (node.nodeName === 'expression') { - node.nodes.forEach(valNode => { - if (isColor(valNode)) { - result.push(valNode); - } else if (valNode.nodeName === 'object') { - Object.keys(valNode.vals).forEach(subValNode => { - result = result.concat(extractColorsFromExpression(valNode.vals[subValNode])); - }); - } - }) - } - - return result; -} - -export function getColors(ast) { - return (ast.nodes || ast || []).reduce((acc, node) => { - if (node.nodeName === 'ident') { - acc = acc.concat(extractColorsFromExpression(node.val)); - } - - if (node.nodeName === 'property' && node.expr) { - acc = acc.concat(extractColorsFromExpression(node.expr)); - } - - return acc; - }, []); -} - -export const buildCallValueFromArgs = args => - args.nodes.map(node => node.nodes[0].val).join(', '); - -export const getRealColumn = (textToSearch: string, text: string[], lineno: number) => - Math.max(text[lineno].indexOf(textToSearch), 0); - -export function normalizeColors(colors: StylusNode[], text: string[]) { - return colors.map(color => { - const normalized = { column: 0, lineno: color.lineno - 1, background: 'transparent' }; - - if (color.nodeName === 'ident') { - normalized.background = color.name; - normalized.column = getRealColumn(color.name, text, normalized.lineno); - } - if (color.nodeName === 'rgba') { - normalized.column = getRealColumn((color as any).raw, text, normalized.lineno); - normalized.background = (color as any).raw; - } - - if (color.nodeName === 'call') { - normalized.column = getRealColumn(color.name, text, normalized.lineno); - normalized.background = `${color.name}(${buildCallValueFromArgs((color as any).args)})`; - } - - return normalized; - }); -} - -export function updateDecorators(colorsDecorationType, editor) { - const document = editor.document.getText(); - const ast = flattenAndFilterAst(buildAst(document)); - const colors = normalizeColors(getColors(ast), document.split('\n')); - - const decorations = colors.map(color => { - const pos = new Position(color.lineno, color.column); - return { - range: new Range(pos, pos), - renderOptions: { - before: { backgroundColor: color.background } - } - }; - }).slice(0, MAX_DECORATORS); - - editor.setDecorations(colorsDecorationType, decorations as any); -} - -export const findEditorByDocument = document => - window.visibleTextEditors.find(editor => - editor.document.uri.toString() === document.uri.toString()); - -export const updateDecoratorsWrapper = (colorsDecorationType, editor) => - updateDecorators(colorsDecorationType, editor); - -export const updateDecoratorsWrapperDebounced = - debounce(updateDecoratorsWrapper, DEBOUNCE_TIME); - -export function activateColorDecorations(): Disposable { - const disposables: Disposable[] = []; - const colorsDecorationType = window.createTextEditorDecorationType(decorationType); - disposables.push(colorsDecorationType); - - window.visibleTextEditors.forEach(editor => { - if (!editor || !editor.document) return; - updateDecoratorsWrapper(colorsDecorationType, editor); - }); - - window.onDidChangeActiveTextEditor(editor => { - if (!editor || !editor.document) return; - updateDecoratorsWrapperDebounced(colorsDecorationType, editor); - }); - - workspace.onDidChangeTextDocument(evt => { - if (!evt.document) return; - const editor = findEditorByDocument(evt.document); - if (!editor) return; - updateDecoratorsWrapperDebounced(colorsDecorationType, editor); - }); - - workspace.onDidOpenTextDocument(document => { - if (!document) return; - const editor = findEditorByDocument(document); - if (!editor) return; - updateDecoratorsWrapperDebounced(colorsDecorationType, editor); - }); - - (window as any).onDidChangeVisibleTextEditors(editors => { - editors.forEach(editor => { - if (!editor.document) return; - updateDecoratorsWrapperDebounced(colorsDecorationType, editor); - }) - }); - - return Disposable.from(...disposables); -} diff --git a/src/color-provider.ts b/src/color-provider.ts new file mode 100644 index 0000000..f1eafba --- /dev/null +++ b/src/color-provider.ts @@ -0,0 +1,192 @@ +import { + CancellationToken, + Color, + ColorInformation, + ColorPresentation, + DocumentColorProvider, + Position, + ProviderResult, + Range, + TextDocument, + TextEdit +} from 'vscode'; + +import { + StylusNode, + StylusValue, + buildAst, flattenAndFilterAst, + isColor +} from './parser'; +import { + colors, + colorFromHex, + getNumericValue, + getAngle, + toTwoDigitHex, + colorFromHSL, + hslFromColor +} from './colors'; + +export const buildCallValueFromArgs = args => + args.nodes.map(node => node.nodes[0].val).join(', '); + +export const getRealColumn = (textToSearch: string, text: string[], lineno: number) => + Math.max(text[lineno].indexOf(textToSearch), 0); + +export const getRealCallColumn = (textToSearch: string, text: string[], lineno: number) => { + const startPos = Math.max(text[lineno].indexOf(textToSearch), 0); + const searchStr = text[lineno].slice(startPos); + return Math.max(text[lineno].indexOf(textToSearch), 0) + searchStr.indexOf(")") + 1; +} + +export function normalizeColors(colorsNode: StylusNode[], text: string[]): ColorInformation[] { + const colorsInformation = []; + colorsNode.forEach(color => { + if (color.nodeName === 'ident' && colors[color.name]) { + try { + const colorObj = colorFromHex(colors[color.name]); + colorsInformation.push(new ColorInformation( + new Range( + new Position(color.lineno - 1, getRealColumn(color.name, text, color.lineno - 1)), + new Position(color.lineno - 1, getRealColumn(color.name, text, color.lineno - 1) + color.name?.length || 0) + ), + new Color(colorObj.red, colorObj.green, colorObj.blue, colorObj.alpha) + )); + } catch (_) { + // do nothing + } + } else if (color.nodeName === 'rgba') { + try { + colorsInformation.push(new ColorInformation( + new Range( + new Position(color.lineno - 1, getRealColumn((color as any).raw, text, color.lineno - 1)), + new Position(color.lineno - 1, getRealColumn((color as any).raw, text, color.lineno - 1) + (color as any).raw?.length || 0) + ), + // @ts-ignore + new Color(color.r, color.g, color.b, color.a) + )); + } catch (_) { + // do nothing + } + } else if (color.nodeName === 'call') { + try { + // @ts-ignore + const colorValues = color?.args?.nodes?.map?.(node => node.nodes[0].val); + if (!colorValues || colorValues.length < 3 || colorValues.length > 4) { + return; + } + const alpha = colorValues.length === 4 ? getNumericValue(colorValues[3], 1) : 1; + const funcName = color.name as string; + if (funcName === 'rgb' || funcName === 'rgba') { + colorsInformation.push(new ColorInformation( + new Range( + new Position(color.lineno - 1, getRealColumn(color.name, text, color.lineno - 1)), + new Position(color.lineno - 1, getRealCallColumn(color.name, text, color.lineno - 1)) + ), + // @ts-ignore + new Color( + getNumericValue(colorValues[0], 255.0), + getNumericValue(colorValues[1], 255.0), + getNumericValue(colorValues[2], 255.0), + alpha + ) + )); + } else if (funcName === 'hsl' || funcName === 'hsla') { + const h = getAngle(colorValues[0]); + const s = getNumericValue(colorValues[1], 100.0); + const l = getNumericValue(colorValues[2], 100.0); + const colorRes = colorFromHSL(h, s, l, alpha); + colorsInformation.push(new ColorInformation( + new Range( + new Position(color.lineno - 1, getRealColumn(color.name, text, color.lineno - 1)), + new Position(color.lineno - 1, getRealCallColumn(color.name, text, color.lineno - 1)) + ), + new Color(colorRes.red, colorRes.green, colorRes.blue, colorRes.alpha) + )); + } + } catch (_) { + _; + // do nothing + } + } + }); + return colorsInformation; +} + +export function extractColorsFromExpression(node:StylusValue) { + let result = []; + + if (node.nodeName === 'expression') { + node.nodes.forEach(valNode => { + if (isColor(valNode)) { + result.push(valNode); + } else if (valNode.nodeName === 'object') { + Object.keys(valNode.vals).forEach(subValNode => { + result = result.concat(extractColorsFromExpression(valNode.vals[subValNode])); + }); + } + }) + } + + return result; +} + +export function getColors(ast) { + return (ast.nodes || ast || []).reduce((acc, node) => { + if (node.nodeName === 'ident') { + acc = acc.concat(extractColorsFromExpression(node.val)); + } + + if (node.nodeName === 'property' && node.expr) { + acc = acc.concat(extractColorsFromExpression(node.expr)); + } + + return acc; + }, []); +} + +export class StylusColorProvider implements DocumentColorProvider { + + provideDocumentColors(document: TextDocument, token: CancellationToken): ProviderResult { + if (token.isCancellationRequested) { + return []; + } + const documentTxt = document.getText(); + const ast = flattenAndFilterAst(buildAst(documentTxt)); + const list = normalizeColors(getColors(ast), documentTxt.split('\n')); + return list; + } + + provideColorPresentations(color: Color, context: { document: TextDocument; range: Range; }, token: CancellationToken): ProviderResult { + if (token.isCancellationRequested) { + return []; + } + const result: ColorPresentation[] = []; + const red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255); + + let label; + if (color.alpha === 1) { + label = `rgb(${red256}, ${green256}, ${blue256})`; + } else { + label = `rgba(${red256}, ${green256}, ${blue256}, ${color.alpha})`; + } + result.push({ label: label, textEdit: TextEdit.replace(context.range, label) }); + + if (color.alpha === 1) { + label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`; + } else { + label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`; + } + result.push({ label: label, textEdit: TextEdit.replace(context.range, label) }); + + const hsl = hslFromColor(color); + if (hsl.a === 1) { + label = `hsl(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%)`; + } else { + label = `hsla(${hsl.h}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%, ${hsl.a})`; + } + result.push({ label: label, textEdit: TextEdit.replace(context.range, label) }); + + return result; + } +} diff --git a/src/colors.ts b/src/colors.ts new file mode 100644 index 0000000..bd19059 --- /dev/null +++ b/src/colors.ts @@ -0,0 +1,289 @@ +import { Color } from 'vscode'; + +export const colors: { [name: string]: string } = { + aliceblue: '#f0f8ff', + antiquewhite: '#faebd7', + aqua: '#00ffff', + aquamarine: '#7fffd4', + azure: '#f0ffff', + beige: '#f5f5dc', + bisque: '#ffe4c4', + black: '#000000', + blanchedalmond: '#ffebcd', + blue: '#0000ff', + blueviolet: '#8a2be2', + brown: '#a52a2a', + burlywood: '#deb887', + cadetblue: '#5f9ea0', + chartreuse: '#7fff00', + chocolate: '#d2691e', + coral: '#ff7f50', + cornflowerblue: '#6495ed', + cornsilk: '#fff8dc', + crimson: '#dc143c', + cyan: '#00ffff', + darkblue: '#00008b', + darkcyan: '#008b8b', + darkgoldenrod: '#b8860b', + darkgray: '#a9a9a9', + darkgrey: '#a9a9a9', + darkgreen: '#006400', + darkkhaki: '#bdb76b', + darkmagenta: '#8b008b', + darkolivegreen: '#556b2f', + darkorange: '#ff8c00', + darkorchid: '#9932cc', + darkred: '#8b0000', + darksalmon: '#e9967a', + darkseagreen: '#8fbc8f', + darkslateblue: '#483d8b', + darkslategray: '#2f4f4f', + darkslategrey: '#2f4f4f', + darkturquoise: '#00ced1', + darkviolet: '#9400d3', + deeppink: '#ff1493', + deepskyblue: '#00bfff', + dimgray: '#696969', + dimgrey: '#696969', + dodgerblue: '#1e90ff', + firebrick: '#b22222', + floralwhite: '#fffaf0', + forestgreen: '#228b22', + fuchsia: '#ff00ff', + gainsboro: '#dcdcdc', + ghostwhite: '#f8f8ff', + gold: '#ffd700', + goldenrod: '#daa520', + gray: '#808080', + grey: '#808080', + green: '#008000', + greenyellow: '#adff2f', + honeydew: '#f0fff0', + hotpink: '#ff69b4', + indianred: '#cd5c5c', + indigo: '#4b0082', + ivory: '#fffff0', + khaki: '#f0e68c', + lavender: '#e6e6fa', + lavenderblush: '#fff0f5', + lawngreen: '#7cfc00', + lemonchiffon: '#fffacd', + lightblue: '#add8e6', + lightcoral: '#f08080', + lightcyan: '#e0ffff', + lightgoldenrodyellow: '#fafad2', + lightgray: '#d3d3d3', + lightgrey: '#d3d3d3', + lightgreen: '#90ee90', + lightpink: '#ffb6c1', + lightsalmon: '#ffa07a', + lightseagreen: '#20b2aa', + lightskyblue: '#87cefa', + lightslategray: '#778899', + lightslategrey: '#778899', + lightsteelblue: '#b0c4de', + lightyellow: '#ffffe0', + lime: '#00ff00', + limegreen: '#32cd32', + linen: '#faf0e6', + magenta: '#ff00ff', + maroon: '#800000', + mediumaquamarine: '#66cdaa', + mediumblue: '#0000cd', + mediumorchid: '#ba55d3', + mediumpurple: '#9370d8', + mediumseagreen: '#3cb371', + mediumslateblue: '#7b68ee', + mediumspringgreen: '#00fa9a', + mediumturquoise: '#48d1cc', + mediumvioletred: '#c71585', + midnightblue: '#191970', + mintcream: '#f5fffa', + mistyrose: '#ffe4e1', + moccasin: '#ffe4b5', + navajowhite: '#ffdead', + navy: '#000080', + oldlace: '#fdf5e6', + olive: '#808000', + olivedrab: '#6b8e23', + orange: '#ffa500', + orangered: '#ff4500', + orchid: '#da70d6', + palegoldenrod: '#eee8aa', + palegreen: '#98fb98', + paleturquoise: '#afeeee', + palevioletred: '#d87093', + papayawhip: '#ffefd5', + peachpuff: '#ffdab9', + peru: '#cd853f', + pink: '#ffc0cb', + plum: '#dda0dd', + powderblue: '#b0e0e6', + purple: '#800080', + red: '#ff0000', + rebeccapurple: '#663399', + rosybrown: '#bc8f8f', + royalblue: '#4169e1', + saddlebrown: '#8b4513', + salmon: '#fa8072', + sandybrown: '#f4a460', + seagreen: '#2e8b57', + seashell: '#fff5ee', + sienna: '#a0522d', + silver: '#c0c0c0', + skyblue: '#87ceeb', + slateblue: '#6a5acd', + slategray: '#708090', + slategrey: '#708090', + snow: '#fffafa', + springgreen: '#00ff7f', + steelblue: '#4682b4', + tan: '#d2b48c', + teal: '#008080', + thistle: '#d8bfd8', + tomato: '#ff6347', + turquoise: '#40e0d0', + violet: '#ee82ee', + wheat: '#f5deb3', + white: '#ffffff', + whitesmoke: '#f5f5f5', + yellow: '#ffff00', + yellowgreen: '#9acd32' +}; + +export function getNumericValue(val: any, factor: number) { + const m = String(val).match(/^([-+]?[0-9]*\.?[0-9]+)(%?)$/); + if (m) { + if (m[2]) { + factor = 100.0; + } + const result = parseFloat(m[1]) / factor; + if (result >= 0 && result <= 1) { + return result; + } + } + throw new Error(); +} + +export function getAngle(val: any) { + const m = String(val).match(/^([-+]?[0-9]*\.?[0-9]+)(deg)?$/); + if (m) { + return parseFloat(val) % 360; + } else if (Number(val)) { + return Number(val); + } + throw new Error(); +} + +const Digit0 = 48; +const Digit9 = 57; +const A = 65; +const F = 70; +const a = 97; +const f = 102; + +export function hexDigit(charCode: number) { + if (charCode < Digit0) { + return 0; + } + if (charCode <= Digit9) { + return charCode - Digit0; + } + if (charCode < a) { + charCode += (a - A); + } + if (charCode >= a && charCode <= f) { + return charCode - a + 10; + } + return 0; +} + +export function colorFromHex(text: string): Color | null { + if (text[0] !== '#') { + return null; + } + switch (text.length) { + case 4: + return { + red: (hexDigit(text.charCodeAt(1)) * 0x11) / 255.0, + green: (hexDigit(text.charCodeAt(2)) * 0x11) / 255.0, + blue: (hexDigit(text.charCodeAt(3)) * 0x11) / 255.0, + alpha: 1 + }; + case 5: + return { + red: (hexDigit(text.charCodeAt(1)) * 0x11) / 255.0, + green: (hexDigit(text.charCodeAt(2)) * 0x11) / 255.0, + blue: (hexDigit(text.charCodeAt(3)) * 0x11) / 255.0, + alpha: (hexDigit(text.charCodeAt(4)) * 0x11) / 255.0, + }; + case 7: + return { + red: (hexDigit(text.charCodeAt(1)) * 0x10 + hexDigit(text.charCodeAt(2))) / 255.0, + green: (hexDigit(text.charCodeAt(3)) * 0x10 + hexDigit(text.charCodeAt(4))) / 255.0, + blue: (hexDigit(text.charCodeAt(5)) * 0x10 + hexDigit(text.charCodeAt(6))) / 255.0, + alpha: 1 + }; + case 9: + return { + red: (hexDigit(text.charCodeAt(1)) * 0x10 + hexDigit(text.charCodeAt(2))) / 255.0, + green: (hexDigit(text.charCodeAt(3)) * 0x10 + hexDigit(text.charCodeAt(4))) / 255.0, + blue: (hexDigit(text.charCodeAt(5)) * 0x10 + hexDigit(text.charCodeAt(6))) / 255.0, + alpha: (hexDigit(text.charCodeAt(7)) * 0x10 + hexDigit(text.charCodeAt(8))) / 255.0 + }; + } + return null; +} + +export function colorFromHSL(hue: number, sat: number, light: number, alpha: number = 1.0): Color { + hue = hue / 60.0; + if (sat === 0) { + return { red: light, green: light, blue: light, alpha }; + } else { + const hueToRgb = (t1: number, t2: number, hue: number) => { + while (hue < 0) { hue += 6; } + while (hue >= 6) { hue -= 6; } + + if (hue < 1) { return (t2 - t1) * hue + t1; } + if (hue < 3) { return t2; } + if (hue < 4) { return (t2 - t1) * (4 - hue) + t1; } + return t1; + }; + const t2 = light <= 0.5 ? (light * (sat + 1)) : (light + sat - (light * sat)); + const t1 = light * 2 - t2; + return { red: hueToRgb(t1, t2, hue + 2), green: hueToRgb(t1, t2, hue), blue: hueToRgb(t1, t2, hue - 2), alpha }; + } +} + +export function hslFromColor(rgba: Color): any { + const r = rgba.red; + const g = rgba.green; + const b = rgba.blue; + const a = rgba.alpha; + + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let h = 0; + let s = 0; + const l = (min + max) / 2; + const chroma = max - min; + + if (chroma > 0) { + s = Math.min((l <= 0.5 ? chroma / (2 * l) : chroma / (2 - (2 * l))), 1); + + switch (max) { + case r: h = (g - b) / chroma + (g < b ? 6 : 0); break; + case g: h = (b - r) / chroma + 2; break; + case b: h = (r - g) / chroma + 4; break; + } + + h *= 60; + h = Math.round(h); + } + return { h, s, l, a }; +} + +export function toTwoDigitHex(n: number): string { + const r = n.toString(16); + return r.length !== 2 ? '0' + r : r; +} diff --git a/src/extension.ts b/src/extension.ts index 4558abb..e71ea80 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import CompletionProvider from './completion-item-provider'; import { StylusDocumentSimbolsProvider } from './symbols-provider'; -import { activateColorDecorations } from './color-decorators'; +import { StylusColorProvider } from './color-provider'; const DOCUMENT_SELECTOR = { language: 'stylus', @@ -49,11 +49,13 @@ export function activate(context: vscode.ExtensionContext) { ] }); + // symbol const symbolsProvider = new StylusDocumentSimbolsProvider(); const symbolsProviderDisposable = vscode.languages.registerDocumentSymbolProvider(DOCUMENT_SELECTOR, symbolsProvider); context.subscriptions.push(symbolsProviderDisposable); - if (editorConfig.get('colorDecorators')) { - context.subscriptions.push(activateColorDecorations()); - } + // color + const colorProvider = new StylusColorProvider(); + const colorProviderDisposable = vscode.languages.registerColorProvider(DOCUMENT_SELECTOR, colorProvider); + context.subscriptions.push(colorProviderDisposable); } diff --git a/test/style.styl b/test/style.styl index c1db359..6455c22 100644 --- a/test/style.styl +++ b/test/style.styl @@ -8,7 +8,7 @@ $color-wheel = { '1': red, '2': rgba(255,255,255,0), '3': rgb(255,255,255), - '4': hsl(255,255,255), + '4': hsl(255,90%,25%), '5': #ddd }