Add support for v3-alpha (#424)

* wip

* Update v3 support, color handling

* Update diagnostics and completions

* bump language service

* update context api usage

* bump language service
master
Brad Cornes 2021-10-01 14:11:45 +01:00 committed by GitHub
parent 11e097ec5a
commit 53743f2faa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 667 additions and 749 deletions

564
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,6 @@
"access": "public"
},
"devDependencies": {
"@ctrl/tinycolor": "3.1.4",
"@parcel/watcher": "2.0.0-alpha.10",
"@types/debounce": "1.2.0",
"@types/node": "14.14.34",
@ -29,6 +28,8 @@
"@vercel/ncc": "0.28.4",
"builtin-modules": "3.2.0",
"chokidar": "3.5.1",
"color-name": "1.1.4",
"culori": "0.20.1",
"debounce": "1.2.0",
"detective": "5.2.0",
"dlv": "1.1.3",

View File

@ -69,12 +69,15 @@ import {
} from './lsp/diagnosticsProvider'
import { doCodeActions } from 'tailwindcss-language-service/src/codeActions/codeActionProvider'
import { getDocumentColors } from 'tailwindcss-language-service/src/documentColorProvider'
import { fromRatio, names as namedColors } from '@ctrl/tinycolor'
import { debounce } from 'debounce'
import { getModuleDependencies } from './util/getModuleDependencies'
import assert from 'assert'
// import postcssLoadConfig from 'postcss-load-config'
import * as parcel from './watcher/index.js'
import { generateRules } from 'tailwindcss-language-service/src/util/jit'
import { getColor } from 'tailwindcss-language-service/src/util/color'
import * as culori from 'culori'
import namedColors from 'color-name'
const CONFIG_FILE_GLOB = '{tailwind,tailwind.config}.{js,cjs}'
const TRIGGER_CHARACTERS = [
@ -101,7 +104,7 @@ declare var __non_webpack_require__: typeof require
const connection =
process.argv.length <= 2 ? createConnection(process.stdin, process.stdout) : createConnection()
console.log = connection.console.log.bind(connection.console)
// console.log = connection.console.log.bind(connection.console)
console.error = connection.console.error.bind(connection.console)
process.on('unhandledRejection', (e: any) => {
@ -150,6 +153,15 @@ function first<T>(...options: Array<() => T>): T {
}
}
function firstOptional<T>(...options: Array<() => T>): T | undefined {
for (let i = 0; i < options.length; i++) {
let option = options[i]
try {
return option()
} catch (_) {}
}
}
interface ProjectService {
state: State
tryInit: () => Promise<void>
@ -528,8 +540,8 @@ async function createProjectService(
}
if (semver.gte(tailwindcssVersion, '1.99.0')) {
applyComplexClasses = __non_webpack_require__(
resolveFrom(tailwindDir, './lib/lib/substituteClassApplyAtRules')
applyComplexClasses = firstOptional(() =>
__non_webpack_require__(resolveFrom(tailwindDir, './lib/lib/substituteClassApplyAtRules'))
)
} else if (semver.gte(tailwindcssVersion, '1.7.0')) {
applyComplexClasses = __non_webpack_require__(
@ -551,6 +563,13 @@ async function createProjectService(
try {
let createContext = first(
() => {
let createContextFn = __non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/lib/setupContextUtils')
).createContext
assert.strictEqual(typeof createContextFn, 'function')
return (state) => createContextFn(state.config)
},
() => {
let createContextFn = __non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/jit/lib/setupContextUtils')
@ -582,17 +601,30 @@ async function createProjectService(
jitModules = {
generateRules: {
module: __non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/jit/lib/generateRules')
).generateRules,
module: first(
() =>
__non_webpack_require__(resolveFrom(configDir, 'tailwindcss/lib/lib/generateRules'))
.generateRules,
() =>
__non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/jit/lib/generateRules')
).generateRules
),
},
createContext: {
module: createContext,
},
expandApplyAtRules: {
module: __non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/jit/lib/expandApplyAtRules')
).default,
module: first(
() =>
__non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/lib/expandApplyAtRules')
).default,
() =>
__non_webpack_require__(
resolveFrom(configDir, 'tailwindcss/lib/jit/lib/expandApplyAtRules')
).default
),
},
}
} catch (_) {
@ -728,6 +760,8 @@ async function createProjectService(
let presetVariants: any[] = []
let originalConfig: any
let isV3 = semver.gte(tailwindcss.version, '2.99.0')
let hook = new Hook(fs.realpathSync(state.configPath), (exports) => {
originalConfig = klona(exports)
@ -736,7 +770,7 @@ async function createProjectService(
separator = ':'
}
dset(exports, sepLocation, `__TWSEP__${separator}__TWSEP__`)
exports.purge = []
exports[isV3 ? 'content' : 'purge'] = []
let mode: any
if (Array.isArray(exports.presets)) {
@ -753,7 +787,9 @@ async function createProjectService(
}
delete exports.mode
if (state.modules.jit && mode === 'jit') {
let isJit = isV3 || (state.modules.jit && mode === 'jit')
if (isJit) {
state.jit = true
exports.variants = []
@ -828,32 +864,42 @@ async function createProjectService(
if (state.jit) {
state.jitContext = state.modules.jit.createContext.module(state)
state.jitContext.tailwindConfig.separator = state.config.separator
if (state.jitContext.getClassList) {
state.classList = state.jitContext.getClassList().map((className) => {
return [className, { color: getColor(state, className) }]
})
}
}
let postcssResult: Result
try {
postcssResult = await postcss
.module([
// ...state.postcssPlugins.before.map((x) => x()),
tailwindcss.module(state.configPath),
// ...state.postcssPlugins.after.map((x) => x()),
])
.process(
[
semver.gte(tailwindcss.version, '0.99.0') ? 'base' : 'preflight',
'components',
'utilities',
]
.map((x) => `/*__tw_intellisense_layer_${x}__*/\n@tailwind ${x};`)
.join('\n'),
{
from: undefined,
}
)
} catch (error) {
throw error
} finally {
if (state.classList) {
hook.unhook()
} else {
try {
postcssResult = await postcss
.module([
// ...state.postcssPlugins.before.map((x) => x()),
tailwindcss.module(state.configPath),
// ...state.postcssPlugins.after.map((x) => x()),
])
.process(
[
semver.gte(tailwindcss.version, '0.99.0') ? 'base' : 'preflight',
'components',
'utilities',
]
.map((x) => `/*__tw_intellisense_layer_${x}__*/\n@tailwind ${x};`)
.join('\n'),
{
from: undefined,
}
)
} catch (error) {
throw error
} finally {
hook.unhook()
}
}
if (state.dependencies) {
@ -865,7 +911,9 @@ async function createProjectService(
state.configId = getConfigId(state.configPath, state.dependencies)
state.plugins = await getPlugins(originalConfig)
state.classNames = (await extractClassNames(postcssResult.root)) as ClassNames
if (postcssResult) {
state.classNames = (await extractClassNames(postcssResult.root)) as ClassNames
}
state.variants = getVariants(state)
let screens = dlv(state.config, 'theme.screens', dlv(state.config, 'screens', {}))
@ -939,16 +987,25 @@ async function createProjectService(
let currentColor = match[1]
let isNamedColor = colorNames.includes(currentColor)
let color = fromRatio({
let color: culori.RgbColor = {
mode: 'rgb',
r: params.color.red,
g: params.color.green,
b: params.color.blue,
a: params.color.alpha,
})
alpha: params.color.alpha,
}
let hexValue = culori.formatHex8(color)
if (!isNamedColor && (currentColor.length === 4 || currentColor.length === 5)) {
let [, ...chars] =
hexValue.match(/^#([a-f\d])\1([a-f\d])\2([a-f\d])\3(?:([a-f\d])\4)?$/i) ?? []
if (chars.length) {
hexValue = `#${chars.filter(Boolean).join('')}`
}
}
let hexValue = color.toHex8String(
!isNamedColor && (currentColor.length === 4 || currentColor.length === 5)
)
if (hexValue.length === 5) {
hexValue = hexValue.replace(/f$/, '')
} else if (hexValue.length === 9) {
@ -959,8 +1016,12 @@ async function createProjectService(
return [
hexValue,
color.toRgbString().replace(/ /g, ''),
color.toHslString().replace(/ /g, ''),
culori.formatRgb(color).replace(/ /g, ''),
culori
.formatHsl(color)
.replace(/ /g, '')
// round numbers
.replace(/\d+\.\d+(%?)/g, (value, suffix) => `${Math.round(parseFloat(value))}${suffix}`),
].map((value) => ({ label: `${prefix}-[${value}]` }))
},
}

View File

@ -14,5 +14,5 @@
"tailwindcss-language-service/*": ["../packages/tailwindcss-language-service/*"]
}
},
"include": ["src", "../packages/tailwindcss-language-service"]
"include": ["src", "../packages/tailwindcss-language-service", "../../types"]
}

View File

@ -1,15 +1,16 @@
{
"name": "tailwindcss-language-service",
"version": "0.0.17",
"version": "0.0.20",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.0.17",
"version": "0.0.20",
"dependencies": {
"@ctrl/tinycolor": "3.1.4",
"@types/moo": "0.5.3",
"color-name": "1.1.4",
"css.escape": "1.5.1",
"culori": "0.20.1",
"detect-indent": "6.0.0",
"dlv": "1.1.3",
"dset": "2.0.1",
@ -20,6 +21,7 @@
"postcss-selector-parser": "6.0.2",
"semver": "7.3.2",
"sift-string": "0.0.2",
"stringify-object": "3.3.0",
"vscode-emmet-helper-bundled": "0.0.1",
"vscode-languageclient": "7.0.0",
"vscode-languageserver": "7.0.0",
@ -1350,14 +1352,6 @@
"node": ">=0.1.95"
}
},
"node_modules/@ctrl/tinycolor": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.1.4.tgz",
"integrity": "sha512-WHn6ClDzGS3oACt4F/k0B9QwhQCeXXRguYE6UFe6OD6wLdESU8RoMs7Y1+FEr4Tj2VZd9bfb1aEhnB9KoVrLEA==",
"engines": {
"node": ">=10.19.0"
}
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -1457,12 +1451,6 @@
"node": ">=7.0.0"
}
},
"node_modules/@jest/console/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/@jest/console/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -1572,12 +1560,6 @@
"node": ">=7.0.0"
}
},
"node_modules/@jest/core/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/@jest/core/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -1748,12 +1730,6 @@
"node": ">=7.0.0"
}
},
"node_modules/@jest/reporters/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/@jest/reporters/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -1918,12 +1894,6 @@
"node": ">=7.0.0"
}
},
"node_modules/@jest/transform/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/@jest/transform/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -2009,12 +1979,6 @@
"node": ">=7.0.0"
}
},
"node_modules/@jest/types/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/@jest/types/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -2856,12 +2820,6 @@
"node": ">=7.0.0"
}
},
"node_modules/babel-jest/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/babel-jest/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -3463,12 +3421,6 @@
"node": ">=7.0.0"
}
},
"node_modules/cliui/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/cliui/node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@ -3542,12 +3494,17 @@
"color-name": "1.1.3"
}
},
"node_modules/color-name": {
"node_modules/color-convert/node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
@ -3742,6 +3699,11 @@
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
"dev": true
},
"node_modules/culori": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/culori/-/culori-0.20.1.tgz",
"integrity": "sha512-jNZDmufWx4vCHW2fTb62sarHEeIF3WWrUYIv4ZpoQnN2vQU6IRPz1Ra9QnsHUKzdb5lppSuLsdB72rMmBMAd+A=="
},
"node_modules/damerau-levenshtein": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
@ -4843,12 +4805,6 @@
"node": ">=7.0.0"
}
},
"node_modules/expect/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@ -5209,6 +5165,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-own-enumerable-property-symbols": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g=="
},
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@ -5673,12 +5634,6 @@
"node": ">=7.0.0"
}
},
"node_modules/inquirer/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/inquirer/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -5942,6 +5897,14 @@
"node": ">=0.12.0"
}
},
"node_modules/is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -5987,6 +5950,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
@ -6362,12 +6333,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-cli/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-cli/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6459,12 +6424,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-config/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-config/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6541,12 +6500,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-diff/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-diff/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6636,12 +6589,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-each/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-each/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6858,12 +6805,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-jasmine2/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-jasmine2/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -6953,12 +6894,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-matcher-utils/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-matcher-utils/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7039,12 +6974,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-message-util/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-message-util/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7178,12 +7107,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-resolve/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-resolve/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7325,12 +7248,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-runner/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-runner/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7445,12 +7362,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-runtime/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-runtime/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7559,12 +7470,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-snapshot/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-snapshot/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7651,12 +7556,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-util/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-util/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7744,12 +7643,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-validate/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-validate/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7835,12 +7728,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-watch-typeahead/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-watch-typeahead/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -7931,12 +7818,6 @@
"node": ">=7.0.0"
}
},
"node_modules/jest-watcher/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/jest-watcher/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -9117,12 +8998,6 @@
"node": ">=7.0.0"
}
},
"node_modules/ora/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/ora/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -9556,12 +9431,6 @@
"node": ">=7.0.0"
}
},
"node_modules/pretty-format/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@ -11388,6 +11257,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/stringify-object": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
"integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
"dependencies": {
"get-own-enumerable-property-symbols": "^3.0.0",
"is-obj": "^1.0.1",
"is-regexp": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
@ -11858,12 +11740,6 @@
"node": ">=7.0.0"
}
},
"node_modules/tsdx/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/tsdx/node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -13724,11 +13600,6 @@
"minimist": "^1.2.0"
}
},
"@ctrl/tinycolor": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.1.4.tgz",
"integrity": "sha512-WHn6ClDzGS3oACt4F/k0B9QwhQCeXXRguYE6UFe6OD6wLdESU8RoMs7Y1+FEr4Tj2VZd9bfb1aEhnB9KoVrLEA=="
},
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
@ -13803,12 +13674,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -13896,12 +13761,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -14033,12 +13892,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -14168,12 +14021,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -14237,12 +14084,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -14872,12 +14713,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -15359,12 +15194,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
@ -15422,13 +15251,20 @@
"dev": true,
"requires": {
"color-name": "1.1.3"
},
"dependencies": {
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
}
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"colorette": {
"version": "1.2.2",
@ -15591,6 +15427,11 @@
}
}
},
"culori": {
"version": "0.20.1",
"resolved": "https://registry.npmjs.org/culori/-/culori-0.20.1.tgz",
"integrity": "sha512-jNZDmufWx4vCHW2fTb62sarHEeIF3WWrUYIv4ZpoQnN2vQU6IRPz1Ra9QnsHUKzdb5lppSuLsdB72rMmBMAd+A=="
},
"damerau-levenshtein": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
@ -16437,12 +16278,6 @@
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
}
}
},
@ -16730,6 +16565,11 @@
"has-symbols": "^1.0.1"
}
},
"get-own-enumerable-property-symbols": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g=="
},
"get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@ -17089,12 +16929,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -17282,6 +17116,11 @@
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
@ -17317,6 +17156,11 @@
"has-symbols": "^1.0.1"
}
},
"is-regexp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
"integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk="
},
"is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
@ -17601,12 +17445,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -17679,12 +17517,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -17742,12 +17574,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -17815,12 +17641,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -17990,12 +17810,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18063,12 +17877,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18130,12 +17938,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18220,12 +18022,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18346,12 +18142,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18441,12 +18231,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18530,12 +18314,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18600,12 +18378,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18671,12 +18443,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18743,12 +18509,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -18817,12 +18577,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -19768,12 +19522,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@ -20085,12 +19833,6 @@
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
}
}
},
@ -21578,6 +21320,16 @@
}
}
},
"stringify-object": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
"integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
"requires": {
"get-own-enumerable-property-symbols": "^3.0.0",
"is-obj": "^1.0.1",
"is-regexp": "^1.0.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
@ -21955,12 +21707,6 @@
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "tailwindcss-language-service",
"version": "0.0.17",
"version": "0.0.20",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@ -14,9 +14,10 @@
"prepublishOnly": "npm run build"
},
"dependencies": {
"@ctrl/tinycolor": "3.1.4",
"@types/moo": "0.5.3",
"color-name": "1.1.4",
"css.escape": "1.5.1",
"culori": "0.20.1",
"detect-indent": "6.0.0",
"dlv": "1.1.3",
"dset": "2.0.1",

View File

@ -31,8 +31,8 @@ import { flagEnabled } from './util/flagEnabled'
import { remToPx } from './util/remToPx'
import { createMultiRegexp } from './util/createMultiRegexp'
import * as jit from './util/jit'
import { TinyColor } from '@ctrl/tinycolor'
import { getVariantsFromClassName } from './util/getVariantsFromClassName'
import * as culori from 'culori'
let isUtil = (className) =>
Array.isArray(className.__info)
@ -89,8 +89,8 @@ export function completionsFromClassList(
const color = getColor(state, className)
if (color !== null) {
kind = 16
if (typeof color !== 'string') {
documentation = color.toRgbString().replace(/(^rgba\([^)]+) 0\)$/, '$1 0.001)')
if (typeof color !== 'string' && (color.alpha ?? 1) !== 0) {
documentation = culori.formatRgb(color)
}
}
@ -169,6 +169,34 @@ export function completionsFromClassList(
)
}
if (state.classList) {
return {
isIncomplete: false,
items: items.concat(
state.classList.map(([className, { color }], index) => {
let kind: CompletionItemKind = color ? 16 : 21
let documentation = null
if (color && typeof color !== 'string') {
documentation = culori.formatRgb(color)
}
return {
label: className,
kind,
documentation,
sortText: naturalExpand(index),
data: [...existingVariants, important ? `!${className}` : className],
textEdit: {
newText: className,
range: replacementRange,
},
} as CompletionItem
})
),
}
}
return {
isIncomplete: false,
items: items
@ -188,8 +216,8 @@ export function completionsFromClassList(
const color = getColor(state, className)
if (color !== null) {
kind = 16
if (typeof color !== 'string' && color.a !== 0) {
documentation = color.toRgbString()
if (typeof color !== 'string' && (color.alpha ?? 1) !== 0) {
documentation = culori.formatRgb(color)
}
}
@ -269,8 +297,8 @@ export function completionsFromClassList(
const color = getColor(state, className)
if (color !== null) {
kind = 16
if (typeof color !== 'string' && color.a !== 0) {
documentation = color.toRgbString()
if (typeof color !== 'string' && (color.alpha ?? 1) !== 0) {
documentation = culori.formatRgb(color)
}
}
@ -552,7 +580,10 @@ function provideCssHelperCompletions(
kind: color ? 16 : isObject(obj[item]) ? 9 : 10,
// VS Code bug causes some values to not display in some cases
detail: detail === '0' || detail === 'transparent' ? `${detail} ` : detail,
documentation: color instanceof TinyColor && color.a !== 0 ? color.toRgbString() : null,
documentation:
color && typeof color !== 'string' && (color.alpha ?? 1) !== 0
? culori.formatRgb(color)
: null,
textEdit: {
newText: `${replaceDot ? '[' : ''}${item}${insertClosingBrace ? ']' : ''}`,
range: {
@ -680,6 +711,10 @@ function provideVariantsDirectiveCompletions(
return null
}
if (semver.gte(state.version, '2.99.0')) {
return null
}
let text = document.getText({
start: { line: position.line, character: 0 },
end: position,
@ -831,32 +866,14 @@ function provideCssDirectiveCompletions(
label: '@tailwind',
documentation: {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: `Use the \`@tailwind\` directive to insert Tailwinds \`base\`, \`components\`, \`utilities\` and \`screens\` styles into your CSS.\n\n[Tailwind CSS Documentation](${docsUrl(
value: `Use the \`@tailwind\` directive to insert Tailwinds \`base\`, \`components\`, \`utilities\` and \`${
state.jit && semver.gte(state.version, '2.1.99') ? 'variants' : 'screens'
}\` styles into your CSS.\n\n[Tailwind CSS Documentation](${docsUrl(
state.version,
'functions-and-directives/#tailwind'
)})`,
},
},
{
label: '@variants',
documentation: {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: `You can generate \`responsive\`, \`hover\`, \`focus\`, \`active\`, and \`group-hover\` versions of your own utilities by wrapping their definitions in the \`@variants\` directive.\n\n[Tailwind CSS Documentation](${docsUrl(
state.version,
'functions-and-directives/#variants'
)})`,
},
},
{
label: '@responsive',
documentation: {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: `You can generate responsive variants of your own classes by wrapping their definitions in the \`@responsive\` directive.\n\n[Tailwind CSS Documentation](${docsUrl(
state.version,
'functions-and-directives/#responsive'
)})`,
},
},
{
label: '@screen',
documentation: {
@ -891,6 +908,30 @@ function provideCssDirectiveCompletions(
},
]
: []),
...(semver.gte(state.version, '2.99.0')
? []
: [
{
label: '@variants',
documentation: {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: `You can generate \`responsive\`, \`hover\`, \`focus\`, \`active\`, and other variants of your own utilities by wrapping their definitions in the \`@variants\` directive.\n\n[Tailwind CSS Documentation](${docsUrl(
state.version,
'functions-and-directives/#variants'
)})`,
},
},
{
label: '@responsive',
documentation: {
kind: 'markdown' as typeof MarkupKind.Markdown,
value: `You can generate responsive variants of your own classes by wrapping their definitions in the \`@responsive\` directive.\n\n[Tailwind CSS Documentation](${docsUrl(
state.version,
'functions-and-directives/#responsive'
)})`,
},
},
]),
]
return {

View File

@ -27,6 +27,8 @@ export function getInvalidTailwindDirectiveDiagnostics(
ranges.push(...boundaries.css)
}
let hasVariantsDirective = state.jit && semver.gte(state.version, '2.1.99')
ranges.forEach((range) => {
let text = document.getText(range)
let matches = findAll(/(?:\s|^)@tailwind\s+(?<value>[^;]+)/g, text)
@ -34,9 +36,17 @@ export function getInvalidTailwindDirectiveDiagnostics(
let valid = [
'utilities',
'components',
state.jit && semver.gte(state.version, '2.1.99') ? 'variants' : 'screens',
'screens',
semver.gte(state.version, '1.0.0-beta.1') ? 'base' : 'preflight',
]
hasVariantsDirective && 'variants',
].filter(Boolean)
let suggestable = valid
if (hasVariantsDirective) {
// Don't suggest `screens`, because it's deprecated
suggestable = suggestable.filter((value) => value !== 'screens')
}
matches.forEach((match) => {
if (valid.includes(match.groups.value)) {
@ -49,11 +59,8 @@ export function getInvalidTailwindDirectiveDiagnostics(
if (match.groups.value === 'preflight') {
suggestions.push('base')
message += ` Did you mean 'base'?`
} else if (match.groups.value === 'screens') {
suggestions.push('variants')
message += ` Did you mean 'variants'?`
} else {
let suggestion = closest(match.groups.value, valid)
let suggestion = closest(match.groups.value, suggestable)
if (suggestion) {
suggestions.push(suggestion)
message += ` Did you mean '${suggestion}'?`

View File

@ -6,7 +6,7 @@ import { getLanguageBoundaries } from '../util/getLanguageBoundaries'
import { findAll, indexToPosition } from '../util/find'
import { closest } from '../util/closest'
import { absoluteRange } from '../util/absoluteRange'
import dlv from 'dlv'
import semver from 'semver'
export function getInvalidVariantDiagnostics(
state: State,
@ -16,6 +16,10 @@ export function getInvalidVariantDiagnostics(
let severity = settings.tailwindCSS.lint.invalidVariant
if (severity === 'ignore') return []
if (semver.gte(state.version, '2.99.0')) {
return []
}
let diagnostics: InvalidVariantDiagnostic[] = []
let ranges: Range[] = []

View File

@ -4,10 +4,9 @@ import {
getClassNamesInClassList,
findHelperFunctionsInDocument,
} from './util/find'
import { getColor, getColorFromValue, tinyColorToVscodeColor } from './util/color'
import { getColor, getColorFromValue, culoriColorToVscodeColor } from './util/color'
import { stringToPath } from './util/stringToPath'
import type { TextDocument, ColorInformation } from 'vscode-languageserver'
import { TinyColor } from '@ctrl/tinycolor'
import dlv from 'dlv'
export async function getDocumentColors(
@ -25,12 +24,12 @@ export async function getDocumentColors(
let classNames = getClassNamesInClassList(classList)
classNames.forEach((className) => {
let color = getColor(state, className.className)
if (color === null || typeof color === 'string' || color.a === 0) {
if (color === null || typeof color === 'string' || (color.alpha ?? 1) === 0) {
return
}
colors.push({
range: className.range,
color: tinyColorToVscodeColor(color),
color: culoriColorToVscodeColor(color),
})
})
})
@ -41,8 +40,8 @@ export async function getDocumentColors(
let base = fn.helper === 'theme' ? ['theme'] : []
let value = dlv(state.config, [...base, ...keys])
let color = getColorFromValue(value)
if (color instanceof TinyColor && color.a !== 0) {
colors.push({ range: fn.valueRange, color: tinyColorToVscodeColor(color) })
if (color && typeof color !== 'string' && (color.alpha ?? 1) !== 0) {
colors.push({ range: fn.valueRange, color: culoriColorToVscodeColor(color) })
}
})

View File

@ -1,11 +1,8 @@
export {
doComplete,
resolveCompletionItem,
completionsFromClassList,
} from './completionProvider'
export { doComplete, resolveCompletionItem, completionsFromClassList } from './completionProvider'
export { doValidate } from './diagnostics/diagnosticsProvider'
export { doHover } from './hoverProvider'
export { doCodeActions } from './codeActions/codeActionProvider'
export { getDocumentColors } from './documentColorProvider'
export * from './util/state'
export * from './diagnostics/types'
export * from './util/color'

View File

@ -1,11 +1,12 @@
const dlv = require('dlv')
import { State } from './state'
import removeMeta from './removeMeta'
import { TinyColor, names as colorNames } from '@ctrl/tinycolor'
import { ensureArray, dedupe, flatten } from './array'
import type { Color } from 'vscode-languageserver'
import { getClassNameParts } from './getClassNameAtPosition'
import * as jit from './jit'
import * as culori from 'culori'
import namedColors from 'color-name'
const COLOR_PROPS = [
'caret-color',
@ -24,7 +25,7 @@ const COLOR_PROPS = [
'text-decoration-color',
]
type KeywordColor = 'transparent' | 'currentColor'
export type KeywordColor = 'transparent' | 'currentColor'
function getKeywordColor(value: unknown): KeywordColor | null {
if (typeof value !== 'string') return null
@ -40,13 +41,13 @@ function getKeywordColor(value: unknown): KeywordColor | null {
// https://github.com/khalilgharbaoui/coloregex
const colorRegex = new RegExp(
`(?:^|\\s|,)(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\\((-?[\\d.]+%?[,\\s]+){2,3}\\s*([\\d.]+%?|var\\([^)]+\\))?\\)|transparent|currentColor|${Object.keys(
colorNames
`(?:^|\\s|,)(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\\((-?[\\d.]+%?(\\s*[,/]\\s*|\\s+)+){2,3}\\s*([\\d.]+%?|var\\([^)]+\\))?\\)|transparent|currentColor|${Object.keys(
namedColors
).join('|')})(?:$|\\s|,)`,
'gi'
)
function getColorsInString(str: string): (TinyColor | KeywordColor)[] {
function getColorsInString(str: string): (culori.Color | KeywordColor)[] {
if (/(?:box|drop)-shadow/.test(str)) return []
return (
@ -58,14 +59,14 @@ function getColorsInString(str: string): (TinyColor | KeywordColor)[] {
.replace(/^,|,$/g, '')
.replace(/var\([^)]+\)/, '1')
)
.map((color) => getKeywordColor(color) ?? new TinyColor(color))
.filter((color) => (color instanceof TinyColor ? color.isValid : true)) ?? []
.map((color) => getKeywordColor(color) ?? culori.parse(color))
.filter(Boolean) ?? []
)
}
function getColorFromDecls(
decls: Record<string, string | string[]>
): TinyColor | KeywordColor | null {
): culori.Color | KeywordColor | null {
let props = Object.keys(decls).filter((prop) => {
// ignore content: "";
if (prop === 'content' && (decls[prop] === '""' || decls[prop] === "''")) {
@ -96,7 +97,9 @@ function getColorFromDecls(
// check that all of the values are the same color, ignoring alpha
const colorStrings = dedupe(
colors.map((color) => (color instanceof TinyColor ? `${color.r}-${color.g}-${color.b}` : color))
colors.map((color) =>
typeof color === 'string' ? color : culori.formatRgb({ ...color, alpha: undefined })
)
)
if (colorStrings.length !== 1) {
return null
@ -107,30 +110,35 @@ function getColorFromDecls(
return keyword
}
const nonKeywordColors = colors.filter((color): color is TinyColor => typeof color !== 'string')
const nonKeywordColors = colors.filter(
(color): color is culori.Color => typeof color !== 'string'
)
const alphas = dedupe(nonKeywordColors.map((color) => color.a))
const alphas = dedupe(nonKeywordColors.map((color) => color.alpha ?? 1))
if (alphas.length === 1) {
return nonKeywordColors[0]
}
if (alphas.length === 2 && alphas.includes(0)) {
return nonKeywordColors.find((color) => color.a !== 0)
return nonKeywordColors.find((color) => (color.alpha ?? 1) !== 0)
}
return null
}
export function getColor(state: State, className: string): TinyColor | KeywordColor | null {
export function getColor(state: State, className: string): culori.Color | KeywordColor | null {
if (state.jit) {
const item = dlv(state.classNames.classNames, [className, '__info'])
if (item && item.__rule) {
return getColorFromDecls(removeMeta(item))
if (state.classNames) {
const item = dlv(state.classNames.classNames, [className, '__info'])
if (item && item.__rule) {
return getColorFromDecls(removeMeta(item))
}
}
let { root, rules } = jit.generateRules(state, [className])
if (rules.length === 0) return null
let decls: Record<string, string | string[]> = {}
root.walkDecls((decl) => {
let value = decls[decl.prop]
@ -156,7 +164,7 @@ export function getColor(state: State, className: string): TinyColor | KeywordCo
return getColorFromDecls(removeMeta(item))
}
export function getColorFromValue(value: unknown): TinyColor | KeywordColor | null {
export function getColorFromValue(value: unknown): culori.Color | KeywordColor | null {
if (typeof value !== 'string') return null
const trimmedValue = value.trim()
if (trimmedValue.toLowerCase() === 'transparent') {
@ -168,41 +176,17 @@ export function getColorFromValue(value: unknown): TinyColor | KeywordColor | nu
if (
!/^\s*(?:rgba?|hsla?)\s*\([^)]+\)\s*$/.test(trimmedValue) &&
!/^\s*#[0-9a-f]+\s*$/i.test(trimmedValue) &&
!Object.keys(colorNames).includes(trimmedValue)
!Object.keys(namedColors).includes(trimmedValue)
) {
return null
}
const color = new TinyColor(trimmedValue)
if (color.isValid) {
return color
// return { red: color.r / 255, green: color.g / 255, blue: color.b / 255, alpha: color.a }
}
return null
const color = culori.parse(trimmedValue)
return color ?? null
}
function createColor(str: string): TinyColor | KeywordColor {
let keyword = getKeywordColor(str)
if (keyword) {
return keyword
}
let toRgb = culori.converter('rgb')
// matches: rgba(<r>, <g>, <b>, var(--bg-opacity))
// TODO: support other formats? e.g. hsla, css level 4
const match = str.match(
/^\s*rgba\(\s*(?<r>[0-9.]+)\s*,\s*(?<g>[0-9.]+)\s*,\s*(?<b>[0-9.]+)\s*,\s*var/
)
if (match) {
return new TinyColor({
r: match.groups.r,
g: match.groups.g,
b: match.groups.b,
})
}
return new TinyColor(str)
}
export function tinyColorToVscodeColor(color: TinyColor): Color {
return { red: color.r / 255, green: color.g / 255, blue: color.b / 255, alpha: color.a }
export function culoriColorToVscodeColor(color: culori.Color): Color {
let rgb = toRgb(color)
return { red: rgb.r, green: rgb.g, blue: rgb.b, alpha: rgb.alpha ?? 1 }
}

View File

@ -1,6 +1,8 @@
import type { TextDocuments, Connection, Range, SymbolInformation } from 'vscode-languageserver'
import type { TextDocument } from 'vscode-languageserver-textdocument'
import type { Postcss } from 'postcss'
import { KeywordColor } from './color'
import * as culori from 'culori'
export type ClassNamesTree = {
[key: string]: ClassNamesTree
@ -90,6 +92,7 @@ export interface State {
editor?: EditorState
jit?: boolean
jitContext?: any
classList?: Array<[string, { color: culori.Color | KeywordColor | null }]>
// postcssPlugins?: { before: any[]; after: any[] }
}

View File

@ -1,5 +1,5 @@
{
"include": ["src", "types"],
"include": ["src", "../../types"],
"compilerOptions": {
"module": "esnext",
"lib": ["dom", "esnext"],

View File

@ -207,9 +207,9 @@
"test": "jest"
},
"devDependencies": {
"@ctrl/tinycolor": "3.1.4",
"@types/vscode": "1.52.0",
"@vercel/ncc": "0.28.4",
"color-name": "1.1.4",
"glob-exec": "0.1.1",
"rimraf": "3.0.2",
"terser": "4.6.12",

View File

@ -30,7 +30,7 @@ import {
import { languages as defaultLanguages } from 'tailwindcss-language-service/src/util/languages'
import isObject from 'tailwindcss-language-service/src/util/isObject'
import { dedupe, equal } from 'tailwindcss-language-service/src/util/array'
import { names as namedColors } from '@ctrl/tinycolor'
import namedColors from 'color-name'
const colorNames = Object.keys(namedColors)

28
types/culori.d.ts vendored 100644
View File

@ -0,0 +1,28 @@
declare module 'culori' {
export interface RgbColor {
mode: 'rgb'
r: number
g: number
b: number
alpha?: number
}
export interface HslColor {
mode: 'hsl'
h: number
s: number
b: number
alpha?: number
}
export type Color = RgbColor | HslColor
export function parse(color: string): Color | undefined
export function formatRgb(color: Color | string): string
export function formatHsl(color: Color | string): string
export function formatHex(color: Color | string): string
export function formatHex8(color: Color | string): string
type Mode = 'rgb' | 'hsl'
export function converter<T extends Mode>(
mode: T
): (color: Color | string) => T extends 'rgb' ? RgbColor : T extends 'hsl' ? HslColor : never
}