fix error when using @​apply in plugins (#255)

master
Brad Cornes 2021-01-29 16:37:39 +00:00
parent 09e96ed598
commit c7a1632250
5 changed files with 200 additions and 115 deletions

35
package-lock.json generated
View File

@ -6295,6 +6295,14 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
"engines": {
"node": ">= 8"
}
},
"node_modules/language-subtag-registry": { "node_modules/language-subtag-registry": {
"version": "0.3.20", "version": "0.3.20",
"license": "ODC-By-1.0" "license": "ODC-By-1.0"
@ -12158,7 +12166,7 @@
}, },
"packages/tailwindcss-intellisense": { "packages/tailwindcss-intellisense": {
"name": "vscode-tailwindcss", "name": "vscode-tailwindcss",
"version": "0.5.6", "version": "0.5.7",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/debounce": "^1.2.0", "@types/debounce": "^1.2.0",
@ -12179,6 +12187,7 @@
"glob-exec": "^0.1.1", "glob-exec": "^0.1.1",
"import-from": "^3.0.0", "import-from": "^3.0.0",
"jest": "^25.5.4", "jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0", "mitt": "^1.2.0",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"pkg-up": "^3.1.0", "pkg-up": "^3.1.0",
@ -12188,7 +12197,7 @@
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"semver": "^7.3.2", "semver": "^7.3.2",
"stack-trace": "0.0.10", "stack-trace": "0.0.10",
"tailwindcss-language-service": "0.0.10", "tailwindcss-language-service": "0.0.11",
"terser": "^4.6.12", "terser": "^4.6.12",
"tiny-invariant": "^1.1.0", "tiny-invariant": "^1.1.0",
"tslint": "^5.16.0", "tslint": "^5.16.0",
@ -12262,9 +12271,9 @@
} }
}, },
"packages/tailwindcss-intellisense/node_modules/tailwindcss-language-service": { "packages/tailwindcss-intellisense/node_modules/tailwindcss-language-service": {
"version": "0.0.10", "version": "0.0.11",
"resolved": "https://registry.npmjs.org/tailwindcss-language-service/-/tailwindcss-language-service-0.0.10.tgz", "resolved": "https://registry.npmjs.org/tailwindcss-language-service/-/tailwindcss-language-service-0.0.11.tgz",
"integrity": "sha512-qE2blv1x8wxSUN+PH1kjvN28UjNKhrZeZcAFHL4X35jtTbGZ2X//b1Ya+NOK5hLOFWinHPxR9PB/WeNuOSn/sQ==", "integrity": "sha512-dIOvB4CveOkz6DPYz0lqMbQHz4pEBiuTQcBMi86e+xoyW6OwosEj3k3ds6+pwra+ZN4SScxHdru63bGjWM5fiQ==",
"dependencies": { "dependencies": {
"@ctrl/tinycolor": "^3.1.4", "@ctrl/tinycolor": "^3.1.4",
"@types/moo": "^0.5.3", "@types/moo": "^0.5.3",
@ -12304,7 +12313,7 @@
} }
}, },
"packages/tailwindcss-language-service": { "packages/tailwindcss-language-service": {
"version": "0.0.10", "version": "0.0.11",
"dependencies": { "dependencies": {
"@ctrl/tinycolor": "^3.1.4", "@ctrl/tinycolor": "^3.1.4",
"@types/moo": "^0.5.3", "@types/moo": "^0.5.3",
@ -16490,6 +16499,11 @@
"kleur": { "kleur": {
"version": "3.0.3" "version": "3.0.3"
}, },
"klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA=="
},
"language-subtag-registry": { "language-subtag-registry": {
"version": "0.3.20" "version": "0.3.20"
}, },
@ -20269,6 +20283,7 @@
"glob-exec": "^0.1.1", "glob-exec": "^0.1.1",
"import-from": "^3.0.0", "import-from": "^3.0.0",
"jest": "^25.5.4", "jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0", "mitt": "^1.2.0",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"pkg-up": "^3.1.0", "pkg-up": "^3.1.0",
@ -20278,7 +20293,7 @@
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"semver": "^7.3.2", "semver": "^7.3.2",
"stack-trace": "0.0.10", "stack-trace": "0.0.10",
"tailwindcss-language-service": "0.0.10", "tailwindcss-language-service": "0.0.11",
"terser": "^4.6.12", "terser": "^4.6.12",
"tiny-invariant": "^1.1.0", "tiny-invariant": "^1.1.0",
"tslint": "^5.16.0", "tslint": "^5.16.0",
@ -20325,9 +20340,9 @@
} }
}, },
"tailwindcss-language-service": { "tailwindcss-language-service": {
"version": "0.0.10", "version": "0.0.11",
"resolved": "https://registry.npmjs.org/tailwindcss-language-service/-/tailwindcss-language-service-0.0.10.tgz", "resolved": "https://registry.npmjs.org/tailwindcss-language-service/-/tailwindcss-language-service-0.0.11.tgz",
"integrity": "sha512-qE2blv1x8wxSUN+PH1kjvN28UjNKhrZeZcAFHL4X35jtTbGZ2X//b1Ya+NOK5hLOFWinHPxR9PB/WeNuOSn/sQ==", "integrity": "sha512-dIOvB4CveOkz6DPYz0lqMbQHz4pEBiuTQcBMi86e+xoyW6OwosEj3k3ds6+pwra+ZN4SScxHdru63bGjWM5fiQ==",
"requires": { "requires": {
"@ctrl/tinycolor": "^3.1.4", "@ctrl/tinycolor": "^3.1.4",
"@types/moo": "^0.5.3", "@types/moo": "^0.5.3",

View File

@ -27,6 +27,7 @@
"glob-exec": "^0.1.1", "glob-exec": "^0.1.1",
"import-from": "^3.0.0", "import-from": "^3.0.0",
"jest": "^25.5.4", "jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0", "mitt": "^1.2.0",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"pkg-up": "^3.1.0", "pkg-up": "^3.1.0",
@ -7107,6 +7108,14 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
"engines": {
"node": ">= 8"
}
},
"node_modules/language-subtag-registry": { "node_modules/language-subtag-registry": {
"version": "0.3.21", "version": "0.3.21",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz",
@ -19307,6 +19316,11 @@
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="
}, },
"klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA=="
},
"language-subtag-registry": { "language-subtag-registry": {
"version": "0.3.21", "version": "0.3.21",
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz",

View File

@ -197,6 +197,7 @@
"glob-exec": "^0.1.1", "glob-exec": "^0.1.1",
"import-from": "^3.0.0", "import-from": "^3.0.0",
"jest": "^25.5.4", "jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0", "mitt": "^1.2.0",
"normalize-path": "^3.0.0", "normalize-path": "^3.0.0",
"pkg-up": "^3.1.0", "pkg-up": "^3.1.0",

View File

@ -44,93 +44,100 @@ function getClassNamesFromSelector(selector) {
return classNames return classNames
} }
async function process(groups) { async function process(root) {
const tree = {} const tree = {}
const commonContext = {} const commonContext = {}
groups.forEach((group) => { let layer
group.root.walkRules((rule) => {
const classNames = getClassNamesFromSelector(rule.selector)
const decls = {} root.walk((node) => {
rule.walkDecls((decl) => { if (node.type === 'comment') {
if (decls[decl.prop]) { let match = node.text.trim().match(/^__tw_intellisense_layer_([a-z]+)__$/)
decls[decl.prop] = [ if (match === null) return
...(Array.isArray(decls[decl.prop]) layer = match[1]
? decls[decl.prop] node.remove()
: [decls[decl.prop]]), return
decl.value, }
]
} else {
decls[decl.prop] = decl.value
}
})
let p = rule if (node.type !== 'rule') return
const keys = []
while (p.parent.type !== 'root') {
p = p.parent
if (p.type === 'atrule') {
keys.push(`@${p.name} ${p.params}`)
}
}
for (let i = 0; i < classNames.length; i++) { const rule = node
const context = keys.concat([]) const classNames = getClassNamesFromSelector(rule.selector)
const baseKeys = classNames[i].className.split('__TAILWIND_SEPARATOR__')
const contextKeys = baseKeys.slice(0, baseKeys.length - 1)
const index = []
const existing = dlv(tree, [...baseKeys, '__info']) const decls = {}
if (typeof existing !== 'undefined') { rule.walkDecls((decl) => {
if (Array.isArray(existing)) { if (decls[decl.prop]) {
index.push(existing.length) decls[decl.prop] = [
} else { ...(Array.isArray(decls[decl.prop])
dset(tree, [...baseKeys, '__info'], [existing]) ? decls[decl.prop]
index.push(1) : [decls[decl.prop]]),
} decl.value,
} ]
if (classNames[i].__rule) { } else {
dset(tree, [...baseKeys, '__info', ...index, '__rule'], true) decls[decl.prop] = decl.value
dset(
tree,
[...baseKeys, '__info', ...index, '__source'],
group.source
)
dsetEach(tree, [...baseKeys, '__info', ...index], decls)
}
dset(
tree,
[...baseKeys, '__info', ...index, '__pseudo'],
classNames[i].__pseudo
)
dset(
tree,
[...baseKeys, '__info', ...index, '__scope'],
classNames[i].scope
)
dset(
tree,
[...baseKeys, '__info', ...index, '__context'],
context.concat([]).reverse()
)
// common context
context.push(...classNames[i].__pseudo.map((x) => `&${x}`))
for (let i = 0; i < contextKeys.length; i++) {
if (typeof commonContext[contextKeys[i]] === 'undefined') {
commonContext[contextKeys[i]] = context
} else {
commonContext[contextKeys[i]] = intersection(
commonContext[contextKeys[i]],
context
)
}
}
} }
}) })
let p = rule
const keys = []
while (p.parent.type !== 'root') {
p = p.parent
if (p.type === 'atrule') {
keys.push(`@${p.name} ${p.params}`)
}
}
for (let i = 0; i < classNames.length; i++) {
const context = keys.concat([])
const baseKeys = classNames[i].className.split(/__TWSEP__.*?__TWSEP__/)
const contextKeys = baseKeys.slice(0, baseKeys.length - 1)
const index = []
const existing = dlv(tree, [...baseKeys, '__info'])
if (typeof existing !== 'undefined') {
if (Array.isArray(existing)) {
index.push(existing.length)
} else {
dset(tree, [...baseKeys, '__info'], [existing])
index.push(1)
}
}
if (classNames[i].__rule) {
dset(tree, [...baseKeys, '__info', ...index, '__rule'], true)
dset(tree, [...baseKeys, '__info', ...index, '__source'], layer)
dsetEach(tree, [...baseKeys, '__info', ...index], decls)
}
dset(
tree,
[...baseKeys, '__info', ...index, '__pseudo'],
classNames[i].__pseudo
)
dset(
tree,
[...baseKeys, '__info', ...index, '__scope'],
classNames[i].scope
)
dset(
tree,
[...baseKeys, '__info', ...index, '__context'],
context.concat([]).reverse()
)
// common context
context.push(...classNames[i].__pseudo.map((x) => `&${x}`))
for (let i = 0; i < contextKeys.length; i++) {
if (typeof commonContext[contextKeys[i]] === 'undefined') {
commonContext[contextKeys[i]] = context
} else {
commonContext[contextKeys[i]] = intersection(
commonContext[contextKeys[i]],
context
)
}
}
}
}) })
return { classNames: tree, context: commonContext } return { classNames: tree, context: commonContext }

View File

@ -16,6 +16,7 @@ import glob from 'fast-glob'
import normalizePath from 'normalize-path' import normalizePath from 'normalize-path'
import { withUserEnvironment } from './environment' import { withUserEnvironment } from './environment'
import execa from 'execa' import execa from 'execa'
import { klona } from 'klona/full'
function arraysEqual(arr1, arr2) { function arraysEqual(arr1, arr2) {
return ( return (
@ -71,7 +72,13 @@ export default async function getClassNames(
let hook = Hook(fs.realpathSync(configPath), (exports) => { let hook = Hook(fs.realpathSync(configPath), (exports) => {
userSeperator = dlv(exports, sepLocation) userSeperator = dlv(exports, sepLocation)
userPurge = exports.purge userPurge = exports.purge
dset(exports, sepLocation, '__TAILWIND_SEPARATOR__') dset(
exports,
sepLocation,
`__TWSEP__${
typeof userSeperator === 'undefined' ? ':' : userSeperator
}__TWSEP__`
)
exports.purge = {} exports.purge = {}
return exports return exports
}) })
@ -89,15 +96,17 @@ export default async function getClassNames(
hook.unwatch() hook.unwatch()
const { const {
base, postcssResult,
components,
utilities,
resolvedConfig, resolvedConfig,
browserslist, browserslist,
postcss, postcss,
} = await withPackages( } = await withPackages(
configDir, {
cwd, configDir,
cwd,
userSeperator,
version,
},
async ({ async ({
postcss, postcss,
tailwindcss, tailwindcss,
@ -106,19 +115,17 @@ export default async function getClassNames(
}) => { }) => {
let postcssResult let postcssResult
try { try {
postcssResult = await Promise.all( postcssResult = await postcss([tailwindcss(configPath)]).process(
[ [
semver.gte(version, '0.99.0') ? 'base' : 'preflight', semver.gte(version, '0.99.0') ? 'base' : 'preflight',
'components', 'components',
'utilities', 'utilities',
].map((group) => ]
postcss([tailwindcss(configPath)]).process( .map((x) => `/*__tw_intellisense_layer_${x}__*/\n@tailwind ${x};`)
`@tailwind ${group};`, .join('\n'),
{ {
from: undefined, from: undefined,
} }
)
)
) )
} catch (error) { } catch (error) {
throw error throw error
@ -126,8 +133,6 @@ export default async function getClassNames(
hook.unhook() hook.unhook()
} }
const [base, components, utilities] = postcssResult
if (typeof userSeperator !== 'undefined') { if (typeof userSeperator !== 'undefined') {
dset(config, sepLocation, userSeperator) dset(config, sepLocation, userSeperator)
} else { } else {
@ -168,9 +173,7 @@ export default async function getClassNames(
} }
return { return {
base, postcssResult,
components,
utilities,
resolvedConfig, resolvedConfig,
postcss, postcss,
browserslist, browserslist,
@ -183,11 +186,7 @@ export default async function getClassNames(
configPath, configPath,
config: resolvedConfig, config: resolvedConfig,
separator: typeof userSeperator === 'undefined' ? ':' : userSeperator, separator: typeof userSeperator === 'undefined' ? ':' : userSeperator,
classNames: await extractClassNames([ classNames: await extractClassNames(postcssResult.root),
{ root: base.root, source: 'base' },
{ root: components.root, source: 'components' },
{ root: utilities.root, source: 'utilities' },
]),
dependencies: hook.deps, dependencies: hook.deps,
plugins: getPlugins(config), plugins: getPlugins(config),
variants: getVariants({ config, version, postcss, browserslist }), variants: getVariants({ config, version, postcss, browserslist }),
@ -262,10 +261,10 @@ function loadMeta(configDir, root) {
}) })
} }
function withPackages(configDir, root, cb) { function withPackages({ configDir, cwd, userSeperator, version }, cb) {
return withUserEnvironment( return withUserEnvironment(
configDir, configDir,
root, cwd,
async ({ isPnp, require, resolve }) => { async ({ isPnp, require, resolve }) => {
const tailwindBase = path.dirname(resolve('tailwindcss/package.json')) const tailwindBase = path.dirname(resolve('tailwindcss/package.json'))
const postcss = require('postcss', tailwindBase) const postcss = require('postcss', tailwindBase)
@ -290,6 +289,55 @@ function withPackages(configDir, root, cb) {
} }
} catch (_) {} } catch (_) {}
if (semver.gte(version, '1.7.0')) {
const applyComplexClasses = semver.gte(version, '1.99.0')
? require('./lib/lib/substituteClassApplyAtRules', tailwindBase)
: require('./lib/flagged/applyComplexClasses', tailwindBase)
if (!applyComplexClasses.default.__patched) {
let _applyComplexClasses = applyComplexClasses.default
applyComplexClasses.default = (config, ...args) => {
let configClone = klona(config)
configClone.separator =
typeof userSeperator === 'undefined' ? ':' : userSeperator
let fn = _applyComplexClasses(configClone, ...args)
return async (css) => {
css.walkRules((rule) => {
const newSelector = rule.selector.replace(
/__TWSEP__(.*?)__TWSEP__/g,
'$1'
)
if (newSelector !== rule.selector) {
rule.before(
postcss.comment({
text: '__ORIGINAL_SELECTOR__:' + rule.selector,
})
)
rule.selector = newSelector
}
})
await fn(css)
css.walkComments((comment) => {
if (comment.text.startsWith('__ORIGINAL_SELECTOR__:')) {
comment.next().selector = comment.text.replace(
/^__ORIGINAL_SELECTOR__:/,
''
)
comment.remove()
}
})
return css
}
}
applyComplexClasses.default.__patched = true
}
}
return cb({ postcss, tailwindcss, browserslistCommand, browserslistArgs }) return cb({ postcss, tailwindcss, browserslistCommand, browserslistArgs })
} }
) )