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

View File

@ -27,6 +27,7 @@
"glob-exec": "^0.1.1",
"import-from": "^3.0.0",
"jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0",
"normalize-path": "^3.0.0",
"pkg-up": "^3.1.0",
@ -7107,6 +7108,14 @@
"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": {
"version": "0.3.21",
"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",
"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": {
"version": "0.3.21",
"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",
"import-from": "^3.0.0",
"jest": "^25.5.4",
"klona": "^2.0.4",
"mitt": "^1.2.0",
"normalize-path": "^3.0.0",
"pkg-up": "^3.1.0",

View File

@ -44,93 +44,100 @@ function getClassNamesFromSelector(selector) {
return classNames
}
async function process(groups) {
async function process(root) {
const tree = {}
const commonContext = {}
groups.forEach((group) => {
group.root.walkRules((rule) => {
const classNames = getClassNamesFromSelector(rule.selector)
let layer
const decls = {}
rule.walkDecls((decl) => {
if (decls[decl.prop]) {
decls[decl.prop] = [
...(Array.isArray(decls[decl.prop])
? decls[decl.prop]
: [decls[decl.prop]]),
decl.value,
]
} else {
decls[decl.prop] = decl.value
}
})
root.walk((node) => {
if (node.type === 'comment') {
let match = node.text.trim().match(/^__tw_intellisense_layer_([a-z]+)__$/)
if (match === null) return
layer = match[1]
node.remove()
return
}
let p = rule
const keys = []
while (p.parent.type !== 'root') {
p = p.parent
if (p.type === 'atrule') {
keys.push(`@${p.name} ${p.params}`)
}
}
if (node.type !== 'rule') return
for (let i = 0; i < classNames.length; i++) {
const context = keys.concat([])
const baseKeys = classNames[i].className.split('__TAILWIND_SEPARATOR__')
const contextKeys = baseKeys.slice(0, baseKeys.length - 1)
const index = []
const rule = node
const classNames = getClassNamesFromSelector(rule.selector)
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'],
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
)
}
}
const decls = {}
rule.walkDecls((decl) => {
if (decls[decl.prop]) {
decls[decl.prop] = [
...(Array.isArray(decls[decl.prop])
? decls[decl.prop]
: [decls[decl.prop]]),
decl.value,
]
} else {
decls[decl.prop] = decl.value
}
})
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 }

View File

@ -16,6 +16,7 @@ import glob from 'fast-glob'
import normalizePath from 'normalize-path'
import { withUserEnvironment } from './environment'
import execa from 'execa'
import { klona } from 'klona/full'
function arraysEqual(arr1, arr2) {
return (
@ -71,7 +72,13 @@ export default async function getClassNames(
let hook = Hook(fs.realpathSync(configPath), (exports) => {
userSeperator = dlv(exports, sepLocation)
userPurge = exports.purge
dset(exports, sepLocation, '__TAILWIND_SEPARATOR__')
dset(
exports,
sepLocation,
`__TWSEP__${
typeof userSeperator === 'undefined' ? ':' : userSeperator
}__TWSEP__`
)
exports.purge = {}
return exports
})
@ -89,15 +96,17 @@ export default async function getClassNames(
hook.unwatch()
const {
base,
components,
utilities,
postcssResult,
resolvedConfig,
browserslist,
postcss,
} = await withPackages(
configDir,
cwd,
{
configDir,
cwd,
userSeperator,
version,
},
async ({
postcss,
tailwindcss,
@ -106,19 +115,17 @@ export default async function getClassNames(
}) => {
let postcssResult
try {
postcssResult = await Promise.all(
postcssResult = await postcss([tailwindcss(configPath)]).process(
[
semver.gte(version, '0.99.0') ? 'base' : 'preflight',
'components',
'utilities',
].map((group) =>
postcss([tailwindcss(configPath)]).process(
`@tailwind ${group};`,
{
from: undefined,
}
)
)
]
.map((x) => `/*__tw_intellisense_layer_${x}__*/\n@tailwind ${x};`)
.join('\n'),
{
from: undefined,
}
)
} catch (error) {
throw error
@ -126,8 +133,6 @@ export default async function getClassNames(
hook.unhook()
}
const [base, components, utilities] = postcssResult
if (typeof userSeperator !== 'undefined') {
dset(config, sepLocation, userSeperator)
} else {
@ -168,9 +173,7 @@ export default async function getClassNames(
}
return {
base,
components,
utilities,
postcssResult,
resolvedConfig,
postcss,
browserslist,
@ -183,11 +186,7 @@ export default async function getClassNames(
configPath,
config: resolvedConfig,
separator: typeof userSeperator === 'undefined' ? ':' : userSeperator,
classNames: await extractClassNames([
{ root: base.root, source: 'base' },
{ root: components.root, source: 'components' },
{ root: utilities.root, source: 'utilities' },
]),
classNames: await extractClassNames(postcssResult.root),
dependencies: hook.deps,
plugins: getPlugins(config),
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(
configDir,
root,
cwd,
async ({ isPnp, require, resolve }) => {
const tailwindBase = path.dirname(resolve('tailwindcss/package.json'))
const postcss = require('postcss', tailwindBase)
@ -290,6 +289,55 @@ function withPackages(configDir, root, cb) {
}
} 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 })
}
)