styled-components-to-stylex-codemod 0.0.38 → 0.0.40
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/dist/{bridge-consumer-patcher-BzAIO9pC.mjs → bridge-consumer-patcher-31jI1854.mjs} +146 -1
- package/dist/{compute-leaf-set-Drcu2eju.mjs → compute-leaf-set-C-xis90s.mjs} +6 -3
- package/dist/{extract-external-interface-CdHbvfxu.mjs → extract-external-interface-DbzIPO0Z.mjs} +28 -13
- package/dist/{forwarded-as-consumer-patcher-Cs0X-olz.mjs → forwarded-as-consumer-patcher-BYCrqzRm.mjs} +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +8 -7
- package/dist/prop-usage-D6ZiDfzz.mjs +136 -0
- package/dist/{resolve-imports-BlxKezSJ.mjs → resolve-imports-DgSAddIF.mjs} +1 -0
- package/dist/{run-prepass-Us5SBTib.mjs → run-prepass-jnJbdfxU.mjs} +174 -22
- package/dist/{string-utils-KggM5TNH.mjs → string-utils-DD9wdRHW.mjs} +16 -1
- package/dist/{transform-types--9qCqNSJ.d.mts → transform-types-DUT5eSAm.d.mts} +16 -1
- package/dist/transform.d.mts +1 -1
- package/dist/transform.mjs +2950 -1187
- package/dist/{transient-prop-consumer-patcher-DLsKxg1R.mjs → transient-prop-consumer-patcher-DdIYPSFk.mjs} +1 -1
- package/package.json +4 -4
- package/dist/styled-css-BVR82jN5.mjs +0 -72
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as toRealPath } from "./path-utils-BIpoL4Ue.mjs";
|
|
2
|
-
import { r as escapeRegex } from "./string-utils-
|
|
2
|
+
import { r as escapeRegex } from "./string-utils-DD9wdRHW.mjs";
|
|
3
3
|
import { t as isSelectorContext } from "./selector-context-heuristic-6_jSRGkZ.mjs";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
//#region src/internal/bridge-consumer-patcher.ts
|
|
@@ -102,6 +102,7 @@ function patchConsumerFile(filePath, replacements) {
|
|
|
102
102
|
return match;
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
+
modified = removeNowUnusedComponentImports(modified, replacements);
|
|
105
106
|
return modified !== source ? modified : null;
|
|
106
107
|
}
|
|
107
108
|
/** Find the end position of an import statement starting at startIdx (handles multi-line imports). */
|
|
@@ -119,5 +120,149 @@ function isInStyledTemplateSelectorContext(source, offset, length) {
|
|
|
119
120
|
function hasExactImportName(importSpecifiers, name) {
|
|
120
121
|
return new RegExp(`(?:^|[^A-Za-z0-9_$])${escapeRegex(name)}(?:$|[^A-Za-z0-9_$])`).test(importSpecifiers);
|
|
121
122
|
}
|
|
123
|
+
function removeNowUnusedComponentImports(source, replacements) {
|
|
124
|
+
let modified = source;
|
|
125
|
+
for (const replacement of replacements) {
|
|
126
|
+
if (hasIdentifierUsageOutsideImports(modified, replacement.localName)) continue;
|
|
127
|
+
modified = removeNamedImportSpecifier(modified, replacement.importSource, replacement.localName);
|
|
128
|
+
}
|
|
129
|
+
return modified;
|
|
130
|
+
}
|
|
131
|
+
function hasIdentifierUsageOutsideImports(source, name) {
|
|
132
|
+
const withoutImports = stripImportDeclarations(stripComments(source));
|
|
133
|
+
return new RegExp(`(^|[^A-Za-z0-9_$])${escapeRegex(name)}($|[^A-Za-z0-9_$])`).test(withoutImports);
|
|
134
|
+
}
|
|
135
|
+
function stripImportDeclarations(source) {
|
|
136
|
+
const lines = source.split(/(?<=\n)/);
|
|
137
|
+
let result = "";
|
|
138
|
+
let inImport = false;
|
|
139
|
+
let nestingDepth = 0;
|
|
140
|
+
for (const line of lines) {
|
|
141
|
+
if (!inImport && !isImportDeclarationStart(line)) {
|
|
142
|
+
result += line;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
inImport = true;
|
|
146
|
+
nestingDepth += getImportNestingDelta(line);
|
|
147
|
+
if (nestingDepth <= 0 && isImportDeclarationEnd(line)) {
|
|
148
|
+
inImport = false;
|
|
149
|
+
nestingDepth = 0;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
function isImportDeclarationStart(line) {
|
|
155
|
+
const match = line.match(/^[ \t]*import\b/);
|
|
156
|
+
if (!match) return false;
|
|
157
|
+
const next = line.slice(match[0].length).trimStart()[0];
|
|
158
|
+
return next !== "(" && next !== ".";
|
|
159
|
+
}
|
|
160
|
+
function isImportDeclarationEnd(line) {
|
|
161
|
+
const trimmed = line.trim();
|
|
162
|
+
return trimmed.endsWith(";") || /^import\s+["'][^"']+["']$/.test(trimmed) || /\bfrom\s+["'][^"']+["'](?:\s+with\s+\{[^}]*\})?$/.test(trimmed);
|
|
163
|
+
}
|
|
164
|
+
function getImportNestingDelta(line) {
|
|
165
|
+
let depth = 0;
|
|
166
|
+
let quote = null;
|
|
167
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
168
|
+
const char = line[index];
|
|
169
|
+
if (quote) {
|
|
170
|
+
if (char === "\\") index += 1;
|
|
171
|
+
else if (char === quote) quote = null;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
if (char === "'" || char === "\"") quote = char;
|
|
175
|
+
else if (char === "{" || char === "(" || char === "[") depth += 1;
|
|
176
|
+
else if (char === "}" || char === ")" || char === "]") depth -= 1;
|
|
177
|
+
}
|
|
178
|
+
return depth;
|
|
179
|
+
}
|
|
180
|
+
function stripComments(source) {
|
|
181
|
+
let result = "";
|
|
182
|
+
let state = "normal";
|
|
183
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
184
|
+
const char = source[index] ?? "";
|
|
185
|
+
const next = source[index + 1] ?? "";
|
|
186
|
+
if (state === "lineComment") {
|
|
187
|
+
if (char === "\n") {
|
|
188
|
+
result += char;
|
|
189
|
+
state = "normal";
|
|
190
|
+
} else result += " ";
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (state === "blockComment") {
|
|
194
|
+
if (char === "*" && next === "/") {
|
|
195
|
+
result += " ";
|
|
196
|
+
index += 1;
|
|
197
|
+
state = "normal";
|
|
198
|
+
} else result += char === "\n" ? "\n" : " ";
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (state === "template") {
|
|
202
|
+
if (char === "/" && next === "/") {
|
|
203
|
+
result += " ";
|
|
204
|
+
index += 1;
|
|
205
|
+
state = "lineComment";
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (char === "/" && next === "*") {
|
|
209
|
+
result += " ";
|
|
210
|
+
index += 1;
|
|
211
|
+
state = "blockComment";
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
result += char;
|
|
215
|
+
if (char === "\\") {
|
|
216
|
+
result += next;
|
|
217
|
+
index += 1;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (char === "`") state = "normal";
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (state === "singleQuote" || state === "doubleQuote") {
|
|
224
|
+
result += char;
|
|
225
|
+
if (char === "\\") {
|
|
226
|
+
result += next;
|
|
227
|
+
index += 1;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (state === "singleQuote" && char === "'" || state === "doubleQuote" && char === "\"") state = "normal";
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (char === "/" && next === "/") {
|
|
234
|
+
result += " ";
|
|
235
|
+
index += 1;
|
|
236
|
+
state = "lineComment";
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (char === "/" && next === "*") {
|
|
240
|
+
result += " ";
|
|
241
|
+
index += 1;
|
|
242
|
+
state = "blockComment";
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (char === "'") state = "singleQuote";
|
|
246
|
+
else if (char === "\"") state = "doubleQuote";
|
|
247
|
+
else if (char === "`") state = "template";
|
|
248
|
+
result += char;
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function removeNamedImportSpecifier(source, importSource, localName) {
|
|
253
|
+
const namedImportRegex = new RegExp(`import\\s+([\\w$]+\\s*,\\s*)?\\{([^}]*)\\}\\s+from\\s+(['"]${escapeRegex(importSource)}['"]\\s*;?)`, "g");
|
|
254
|
+
return source.replace(namedImportRegex, (_match, defaultPart, specifierList, fromClause) => {
|
|
255
|
+
const remainingSpecifiers = String(specifierList).split(",").map((specifier) => specifier.trim()).filter(Boolean).filter((specifier) => getImportedSpecifierLocalName(specifier) !== localName);
|
|
256
|
+
if (remainingSpecifiers.length > 0) return `import ${defaultPart ?? ""}{ ${remainingSpecifiers.join(", ")} } from ${fromClause}`;
|
|
257
|
+
const defaultName = String(defaultPart ?? "").replace(/,\s*$/, "").trim();
|
|
258
|
+
if (defaultName) return `import ${defaultName} from ${fromClause}`;
|
|
259
|
+
return "";
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
function getImportedSpecifierLocalName(specifier) {
|
|
263
|
+
const aliasMatch = specifier.match(/\bas\s+([A-Za-z_$][\w$]*)$/);
|
|
264
|
+
if (aliasMatch?.[1]) return aliasMatch[1];
|
|
265
|
+
return specifier.trim();
|
|
266
|
+
}
|
|
122
267
|
//#endregion
|
|
123
268
|
export { buildConsumerReplacements, patchConsumerFile };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as resolveBarrelReExportBinding, r as findImportSource } from "./extract-external-interface-DbzIPO0Z.mjs";
|
|
2
2
|
//#region src/internal/prepass/compute-leaf-set.ts
|
|
3
3
|
/**
|
|
4
4
|
* Computes which styled-component bindings are "leaves" for leaves-only mode:
|
|
@@ -171,9 +171,12 @@ function computeGlobalLeafKeys(args) {
|
|
|
171
171
|
if (!importInfo) return false;
|
|
172
172
|
const initialDefFile = resolve(importInfo.source, file);
|
|
173
173
|
if (!initialDefFile) return false;
|
|
174
|
-
const
|
|
174
|
+
const reExport = resolveBarrelReExportBinding(initialDefFile, importInfo.isDefault ? "default" : importInfo.exportedName, resolve, cachedRead);
|
|
175
|
+
const defFile = reExport?.filePath ?? initialDefFile;
|
|
176
|
+
const exportedName = reExport?.exportedName ?? importInfo.exportedName;
|
|
177
|
+
const defReal = toRealPath(defFile);
|
|
175
178
|
if (!transformSet.has(defReal)) return false;
|
|
176
|
-
return leafKeyExists(defReal,
|
|
179
|
+
return leafKeyExists(defReal, exportedName, exportedName === "default" || importInfo.isDefault, cachedRead, globalLeaves);
|
|
177
180
|
};
|
|
178
181
|
const tryResolveAdapterIntrinsic = (file, ident) => {
|
|
179
182
|
if (!resolveBaseComponent) return false;
|
package/dist/{extract-external-interface-CdHbvfxu.mjs → extract-external-interface-DbzIPO0Z.mjs}
RENAMED
|
@@ -292,6 +292,9 @@ function getImportSourceRes(localName) {
|
|
|
292
292
|
return cached;
|
|
293
293
|
}
|
|
294
294
|
function resolveBarrelReExport(filePath, name, resolve, read) {
|
|
295
|
+
return resolveBarrelReExportBinding(filePath, name, resolve, read)?.filePath ?? null;
|
|
296
|
+
}
|
|
297
|
+
function resolveBarrelReExportBinding(filePath, name, resolve, read) {
|
|
295
298
|
const basename = path.basename(filePath);
|
|
296
299
|
if (basename !== "index.ts" && basename !== "index.tsx") return null;
|
|
297
300
|
let src;
|
|
@@ -300,14 +303,25 @@ function resolveBarrelReExport(filePath, name, resolve, read) {
|
|
|
300
303
|
} catch {
|
|
301
304
|
return null;
|
|
302
305
|
}
|
|
303
|
-
const
|
|
304
|
-
|
|
306
|
+
for (const match of src.matchAll(/export\s*\{([^}]+)\}\s*from\s*["']([^"']+)["']/g)) {
|
|
307
|
+
const sourceName = getReExportedSourceName(match[1] ?? "", name);
|
|
308
|
+
const specifier = match[2];
|
|
309
|
+
if (!sourceName || !specifier) continue;
|
|
310
|
+
const resolved = resolve(specifier, filePath);
|
|
311
|
+
if (resolved) return {
|
|
312
|
+
filePath: resolved,
|
|
313
|
+
exportedName: sourceName
|
|
314
|
+
};
|
|
315
|
+
}
|
|
305
316
|
for (const match of src.matchAll(/export\s*\*\s*from\s*["']([^"']+)["']/g)) {
|
|
306
317
|
const specifier = match[1];
|
|
307
318
|
if (!specifier) continue;
|
|
308
319
|
const resolved = resolve(specifier, filePath);
|
|
309
320
|
if (resolved) try {
|
|
310
|
-
if (fileExports(read(resolved), name)) return
|
|
321
|
+
if (fileExports(read(resolved), name)) return {
|
|
322
|
+
filePath: resolved,
|
|
323
|
+
exportedName: name
|
|
324
|
+
};
|
|
311
325
|
} catch {}
|
|
312
326
|
}
|
|
313
327
|
return null;
|
|
@@ -315,6 +329,16 @@ function resolveBarrelReExport(filePath, name, resolve, read) {
|
|
|
315
329
|
function fileExports(src, name) {
|
|
316
330
|
return getFileExportsRe(name).test(src);
|
|
317
331
|
}
|
|
332
|
+
function getReExportedSourceName(specifiers, exportedName) {
|
|
333
|
+
for (const raw of specifiers.split(",")) {
|
|
334
|
+
const parts = raw.trim().split(/\s+as\s+/);
|
|
335
|
+
const local = parts[0]?.trim();
|
|
336
|
+
const exported = (parts[1] ?? parts[0])?.trim();
|
|
337
|
+
if (!local || !exported) continue;
|
|
338
|
+
if (exported === exportedName) return local;
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
318
342
|
const fileExportsReCache = /* @__PURE__ */ new Map();
|
|
319
343
|
function getFileExportsRe(name) {
|
|
320
344
|
let re = fileExportsReCache.get(name);
|
|
@@ -324,15 +348,6 @@ function getFileExportsRe(name) {
|
|
|
324
348
|
}
|
|
325
349
|
return re;
|
|
326
350
|
}
|
|
327
|
-
const barrelExportReCache = /* @__PURE__ */ new Map();
|
|
328
|
-
function getBarrelExportRe(name) {
|
|
329
|
-
let re = barrelExportReCache.get(name);
|
|
330
|
-
if (!re) {
|
|
331
|
-
re = new RegExp(String.raw`export\s*\{[^}]*\b${name}\b[^}]*\}\s*from\s*["']([^"']+)["']`);
|
|
332
|
-
barrelExportReCache.set(name, re);
|
|
333
|
-
}
|
|
334
|
-
return re;
|
|
335
|
-
}
|
|
336
351
|
function fileImportsFrom(usageSrc, usageFile, name, defFile, resolve) {
|
|
337
352
|
const [namedRe, defaultRe] = getFileImportsFromRes(name);
|
|
338
353
|
namedRe.lastIndex = 0;
|
|
@@ -358,4 +373,4 @@ function getFileImportsFromRes(name) {
|
|
|
358
373
|
return cached;
|
|
359
374
|
}
|
|
360
375
|
//#endregion
|
|
361
|
-
export {
|
|
376
|
+
export { resolveBarrelReExport as a, getReExportedSourceName as i, fileImportsFrom as n, resolveBarrelReExportBinding as o, findImportSource as r, Logger as s, fileExports as t };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as toRealPath } from "./path-utils-BIpoL4Ue.mjs";
|
|
2
|
-
import { r as escapeRegex } from "./string-utils-
|
|
2
|
+
import { r as escapeRegex } from "./string-utils-DD9wdRHW.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
//#region src/internal/forwarded-as-consumer-patcher.ts
|
|
5
5
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CollectedWarning, c as MarkerFileContext, l as defineAdapter, n as TransformMode, o as AdapterInput, s as ImportSource } from "./transform-types
|
|
1
|
+
import { a as CollectedWarning, c as MarkerFileContext, l as defineAdapter, n as TransformMode, o as AdapterInput, s as ImportSource } from "./transform-types-DUT5eSAm.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/run.d.ts
|
|
4
4
|
interface RunTransformOptions {
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as assertValidAdapterInput, r as defineAdapter, s as describeValue, t as mergeMarkerDeclarations } from "./merge-markers-BC5YNB7D.mjs";
|
|
2
|
-
import { a as
|
|
3
|
-
import { r as extractStyledDefBasesFromSource } from "./compute-leaf-set-
|
|
2
|
+
import { a as resolveBarrelReExport, s as Logger } from "./extract-external-interface-DbzIPO0Z.mjs";
|
|
3
|
+
import { r as extractStyledDefBasesFromSource } from "./compute-leaf-set-C-xis90s.mjs";
|
|
4
4
|
import { n as toRealPath } from "./path-utils-BIpoL4Ue.mjs";
|
|
5
5
|
import jscodeshift from "jscodeshift";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -146,10 +146,10 @@ async function runTransform(options) {
|
|
|
146
146
|
`Pattern(s): ${consumerPatterns.join(", ")}`,
|
|
147
147
|
"Check that the glob pattern is correct and files exist."
|
|
148
148
|
].join("\n"));
|
|
149
|
-
const { createModuleResolver } = await import("./resolve-imports-
|
|
149
|
+
const { createModuleResolver } = await import("./resolve-imports-DgSAddIF.mjs").then((n) => n.n);
|
|
150
150
|
const sharedResolver = createModuleResolver();
|
|
151
151
|
filePaths = orderFilesByLocalImportDependencies(filePaths, sharedResolver, toRealPath);
|
|
152
|
-
const { runPrepass } = await import("./run-prepass-
|
|
152
|
+
const { runPrepass } = await import("./run-prepass-jnJbdfxU.mjs");
|
|
153
153
|
const absoluteFiles = filePaths.map((f) => resolve(f));
|
|
154
154
|
const absoluteConsumers = consumerFilePaths.map((f) => resolve(f));
|
|
155
155
|
let prepassResult;
|
|
@@ -172,6 +172,7 @@ async function runTransform(options) {
|
|
|
172
172
|
selectorUsages: /* @__PURE__ */ new Map(),
|
|
173
173
|
componentsNeedingMarkerSidecar: /* @__PURE__ */ new Map(),
|
|
174
174
|
componentsNeedingGlobalSelectorBridge: /* @__PURE__ */ new Map(),
|
|
175
|
+
propUsageByFile: /* @__PURE__ */ new Map(),
|
|
175
176
|
globalLeafKeys: leavesOnly ? /* @__PURE__ */ new Set() : void 0
|
|
176
177
|
},
|
|
177
178
|
consumerAnalysis: void 0,
|
|
@@ -308,7 +309,7 @@ async function runTransform(options) {
|
|
|
308
309
|
const result = await runTransformSequentially(transformModule, filePaths, runnerOptions);
|
|
309
310
|
if (sidecarFiles.size > 0 && !dryRun) for (const [sidecarPath, content] of sidecarFiles) await writeFile(sidecarPath, mergeSidecarContent(sidecarPath, content), "utf-8");
|
|
310
311
|
if (bridgeResults.size > 0 && !dryRun) {
|
|
311
|
-
const { buildConsumerReplacements, patchConsumerFile } = await import("./bridge-consumer-patcher-
|
|
312
|
+
const { buildConsumerReplacements, patchConsumerFile } = await import("./bridge-consumer-patcher-31jI1854.mjs");
|
|
312
313
|
const consumerReplacements = buildConsumerReplacements(crossFilePrepassResult.selectorUsages, bridgeResults, transformedFiles);
|
|
313
314
|
const patchedFiles = [];
|
|
314
315
|
for (const [consumerPath, replacements] of consumerReplacements) {
|
|
@@ -321,7 +322,7 @@ async function runTransform(options) {
|
|
|
321
322
|
if (formatterCommands && patchedFiles.length > 0) await runFormatters(formatterCommands, patchedFiles);
|
|
322
323
|
}
|
|
323
324
|
if (prepassResult.forwardedAsConsumers.size > 0 && !dryRun) {
|
|
324
|
-
const { buildForwardedAsReplacements, patchConsumerForwardedAs } = await import("./forwarded-as-consumer-patcher-
|
|
325
|
+
const { buildForwardedAsReplacements, patchConsumerForwardedAs } = await import("./forwarded-as-consumer-patcher-BYCrqzRm.mjs");
|
|
325
326
|
const forwardedAsReplacements = buildForwardedAsReplacements(prepassResult.forwardedAsConsumers, transformedFiles);
|
|
326
327
|
const patchedFiles = [];
|
|
327
328
|
for (const [consumerPath, entries] of forwardedAsReplacements) {
|
|
@@ -334,7 +335,7 @@ async function runTransform(options) {
|
|
|
334
335
|
if (formatterCommands && patchedFiles.length > 0) await runFormatters(formatterCommands, patchedFiles);
|
|
335
336
|
}
|
|
336
337
|
if (transientPropRenames.size > 0 && !dryRun) {
|
|
337
|
-
const { collectTransientPropPatches } = await import("./transient-prop-consumer-patcher-
|
|
338
|
+
const { collectTransientPropPatches } = await import("./transient-prop-consumer-patcher-DdIYPSFk.mjs");
|
|
338
339
|
const patches = collectTransientPropPatches({
|
|
339
340
|
transientPropRenames,
|
|
340
341
|
consumerFilePaths: consumerFilePaths.map((p) => resolve(p)),
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { compile } from "stylis";
|
|
2
|
+
//#region src/internal/styled-css.ts
|
|
3
|
+
/** Matches `__SC_EXPR_N__` and captures the slot index in group 1. */
|
|
4
|
+
const PLACEHOLDER_RE = /__SC_EXPR_(\d+)__/;
|
|
5
|
+
function parseStyledTemplateLiteral(template) {
|
|
6
|
+
const parts = [];
|
|
7
|
+
const slots = [];
|
|
8
|
+
for (let i = 0; i < template.quasis.length; i++) {
|
|
9
|
+
const quasi = template.quasis[i];
|
|
10
|
+
parts.push(quasi.value.raw);
|
|
11
|
+
const expr = template.expressions[i];
|
|
12
|
+
if (!expr) continue;
|
|
13
|
+
const placeholder = makeInterpolationPlaceholder(i);
|
|
14
|
+
const startOffset = parts.join("").length;
|
|
15
|
+
parts.push(placeholder);
|
|
16
|
+
const endOffset = parts.join("").length;
|
|
17
|
+
slots.push({
|
|
18
|
+
index: i,
|
|
19
|
+
placeholder,
|
|
20
|
+
expression: expr,
|
|
21
|
+
startOffset,
|
|
22
|
+
endOffset
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const rawCss = parts.join("");
|
|
26
|
+
return {
|
|
27
|
+
rawCss,
|
|
28
|
+
slots,
|
|
29
|
+
stylisAst: compile(terminateStandaloneInterpolationStatements(rawCss))
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function terminateStandaloneInterpolationStatements(css) {
|
|
33
|
+
let parenDepth = 0;
|
|
34
|
+
const lines = css.split(/(?<=\n)/);
|
|
35
|
+
const depthsBeforeLine = [];
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
depthsBeforeLine.push(parenDepth);
|
|
38
|
+
parenDepth = updateParenDepth(parenDepth, line);
|
|
39
|
+
}
|
|
40
|
+
return lines.map((line, index) => {
|
|
41
|
+
return depthsBeforeLine[index] === 0 && /^\s*__SC_EXPR_\d+__\s*$/.test(line) && isBeforeAtRule(lines, index) ? line.replace(/(\s*)$/, ";$1") : line;
|
|
42
|
+
}).join("");
|
|
43
|
+
}
|
|
44
|
+
function makeInterpolationPlaceholder(index) {
|
|
45
|
+
return `__SC_EXPR_${index}__`;
|
|
46
|
+
}
|
|
47
|
+
function isBeforeAtRule(lines, startIndex) {
|
|
48
|
+
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
49
|
+
const trimmed = lines[i].trim();
|
|
50
|
+
if (!trimmed || /^__SC_EXPR_\d+__\s*;?$/.test(trimmed)) continue;
|
|
51
|
+
return trimmed.startsWith("@");
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
function updateParenDepth(startDepth, line) {
|
|
56
|
+
let depth = startDepth;
|
|
57
|
+
let inString = false;
|
|
58
|
+
for (let i = 0; i < line.length; i++) {
|
|
59
|
+
const ch = line[i];
|
|
60
|
+
if ((ch === "\"" || ch === "'") && line[i - 1] !== "\\") {
|
|
61
|
+
if (!inString) inString = ch;
|
|
62
|
+
else if (inString === ch) inString = false;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (inString) continue;
|
|
66
|
+
if (ch === "(") depth++;
|
|
67
|
+
else if (ch === ")") depth = Math.max(0, depth - 1);
|
|
68
|
+
}
|
|
69
|
+
return depth;
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
//#region src/internal/utilities/jsx-static-literal.ts
|
|
73
|
+
function readStaticJsxLiteral(attr) {
|
|
74
|
+
if (!isObjectRecord(attr) || attr.type !== "JSXAttribute") return;
|
|
75
|
+
if (!("value" in attr) || attr.value == null) return true;
|
|
76
|
+
const directLiteral = readLiteralNodeValue(attr.value);
|
|
77
|
+
if (directLiteral !== void 0) return directLiteral;
|
|
78
|
+
if (!isObjectRecord(attr.value) || attr.value.type !== "JSXExpressionContainer") return;
|
|
79
|
+
return readLiteralNodeValue(attr.value.expression);
|
|
80
|
+
}
|
|
81
|
+
function readLiteralNodeValue(node) {
|
|
82
|
+
if (!isObjectRecord(node)) return;
|
|
83
|
+
if (node.type === "StringLiteral" || node.type === "NumericLiteral" || node.type === "BooleanLiteral") return isStaticLiteral(node.value) ? node.value : void 0;
|
|
84
|
+
if (node.type === "Literal") return isStaticLiteral(node.value) ? node.value : void 0;
|
|
85
|
+
if (node.type === "UnaryExpression" && node.operator === "-") {
|
|
86
|
+
const value = readLiteralNodeValue(node.argument);
|
|
87
|
+
return typeof value === "number" ? -value : void 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function isObjectRecord(value) {
|
|
91
|
+
return typeof value === "object" && value !== null;
|
|
92
|
+
}
|
|
93
|
+
function isStaticLiteral(value) {
|
|
94
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/internal/utilities/prop-usage.ts
|
|
98
|
+
const KNOWN_NON_ELEMENT_PROPS = new Set([
|
|
99
|
+
"className",
|
|
100
|
+
"style",
|
|
101
|
+
"as",
|
|
102
|
+
"ref",
|
|
103
|
+
"forwardedAs",
|
|
104
|
+
"key",
|
|
105
|
+
"children"
|
|
106
|
+
]);
|
|
107
|
+
function createComponentPropUsageInfo(name) {
|
|
108
|
+
return {
|
|
109
|
+
componentName: name,
|
|
110
|
+
usageCount: 0,
|
|
111
|
+
hasUnknownUsage: false,
|
|
112
|
+
props: {}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function mergeComponentPropUsage(info, usage) {
|
|
116
|
+
info.usageCount += 1;
|
|
117
|
+
if (usage.hasSpread) info.hasUnknownUsage = true;
|
|
118
|
+
const presentProps = new Set(Object.keys(usage.props));
|
|
119
|
+
for (const [propName, propInfo] of Object.entries(info.props)) if (!presentProps.has(propName)) propInfo.omittedCount += 1;
|
|
120
|
+
for (const [propName, value] of Object.entries(usage.props)) {
|
|
121
|
+
const propInfo = info.props[propName] ?? (info.props[propName] = {
|
|
122
|
+
values: [],
|
|
123
|
+
hasUnknown: false,
|
|
124
|
+
usageCount: 0,
|
|
125
|
+
omittedCount: info.usageCount - 1
|
|
126
|
+
});
|
|
127
|
+
propInfo.usageCount += 1;
|
|
128
|
+
if (value.kind === "unknown") {
|
|
129
|
+
propInfo.hasUnknown = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (!propInfo.values.some((existing) => existing === value.value)) propInfo.values.push(value.value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//#endregion
|
|
136
|
+
export { PLACEHOLDER_RE as a, readStaticJsxLiteral as i, createComponentPropUsageInfo as n, parseStyledTemplateLiteral as o, mergeComponentPropUsage as r, terminateStandaloneInterpolationStatements as s, KNOWN_NON_ELEMENT_PROPS as t };
|