tailwindcss-patch 9.0.0-alpha.1 → 9.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/{chunk-Z6OMJZTU.js → chunk-77GHKSKG.js} +59 -732
- package/dist/{chunk-SWLOK2S6.mjs → chunk-D6ICWMM4.mjs} +63 -736
- package/dist/chunk-PMN7HS4Y.js +25 -0
- package/dist/chunk-YYBY7EM5.mjs +21 -0
- package/dist/cli.js +7 -5
- package/dist/cli.mjs +5 -3
- package/dist/commands/cli-runtime.d.mts +13 -0
- package/dist/commands/cli-runtime.d.ts +13 -0
- package/dist/commands/cli-runtime.js +1331 -0
- package/dist/commands/cli-runtime.mjs +1331 -0
- package/dist/index.d.mts +17 -677
- package/dist/index.d.ts +17 -677
- package/dist/index.js +5 -7
- package/dist/index.mjs +6 -8
- package/dist/validate-nbmOI2w8.d.mts +677 -0
- package/dist/validate-nbmOI2w8.d.ts +677 -0
- package/package.json +11 -3
- package/src/api/tailwindcss-patcher.ts +424 -0
- package/src/babel/index.ts +12 -0
- package/src/cache/context.ts +212 -0
- package/src/cache/store.ts +1440 -0
- package/src/cache/types.ts +71 -0
- package/src/cli.bundle.ts +20 -0
- package/src/cli.ts +20 -0
- package/src/commands/basic-handlers.ts +145 -0
- package/src/commands/cli.ts +56 -0
- package/src/commands/command-context.ts +77 -0
- package/src/commands/command-definitions.ts +102 -0
- package/src/commands/command-metadata.ts +68 -0
- package/src/commands/command-registrar.ts +39 -0
- package/src/commands/command-runtime.ts +33 -0
- package/src/commands/default-handler-map.ts +25 -0
- package/src/commands/migrate-config.ts +104 -0
- package/src/commands/migrate-handler.ts +67 -0
- package/src/commands/migration-aggregation.ts +100 -0
- package/src/commands/migration-args.ts +85 -0
- package/src/commands/migration-file-executor.ts +189 -0
- package/src/commands/migration-output.ts +115 -0
- package/src/commands/migration-report-loader.ts +26 -0
- package/src/commands/migration-report.ts +21 -0
- package/src/commands/migration-source.ts +318 -0
- package/src/commands/migration-target-files.ts +161 -0
- package/src/commands/migration-target-resolver.ts +34 -0
- package/src/commands/migration-types.ts +65 -0
- package/src/commands/restore-handler.ts +24 -0
- package/src/commands/status-handler.ts +17 -0
- package/src/commands/status-output.ts +60 -0
- package/src/commands/token-output.ts +30 -0
- package/src/commands/types.ts +137 -0
- package/src/commands/validate-handler.ts +42 -0
- package/src/commands/validate.ts +83 -0
- package/src/config/index.ts +25 -0
- package/src/config/workspace.ts +87 -0
- package/src/constants.ts +4 -0
- package/src/extraction/candidate-extractor.ts +354 -0
- package/src/index.bundle.ts +105 -0
- package/src/index.ts +57 -0
- package/src/install/class-collector.ts +1 -0
- package/src/install/context-registry.ts +1 -0
- package/src/install/index.ts +5 -0
- package/src/install/patch-runner.ts +1 -0
- package/src/install/process-tailwindcss.ts +1 -0
- package/src/install/status.ts +1 -0
- package/src/logger.ts +5 -0
- package/src/options/legacy.ts +93 -0
- package/src/options/normalize.ts +262 -0
- package/src/options/types.ts +217 -0
- package/src/patching/operations/export-context/index.ts +110 -0
- package/src/patching/operations/export-context/postcss-v2.ts +235 -0
- package/src/patching/operations/export-context/postcss-v3.ts +249 -0
- package/src/patching/operations/extend-length-units.ts +197 -0
- package/src/patching/patch-runner.ts +46 -0
- package/src/patching/status.ts +262 -0
- package/src/runtime/class-collector.ts +105 -0
- package/src/runtime/collector.ts +148 -0
- package/src/runtime/context-registry.ts +65 -0
- package/src/runtime/process-tailwindcss.ts +115 -0
- package/src/types.ts +159 -0
- package/src/utils.ts +52 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import type { ExposeContextTransformOptions } from './postcss-v3'
|
|
2
|
+
import * as t from '@babel/types'
|
|
3
|
+
import { generate, parse, traverse } from '../../../babel'
|
|
4
|
+
|
|
5
|
+
const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i
|
|
6
|
+
|
|
7
|
+
function toIdentifierName(property: string) {
|
|
8
|
+
if (!property) {
|
|
9
|
+
return 'contextRef'
|
|
10
|
+
}
|
|
11
|
+
const sanitized = property.replace(/[^\w$]/gu, '_')
|
|
12
|
+
if (/^\d/.test(sanitized)) {
|
|
13
|
+
return `_${sanitized}`
|
|
14
|
+
}
|
|
15
|
+
return sanitized || 'contextRef'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function createExportsMember(property: string) {
|
|
19
|
+
if (IDENTIFIER_RE.test(property)) {
|
|
20
|
+
return t.memberExpression(t.identifier('exports'), t.identifier(property))
|
|
21
|
+
}
|
|
22
|
+
return t.memberExpression(t.identifier('exports'), t.stringLiteral(property), true)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function transformProcessTailwindFeaturesReturnContextV2(content: string) {
|
|
26
|
+
const ast = parse(content, {
|
|
27
|
+
sourceType: 'unambiguous',
|
|
28
|
+
})
|
|
29
|
+
let hasPatched = false
|
|
30
|
+
|
|
31
|
+
traverse(ast, {
|
|
32
|
+
FunctionDeclaration(path) {
|
|
33
|
+
const node = path.node
|
|
34
|
+
if (
|
|
35
|
+
node.id?.name !== 'processTailwindFeatures'
|
|
36
|
+
|| node.body.body.length !== 1
|
|
37
|
+
|| !t.isReturnStatement(node.body.body[0])
|
|
38
|
+
) {
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const returnStatement = node.body.body[0]
|
|
43
|
+
if (!t.isFunctionExpression(returnStatement.argument)) {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const body = returnStatement.argument.body.body
|
|
48
|
+
const lastStatement = body[body.length - 1]
|
|
49
|
+
const alreadyReturnsContext = Boolean(
|
|
50
|
+
t.isReturnStatement(lastStatement)
|
|
51
|
+
&& t.isIdentifier(lastStatement.argument)
|
|
52
|
+
&& lastStatement.argument.name === 'context',
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
hasPatched = alreadyReturnsContext
|
|
56
|
+
if (!alreadyReturnsContext) {
|
|
57
|
+
body.push(t.returnStatement(t.identifier('context')))
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
code: hasPatched ? content : generate(ast).code,
|
|
64
|
+
hasPatched,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function transformPostcssPluginV2(content: string, options: ExposeContextTransformOptions) {
|
|
69
|
+
const refIdentifier = t.identifier(toIdentifierName(options.refProperty))
|
|
70
|
+
const exportMember = createExportsMember(options.refProperty)
|
|
71
|
+
const valueMember = t.memberExpression(refIdentifier, t.identifier('value'))
|
|
72
|
+
const ast = parse(content)
|
|
73
|
+
|
|
74
|
+
let hasPatched = false
|
|
75
|
+
|
|
76
|
+
traverse(ast, {
|
|
77
|
+
Program(path) {
|
|
78
|
+
const program = path.node
|
|
79
|
+
const index = program.body.findIndex((statement) => {
|
|
80
|
+
return t.isFunctionDeclaration(statement) && statement.id?.name === '_default'
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
if (index === -1) {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const previous = program.body[index - 1]
|
|
88
|
+
const beforePrevious = program.body[index - 2]
|
|
89
|
+
|
|
90
|
+
const alreadyHasVariable = Boolean(
|
|
91
|
+
previous
|
|
92
|
+
&& t.isVariableDeclaration(previous)
|
|
93
|
+
&& previous.declarations.length === 1
|
|
94
|
+
&& (() => {
|
|
95
|
+
const declaration = previous.declarations[0]
|
|
96
|
+
return Boolean(
|
|
97
|
+
declaration
|
|
98
|
+
&& t.isIdentifier(declaration.id)
|
|
99
|
+
&& declaration.id.name === refIdentifier.name,
|
|
100
|
+
)
|
|
101
|
+
})(),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const alreadyAssignsExports = Boolean(
|
|
105
|
+
beforePrevious
|
|
106
|
+
&& t.isExpressionStatement(beforePrevious)
|
|
107
|
+
&& t.isAssignmentExpression(beforePrevious.expression)
|
|
108
|
+
&& t.isMemberExpression(beforePrevious.expression.left)
|
|
109
|
+
&& t.isIdentifier(beforePrevious.expression.right)
|
|
110
|
+
&& beforePrevious.expression.right.name === refIdentifier.name
|
|
111
|
+
&& generate(beforePrevious.expression.left).code === generate(exportMember).code,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
hasPatched = alreadyHasVariable && alreadyAssignsExports
|
|
115
|
+
|
|
116
|
+
if (!alreadyHasVariable) {
|
|
117
|
+
program.body.splice(
|
|
118
|
+
index,
|
|
119
|
+
0,
|
|
120
|
+
t.variableDeclaration('var', [
|
|
121
|
+
t.variableDeclarator(
|
|
122
|
+
refIdentifier,
|
|
123
|
+
t.objectExpression([
|
|
124
|
+
t.objectProperty(t.identifier('value'), t.arrayExpression()),
|
|
125
|
+
]),
|
|
126
|
+
),
|
|
127
|
+
]),
|
|
128
|
+
t.expressionStatement(
|
|
129
|
+
t.assignmentExpression('=', exportMember, refIdentifier),
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
FunctionDeclaration(path) {
|
|
135
|
+
if (hasPatched) {
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const fn = path.node
|
|
140
|
+
if (fn.id?.name !== '_default') {
|
|
141
|
+
return
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (fn.body.body.length !== 1 || !t.isReturnStatement(fn.body.body[0])) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const returnStatement = fn.body.body[0]
|
|
149
|
+
if (
|
|
150
|
+
!t.isCallExpression(returnStatement.argument)
|
|
151
|
+
|| !t.isMemberExpression(returnStatement.argument.callee)
|
|
152
|
+
|| !t.isArrayExpression(returnStatement.argument.callee.object)
|
|
153
|
+
) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const fnExpression = returnStatement.argument.callee.object.elements[1]
|
|
158
|
+
if (!fnExpression || !t.isFunctionExpression(fnExpression)) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const block = fnExpression.body
|
|
163
|
+
const statements = block.body
|
|
164
|
+
|
|
165
|
+
if (
|
|
166
|
+
t.isExpressionStatement(statements[0])
|
|
167
|
+
&& t.isAssignmentExpression(statements[0].expression)
|
|
168
|
+
&& t.isNumericLiteral(statements[0].expression.right)
|
|
169
|
+
) {
|
|
170
|
+
hasPatched = true
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const lastStatement = statements[statements.length - 1]
|
|
175
|
+
if (
|
|
176
|
+
lastStatement
|
|
177
|
+
&& t.isExpressionStatement(lastStatement)
|
|
178
|
+
) {
|
|
179
|
+
statements[statements.length - 1] = t.expressionStatement(
|
|
180
|
+
t.callExpression(
|
|
181
|
+
t.memberExpression(valueMember, t.identifier('push')),
|
|
182
|
+
[lastStatement.expression],
|
|
183
|
+
),
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const index = statements.findIndex(statement => t.isIfStatement(statement))
|
|
188
|
+
if (index > -1) {
|
|
189
|
+
const ifStatement = statements[index] as t.IfStatement
|
|
190
|
+
if (
|
|
191
|
+
t.isBlockStatement(ifStatement.consequent)
|
|
192
|
+
&& ifStatement.consequent.body[1]
|
|
193
|
+
&& t.isForOfStatement(ifStatement.consequent.body[1])
|
|
194
|
+
) {
|
|
195
|
+
const forOf = ifStatement.consequent.body[1]
|
|
196
|
+
if (
|
|
197
|
+
t.isBlockStatement(forOf.body)
|
|
198
|
+
&& forOf.body.body.length === 1
|
|
199
|
+
) {
|
|
200
|
+
const nestedIf = forOf.body.body[0]
|
|
201
|
+
if (
|
|
202
|
+
nestedIf
|
|
203
|
+
&& t.isIfStatement(nestedIf)
|
|
204
|
+
&& t.isBlockStatement(nestedIf.consequent)
|
|
205
|
+
&& nestedIf.consequent.body.length === 1
|
|
206
|
+
&& t.isExpressionStatement(nestedIf.consequent.body[0])
|
|
207
|
+
) {
|
|
208
|
+
nestedIf.consequent.body[0] = t.expressionStatement(
|
|
209
|
+
t.callExpression(
|
|
210
|
+
t.memberExpression(valueMember, t.identifier('push')),
|
|
211
|
+
[nestedIf.consequent.body[0].expression],
|
|
212
|
+
),
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
statements.unshift(
|
|
220
|
+
t.expressionStatement(
|
|
221
|
+
t.assignmentExpression(
|
|
222
|
+
'=',
|
|
223
|
+
t.memberExpression(valueMember, t.identifier('length')),
|
|
224
|
+
t.numericLiteral(0),
|
|
225
|
+
),
|
|
226
|
+
),
|
|
227
|
+
)
|
|
228
|
+
},
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
code: hasPatched ? content : generate(ast).code,
|
|
233
|
+
hasPatched,
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
import { generate, parse, traverse } from '../../../babel'
|
|
3
|
+
|
|
4
|
+
export interface ExposeContextTransformOptions {
|
|
5
|
+
refProperty: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i
|
|
9
|
+
|
|
10
|
+
function toIdentifierName(property: string) {
|
|
11
|
+
if (!property) {
|
|
12
|
+
return 'contextRef'
|
|
13
|
+
}
|
|
14
|
+
const sanitized = property.replace(/[^\w$]/gu, '_')
|
|
15
|
+
if (/^\d/.test(sanitized)) {
|
|
16
|
+
return `_${sanitized}`
|
|
17
|
+
}
|
|
18
|
+
return sanitized || 'contextRef'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createModuleExportsMember(property: string) {
|
|
22
|
+
const object = t.memberExpression(t.identifier('module'), t.identifier('exports'))
|
|
23
|
+
if (IDENTIFIER_RE.test(property)) {
|
|
24
|
+
return t.memberExpression(object, t.identifier(property))
|
|
25
|
+
}
|
|
26
|
+
return t.memberExpression(object, t.stringLiteral(property), true)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function transformProcessTailwindFeaturesReturnContext(content: string) {
|
|
30
|
+
const ast = parse(content)
|
|
31
|
+
let hasPatched = false
|
|
32
|
+
|
|
33
|
+
traverse(ast, {
|
|
34
|
+
FunctionDeclaration(path) {
|
|
35
|
+
const node = path.node
|
|
36
|
+
if (
|
|
37
|
+
node.id?.name !== 'processTailwindFeatures'
|
|
38
|
+
|| node.body.body.length !== 1
|
|
39
|
+
) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const [returnStatement] = node.body.body
|
|
44
|
+
if (
|
|
45
|
+
!t.isReturnStatement(returnStatement)
|
|
46
|
+
|| !t.isFunctionExpression(returnStatement.argument)
|
|
47
|
+
) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const expression = returnStatement.argument
|
|
52
|
+
const body = expression.body.body
|
|
53
|
+
const lastStatement = body[body.length - 1]
|
|
54
|
+
const alreadyReturnsContext = Boolean(
|
|
55
|
+
t.isReturnStatement(lastStatement)
|
|
56
|
+
&& t.isIdentifier(lastStatement.argument)
|
|
57
|
+
&& lastStatement.argument.name === 'context',
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
hasPatched = alreadyReturnsContext
|
|
61
|
+
if (!alreadyReturnsContext) {
|
|
62
|
+
body.push(t.returnStatement(t.identifier('context')))
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
code: hasPatched ? content : generate(ast).code,
|
|
69
|
+
hasPatched,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function transformPostcssPlugin(content: string, { refProperty }: ExposeContextTransformOptions) {
|
|
74
|
+
const ast = parse(content)
|
|
75
|
+
const refIdentifier = t.identifier(toIdentifierName(refProperty))
|
|
76
|
+
const moduleExportsMember = createModuleExportsMember(refProperty)
|
|
77
|
+
const valueMember = t.memberExpression(refIdentifier, t.identifier('value'))
|
|
78
|
+
|
|
79
|
+
let hasPatched = false
|
|
80
|
+
|
|
81
|
+
traverse(ast, {
|
|
82
|
+
Program(path) {
|
|
83
|
+
const program = path.node
|
|
84
|
+
const index = program.body.findIndex((statement) => {
|
|
85
|
+
return (
|
|
86
|
+
t.isExpressionStatement(statement)
|
|
87
|
+
&& t.isAssignmentExpression(statement.expression)
|
|
88
|
+
&& t.isMemberExpression(statement.expression.left)
|
|
89
|
+
&& t.isFunctionExpression(statement.expression.right)
|
|
90
|
+
&& statement.expression.right.id?.name === 'tailwindcss'
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
if (index === -1) {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const previousStatement = program.body[index - 1]
|
|
99
|
+
const lastStatement = program.body[program.body.length - 1]
|
|
100
|
+
const alreadyHasVariable = Boolean(
|
|
101
|
+
previousStatement
|
|
102
|
+
&& t.isVariableDeclaration(previousStatement)
|
|
103
|
+
&& previousStatement.declarations.length === 1
|
|
104
|
+
&& (() => {
|
|
105
|
+
const declaration = previousStatement.declarations[0]
|
|
106
|
+
return Boolean(
|
|
107
|
+
declaration
|
|
108
|
+
&& t.isIdentifier(declaration.id)
|
|
109
|
+
&& declaration.id.name === refIdentifier.name,
|
|
110
|
+
)
|
|
111
|
+
})(),
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
const alreadyAssignsModuleExports = Boolean(
|
|
115
|
+
t.isExpressionStatement(lastStatement)
|
|
116
|
+
&& t.isAssignmentExpression(lastStatement.expression)
|
|
117
|
+
&& t.isMemberExpression(lastStatement.expression.left)
|
|
118
|
+
&& t.isIdentifier(lastStatement.expression.right)
|
|
119
|
+
&& lastStatement.expression.right.name === refIdentifier.name
|
|
120
|
+
&& generate(lastStatement.expression.left).code === generate(moduleExportsMember).code,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
hasPatched = alreadyHasVariable && alreadyAssignsModuleExports
|
|
124
|
+
|
|
125
|
+
if (!alreadyHasVariable) {
|
|
126
|
+
program.body.splice(
|
|
127
|
+
index,
|
|
128
|
+
0,
|
|
129
|
+
t.variableDeclaration('const', [
|
|
130
|
+
t.variableDeclarator(
|
|
131
|
+
refIdentifier,
|
|
132
|
+
t.objectExpression([
|
|
133
|
+
t.objectProperty(t.identifier('value'), t.arrayExpression()),
|
|
134
|
+
]),
|
|
135
|
+
),
|
|
136
|
+
]),
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!alreadyAssignsModuleExports) {
|
|
141
|
+
program.body.push(
|
|
142
|
+
t.expressionStatement(
|
|
143
|
+
t.assignmentExpression('=', moduleExportsMember, refIdentifier),
|
|
144
|
+
),
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
FunctionExpression(path) {
|
|
149
|
+
if (hasPatched) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
const fn = path.node
|
|
153
|
+
if (fn.id?.name !== 'tailwindcss' || fn.body.body.length !== 1) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const [returnStatement] = fn.body.body
|
|
158
|
+
if (!returnStatement || !t.isReturnStatement(returnStatement) || !t.isObjectExpression(returnStatement.argument)) {
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const properties = returnStatement.argument.properties
|
|
163
|
+
if (properties.length !== 2) {
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const pluginsProperty = properties.find(
|
|
168
|
+
prop => t.isObjectProperty(prop) && t.isIdentifier(prop.key) && prop.key.name === 'plugins',
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
if (
|
|
172
|
+
!pluginsProperty
|
|
173
|
+
|| !t.isObjectProperty(pluginsProperty)
|
|
174
|
+
|| !t.isCallExpression(pluginsProperty.value)
|
|
175
|
+
|| !t.isMemberExpression(pluginsProperty.value.callee)
|
|
176
|
+
|| !t.isArrayExpression(pluginsProperty.value.callee.object)
|
|
177
|
+
) {
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const pluginsArray = pluginsProperty.value.callee.object.elements
|
|
182
|
+
|
|
183
|
+
const targetPlugin = pluginsArray[1]
|
|
184
|
+
if (!targetPlugin || !t.isFunctionExpression(targetPlugin)) {
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const block = targetPlugin.body
|
|
189
|
+
const statements = block.body
|
|
190
|
+
const last = statements[statements.length - 1]
|
|
191
|
+
|
|
192
|
+
if (
|
|
193
|
+
last
|
|
194
|
+
&& t.isExpressionStatement(last)
|
|
195
|
+
) {
|
|
196
|
+
statements[statements.length - 1] = t.expressionStatement(
|
|
197
|
+
t.callExpression(
|
|
198
|
+
t.memberExpression(valueMember, t.identifier('push')),
|
|
199
|
+
[last.expression],
|
|
200
|
+
),
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const index = statements.findIndex(s => t.isIfStatement(s))
|
|
205
|
+
if (index > -1) {
|
|
206
|
+
const ifStatement = statements[index] as t.IfStatement
|
|
207
|
+
if (t.isBlockStatement(ifStatement.consequent)) {
|
|
208
|
+
const [, second] = ifStatement.consequent.body
|
|
209
|
+
if (
|
|
210
|
+
second
|
|
211
|
+
&& t.isForOfStatement(second)
|
|
212
|
+
&& t.isBlockStatement(second.body)
|
|
213
|
+
) {
|
|
214
|
+
const bodyStatement = second.body.body[0]
|
|
215
|
+
if (
|
|
216
|
+
bodyStatement
|
|
217
|
+
&& t.isIfStatement(bodyStatement)
|
|
218
|
+
&& t.isBlockStatement(bodyStatement.consequent)
|
|
219
|
+
&& bodyStatement.consequent.body.length === 1
|
|
220
|
+
&& t.isExpressionStatement(bodyStatement.consequent.body[0])
|
|
221
|
+
) {
|
|
222
|
+
bodyStatement.consequent.body[0] = t.expressionStatement(
|
|
223
|
+
t.callExpression(
|
|
224
|
+
t.memberExpression(valueMember, t.identifier('push')),
|
|
225
|
+
[bodyStatement.consequent.body[0].expression],
|
|
226
|
+
),
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
statements.unshift(
|
|
234
|
+
t.expressionStatement(
|
|
235
|
+
t.assignmentExpression(
|
|
236
|
+
'=',
|
|
237
|
+
t.memberExpression(valueMember, t.identifier('length')),
|
|
238
|
+
t.numericLiteral(0),
|
|
239
|
+
),
|
|
240
|
+
),
|
|
241
|
+
)
|
|
242
|
+
},
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
code: hasPatched ? content : generate(ast).code,
|
|
247
|
+
hasPatched,
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type { ArrayExpression, StringLiteral } from '@babel/types'
|
|
2
|
+
import type { NormalizedExtendLengthUnitsOptions } from '../../options/types'
|
|
3
|
+
import * as t from '@babel/types'
|
|
4
|
+
import fs from 'fs-extra'
|
|
5
|
+
import path from 'pathe'
|
|
6
|
+
import { generate, parse, traverse } from '../../babel'
|
|
7
|
+
import logger from '../../logger'
|
|
8
|
+
import { spliceChangesIntoString } from '../../utils'
|
|
9
|
+
|
|
10
|
+
interface FindArrayExpressionResult {
|
|
11
|
+
arrayRef?: ArrayExpression
|
|
12
|
+
changed: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function updateLengthUnitsArray(content: string, options: NormalizedExtendLengthUnitsOptions): FindArrayExpressionResult {
|
|
16
|
+
const { variableName = 'lengthUnits', units } = options
|
|
17
|
+
const ast = parse(content)
|
|
18
|
+
|
|
19
|
+
let arrayRef: ArrayExpression | undefined
|
|
20
|
+
let changed = false
|
|
21
|
+
|
|
22
|
+
traverse(ast, {
|
|
23
|
+
Identifier(path) {
|
|
24
|
+
if (
|
|
25
|
+
path.node.name === variableName
|
|
26
|
+
&& t.isVariableDeclarator(path.parent)
|
|
27
|
+
&& t.isArrayExpression(path.parent.init)
|
|
28
|
+
) {
|
|
29
|
+
arrayRef = path.parent.init
|
|
30
|
+
const existing = new Set(
|
|
31
|
+
path.parent.init.elements.map(element => (t.isStringLiteral(element) ? (element as StringLiteral).value : undefined)).filter(Boolean),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
for (const unit of units) {
|
|
35
|
+
if (!existing.has(unit)) {
|
|
36
|
+
path.parent.init.elements = path.parent.init.elements.map((element) => {
|
|
37
|
+
if (t.isStringLiteral(element)) {
|
|
38
|
+
return t.stringLiteral(element.value)
|
|
39
|
+
}
|
|
40
|
+
return element
|
|
41
|
+
})
|
|
42
|
+
path.parent.init.elements.push(t.stringLiteral(unit))
|
|
43
|
+
changed = true
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
...(arrayRef === undefined ? {} : { arrayRef }),
|
|
52
|
+
changed,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function applyExtendLengthUnitsPatchV3(rootDir: string, options: NormalizedExtendLengthUnitsOptions) {
|
|
57
|
+
if (!options.enabled) {
|
|
58
|
+
return { changed: false, code: undefined }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const opts: NormalisedV3Options = {
|
|
62
|
+
...options,
|
|
63
|
+
lengthUnitsFilePath: options.lengthUnitsFilePath ?? 'lib/util/dataTypes.js',
|
|
64
|
+
variableName: options.variableName ?? 'lengthUnits',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const dataTypesFilePath = path.resolve(rootDir, opts.lengthUnitsFilePath)
|
|
68
|
+
const exists = fs.existsSync(dataTypesFilePath)
|
|
69
|
+
|
|
70
|
+
if (!exists) {
|
|
71
|
+
return { changed: false, code: undefined }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const content = fs.readFileSync(dataTypesFilePath, 'utf8')
|
|
75
|
+
const { arrayRef, changed } = updateLengthUnitsArray(content, opts)
|
|
76
|
+
|
|
77
|
+
if (!arrayRef || !changed) {
|
|
78
|
+
return { changed: false, code: undefined }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { code } = generate(arrayRef, {
|
|
82
|
+
jsescOption: { quotes: 'single' },
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
if (arrayRef.start != null && arrayRef.end != null) {
|
|
86
|
+
const nextCode = `${content.slice(0, arrayRef.start)}${code}${content.slice(arrayRef.end)}`
|
|
87
|
+
if (opts.overwrite) {
|
|
88
|
+
const target = opts.destPath ? path.resolve(opts.destPath) : dataTypesFilePath
|
|
89
|
+
fs.writeFileSync(target, nextCode, 'utf8')
|
|
90
|
+
logger.success('Patched Tailwind CSS length unit list (v3).')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
changed: true,
|
|
95
|
+
code: nextCode,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
changed: false,
|
|
101
|
+
code: undefined,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface NormalisedV3Options extends NormalizedExtendLengthUnitsOptions {
|
|
106
|
+
lengthUnitsFilePath: string
|
|
107
|
+
variableName: string
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface V4FilePatch {
|
|
111
|
+
file: string
|
|
112
|
+
code: string
|
|
113
|
+
hasPatched: boolean
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
interface V4Candidate extends V4FilePatch {
|
|
117
|
+
match: RegExpExecArray
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function applyExtendLengthUnitsPatchV4(rootDir: string, options: NormalizedExtendLengthUnitsOptions) {
|
|
121
|
+
if (!options.enabled) {
|
|
122
|
+
return { files: [], changed: false }
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const opts: NormalisedV4Options = { ...options }
|
|
126
|
+
|
|
127
|
+
const distDir = path.resolve(rootDir, 'dist')
|
|
128
|
+
if (!fs.existsSync(distDir)) {
|
|
129
|
+
return { files: [], changed: false }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const entries = fs.readdirSync(distDir)
|
|
133
|
+
const chunkNames = entries.filter(entry => entry.endsWith('.js') || entry.endsWith('.mjs'))
|
|
134
|
+
const pattern = /\[\s*["']cm["'],\s*["']mm["'],[\w,"']+\]/
|
|
135
|
+
|
|
136
|
+
const candidates = chunkNames.map((chunkName) => {
|
|
137
|
+
const file = path.join(distDir, chunkName)
|
|
138
|
+
const code = fs.readFileSync(file, 'utf8')
|
|
139
|
+
const match = pattern.exec(code)
|
|
140
|
+
if (!match) {
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
file,
|
|
145
|
+
code,
|
|
146
|
+
match,
|
|
147
|
+
hasPatched: false,
|
|
148
|
+
}
|
|
149
|
+
}).filter((candidate): candidate is V4Candidate => candidate !== null)
|
|
150
|
+
|
|
151
|
+
for (const item of candidates) {
|
|
152
|
+
const { code, file, match } = item
|
|
153
|
+
const ast = parse(match[0], { sourceType: 'unambiguous' })
|
|
154
|
+
|
|
155
|
+
traverse(ast, {
|
|
156
|
+
ArrayExpression(path) {
|
|
157
|
+
for (const unit of opts.units) {
|
|
158
|
+
if (path.node.elements.some(element => t.isStringLiteral(element) && element.value === unit)) {
|
|
159
|
+
item.hasPatched = true
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
path.node.elements.push(t.stringLiteral(unit))
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
if (item.hasPatched) {
|
|
168
|
+
continue
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const { code: replacement } = generate(ast, { minified: true })
|
|
172
|
+
const start = match.index ?? 0
|
|
173
|
+
const end = start + match[0].length
|
|
174
|
+
item.code = spliceChangesIntoString(code, [
|
|
175
|
+
{
|
|
176
|
+
start,
|
|
177
|
+
end,
|
|
178
|
+
replacement: replacement.endsWith(';') ? replacement.slice(0, -1) : replacement,
|
|
179
|
+
},
|
|
180
|
+
])
|
|
181
|
+
|
|
182
|
+
if (opts.overwrite) {
|
|
183
|
+
fs.writeFileSync(file, item.code, 'utf8')
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (candidates.some(file => !file.hasPatched)) {
|
|
188
|
+
logger.success('Patched Tailwind CSS length unit list (v4).')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
changed: candidates.some(file => !file.hasPatched),
|
|
193
|
+
files: candidates,
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
interface NormalisedV4Options extends NormalizedExtendLengthUnitsOptions {}
|