diff --git a/README.md b/README.md index 06afafe..dcfef73 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ declare module 'twind' { } ``` +> If no `twind.config.{ts,js,cjs,mjs}` and a `tailwind.config.{ts,js,cjs,mjs}` exists, the compatible values from the tailwind config will be used. + ### With VS Code Currently you must manually install the plugin along side TypeScript in your workspace. diff --git a/package.json b/package.json index 8f11b12..03cebc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@twind/typescript-plugin", - "version": "0.2.2", + "version": "0.2.3", "description": "TypeScript language service plugin that adds IntelliSense for twind", "//": "mark as private to prevent accidental publish - use 'yarn release'", "private": true, @@ -87,7 +87,7 @@ }, "sideEffects": false, "peerDependencies": { - "twind": ">=0.15.9 <2" + "twind": ">=0.16.0 <2" }, "peerDependenciesMeta": { "twind": { @@ -96,7 +96,7 @@ }, "dependencies": { "cssbeautify": "^0.3.1", - "esbuild": "^0.9.1", + "esbuild": "^0.9.3", "import-from": "^3.0.0", "locate-path": "^6.0.0", "match-sorter": "^6.3.0", diff --git a/src/colors.ts b/src/colors.ts index 557ed34..3c50b73 100644 --- a/src/colors.ts +++ b/src/colors.ts @@ -1,155 +1,154 @@ -const NAMED_COLORS = new Set([ - 'transparent', - 'currentColor', - 'aliceblue', - 'antiquewhite', - 'aqua', - 'aquamarine', - 'azure', - 'beige', - 'bisque', - 'black', - 'blanchedalmond', - 'blue', - 'blueviolet', - 'brown', - 'burlywood', - 'cadetblue', - 'chartreuse', - 'chocolate', - 'coral', - 'cornflowerblue', - 'cornsilk', - 'crimson', - 'cyan', - 'darkblue', - 'darkcyan', - 'darkgoldenrod', - 'darkgray', - 'darkgreen', - 'darkgrey', - 'darkkhaki', - 'darkmagenta', - 'darkolivegreen', - 'darkorange', - 'darkorchid', - 'darkred', - 'darksalmon', - 'darkseagreen', - 'darkslateblue', - 'darkslategray', - 'darkslategrey', - 'darkturquoise', - 'darkviolet', - 'deeppink', - 'deepskyblue', - 'dimgray', - 'dimgrey', - 'dodgerblue', - 'firebrick', - 'floralwhite', - 'forestgreen', - 'fuchsia', - 'gainsboro', - 'ghostwhite', - 'gold', - 'goldenrod', - 'gray', - 'green', - 'greenyellow', - 'grey', - 'honeydew', - 'hotpink', - 'indianred', - 'indigo', - 'ivory', - 'khaki', - 'lavender', - 'lavenderblush', - 'lawngreen', - 'lemonchiffon', - 'lightblue', - 'lightcoral', - 'lightcyan', - 'lightgoldenrodyellow', - 'lightgray', - 'lightgreen', - 'lightgrey', - 'lightpink', - 'lightsalmon', - 'lightseagreen', - 'lightskyblue', - 'lightslategray', - 'lightslategrey', - 'lightsteelblue', - 'lightyellow', - 'lime', - 'limegreen', - 'linen', - 'magenta', - 'maroon', - 'mediumaquamarine', - 'mediumblue', - 'mediumorchid', - 'mediumpurple', - 'mediumseagreen', - 'mediumslateblue', - 'mediumspringgreen', - 'mediumturquoise', - 'mediumvioletred', - 'midnightblue', - 'mintcream', - 'mistyrose', - 'moccasin', - 'navajowhite', - 'navy', - 'oldlace', - 'olive', - 'olivedrab', - 'orange', - 'orangered', - 'orchid', - 'palegoldenrod', - 'palegreen', - 'paleturquoise', - 'palevioletred', - 'papayawhip', - 'peachpuff', - 'peru', - 'pink', - 'plum', - 'powderblue', - 'purple', - 'rebeccapurple', - 'red', - 'rosybrown', - 'royalblue', - 'saddlebrown', - 'salmon', - 'sandybrown', - 'seagreen', - 'seashell', - 'sienna', - 'silver', - 'skyblue', - 'slateblue', - 'slategray', - 'slategrey', - 'snow', - 'springgreen', - 'steelblue', - 'tan', - 'teal', - 'thistle', - 'tomato', - 'transparent', - 'turquoise', - 'violet', - 'wheat', - 'white', - 'whitesmoke', - 'yellow', - 'yellowgreen', +const KNOWN_COLORS = new Set(['transparent', 'currentColor']) + +const NAMED_COLORS = new Map([ + ['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'], ]) const DEPRECATED_SYSTEM_COLORS = new Set([ @@ -183,7 +182,7 @@ const DEPRECATED_SYSTEM_COLORS = new Set([ 'WindowText', ]) -const COLORS = new Set([...NAMED_COLORS, ...DEPRECATED_SYSTEM_COLORS]) +const COLORS = new Set([...KNOWN_COLORS, ...NAMED_COLORS.keys(), ...DEPRECATED_SYSTEM_COLORS]) const isColorLike = (value: string): boolean => /^((#[\da-f]{3,8})|(((rgb|hsl)[a]?)\(?([\d]?\.?[\d]+%?,?\s?){3,4}\)?))$/i.test(value) @@ -191,7 +190,7 @@ const isColorLike = (value: string): boolean => // TODO function with opacityValue export const getColor = (value: unknown): string | undefined => { if (typeof value == 'string' && (COLORS.has(value) || isColorLike(value))) { - return value + return NAMED_COLORS.get(value) || value } return undefined diff --git a/src/language-service.ts b/src/language-service.ts index 69b197c..5ec02f8 100644 --- a/src/language-service.ts +++ b/src/language-service.ts @@ -321,7 +321,7 @@ export class TwindTemplateLanguageService implements TemplateLanguageService { ? vscode.CompletionItemKind.Module : completion.interpolation ? vscode.CompletionItemKind.Variable - : vscode.CompletionItemKind.Constant, + : vscode.CompletionItemKind.Property, data: completion.kind, label: rule.prefix && completion.label !== '&' && completion.kind == 'utility' diff --git a/src/load-twind-config.ts b/src/load-twind-config.ts index c8f2dc4..814511c 100644 --- a/src/load-twind-config.ts +++ b/src/load-twind-config.ts @@ -7,13 +7,29 @@ import locatePath from 'locate-path' import type { Configuration } from 'twind' -const CONFIG_FILES = ['twind.config.ts', 'twind.config.mjs', 'twind.config.js', 'twind.config.cjs'] +const TWIND_CONFIG_FILES = [ + 'twind.config.ts', + 'twind.config.mjs', + 'twind.config.js', + 'twind.config.cjs', +] +const TAILWIND_CONFIG_FILES = [ + 'tailwind.config.ts', + 'tailwind.config.mjs', + 'tailwind.config.js', + 'tailwind.config.cjs', +] + +// TODO use typescript to check files +// this.typescript.server.toNormalizedPath(fileName) +// info.project.containsFile() export const findConfig = (cwd = process.cwd()): string | undefined => - locatePath.sync(CONFIG_FILES.map((file) => Path.resolve(cwd, 'config', file))) || - locatePath.sync(CONFIG_FILES.map((file) => Path.resolve(cwd, 'src', file))) || - locatePath.sync(CONFIG_FILES.map((file) => Path.resolve(cwd, 'public', file))) || - findUp.sync(CONFIG_FILES, { cwd }) + locatePath.sync(TWIND_CONFIG_FILES.map((file) => Path.resolve(cwd, 'config', file))) || + locatePath.sync(TWIND_CONFIG_FILES.map((file) => Path.resolve(cwd, 'src', file))) || + locatePath.sync(TWIND_CONFIG_FILES.map((file) => Path.resolve(cwd, 'public', file))) || + findUp.sync(TWIND_CONFIG_FILES, { cwd }) || + findUp.sync(TAILWIND_CONFIG_FILES, { cwd }) export const loadConfig = (configFile: string, cwd = process.cwd()): Configuration => { const result = buildSync({ @@ -23,6 +39,9 @@ export const loadConfig = (configFile: string, cwd = process.cwd()): Configurati platform: 'node', target: `node${process.versions.node}`, external: Module.builtinModules, + // Follow WMR rules + mainFields: ['esmodules', 'modern', 'module', 'jsnext:main', 'main'], + conditions: ['development', 'esmodules', 'module', 'node', 'import', 'require', 'default'], sourcemap: 'inline', minify: false, splitting: false, diff --git a/src/parser.test.ts b/src/parser.test.ts index 27b1989..b96f4cd 100644 --- a/src/parser.test.ts +++ b/src/parser.test.ts @@ -230,6 +230,87 @@ const test = suite('Parser') }, ], ], + [ + 'top-[-123px] grid-cols-[minmax(100px,max-content)repeat(auto-fill,200px)20%] grid-rows-auto-1fr-auto bg-[#1da1f2]', + [ + { + raw: 'top-[-123px]', + value: 'top-[-123px]', + name: 'top-[-123px]', + prefix: '', + important: false, + negated: false, + loc: { + start: 0, + end: 12, + }, + spans: [ + { + start: 0, + end: 12, + }, + ], + variants: [], + }, + { + raw: 'grid-cols-[minmax(100px,max-content)repeat(auto-fill,200px)20%]', + value: 'grid-cols-[minmax(100px,max-content)repeat(auto-fill,200px)20%]', + name: 'grid-cols-[minmax(100px,max-content)repeat(auto-fill,200px)20%]', + prefix: '', + important: false, + negated: false, + loc: { + start: 13, + end: 76, + }, + spans: [ + { + start: 13, + end: 76, + }, + ], + variants: [], + }, + { + raw: 'grid-rows-auto-1fr-auto', + value: 'grid-rows-auto-1fr-auto', + name: 'grid-rows-auto-1fr-auto', + prefix: '', + important: false, + negated: false, + loc: { + start: 77, + end: 100, + }, + spans: [ + { + start: 77, + end: 100, + }, + ], + variants: [], + }, + { + raw: 'bg-[#1da1f2]', + value: 'bg-[#1da1f2]', + name: 'bg-[#1da1f2]', + prefix: '', + important: false, + negated: false, + loc: { + start: 101, + end: 113, + }, + spans: [ + { + start: 101, + end: 113, + }, + ], + variants: [], + }, + ], + ], ] as const).forEach(([input, expected]) => { test(`parse: ${JSON.stringify(input)}`, () => { // console.log(JSON.stringify(parse(input))) diff --git a/src/parser.ts b/src/parser.ts index e218d76..36f9b49 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -279,14 +279,20 @@ export function astish(text: string, atPosition = Infinity): Group { let parent: Exclude = root let node: Exclude = root - for (let char: string, position = 0; position < text.length; position++) { + for (let char: string, dynamic = false, position = 0; (char = text[position]); position++) { if (position >= atPosition) { node.next = createIdentifier(node, parent, buffer, start) return root } - switch ((char = text[position])) { + if (dynamic || char == '[') { + buffer += char + dynamic = char != ']' + continue + } + + switch (char) { case ':': if (buffer) { buffer += char diff --git a/yarn.lock b/yarn.lock index 768fddb..30d7a6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -431,11 +431,16 @@ esbuild@^0.8.28: resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.8.57.tgz#a42d02bc2b57c70bcd0ef897fe244766bb6dd926" integrity sha512-j02SFrUwFTRUqiY0Kjplwjm1psuzO1d6AjaXKuOR9hrY0HuPsT6sV42B6myW34h1q4CRy+Y3g4RU/cGJeI/nNA== -esbuild@^0.9.1, esbuild@^0.9.2: +esbuild@^0.9.2: version "0.9.2" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.9.2.tgz#7e9fde247c913ed8ee059e2648b0c53f7d00abe5" integrity sha512-xE3oOILjnmN8PSjkG3lT9NBbd1DbxNqolJ5qNyrLhDWsFef3yTp/KTQz1C/x7BYFKbtrr9foYtKA6KA1zuNAUQ== +esbuild@^0.9.3: + version "0.9.4" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.9.4.tgz#4480ffc4c1e5d5bb25958f889b5de0279bfb2d6f" + integrity sha512-bF6laCiYE5+iAfZsX+v6Lwvi5QbvKN3tThxDIR2WLyLYzTzNn0ijdpqkvTVsafmRZjic2Nq1nkSf5RSWySDTjA== + escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"