svelte-ag 1.2.8 → 1.3.1

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.
Files changed (61) hide show
  1. package/dist/api/form.svelte.d.ts +7 -10
  2. package/dist/api/form.svelte.d.ts.map +1 -1
  3. package/dist/api/form.svelte.js +6 -9
  4. package/dist/api/query/entrypoint.svelte.d.ts +14 -6
  5. package/dist/api/query/entrypoint.svelte.d.ts.map +1 -1
  6. package/dist/api/query/entrypoint.svelte.js +11 -5
  7. package/dist/api/query/entrypoint.unit.test.js +23 -25
  8. package/dist/api/query/query.svelte.d.ts +4 -5
  9. package/dist/api/query/query.svelte.d.ts.map +1 -1
  10. package/dist/api/query/query.svelte.js +8 -12
  11. package/dist/api/query/query.unit.test.js +21 -30
  12. package/dist/api/query/utils.svelte.d.ts +8 -2
  13. package/dist/api/query/utils.svelte.d.ts.map +1 -1
  14. package/dist/api/query/utils.svelte.js +5 -4
  15. package/dist/bin/build-tailwind-manifest/build-tailwind-manifest.unit.test.d.ts.map +1 -0
  16. package/dist/bin/build-tailwind-manifest/build-tailwind-manifest.unit.test.js +386 -0
  17. package/dist/bin/build-tailwind-manifest/cli.d.ts +2 -0
  18. package/dist/bin/build-tailwind-manifest/cli.d.ts.map +1 -0
  19. package/dist/bin/build-tailwind-manifest/cli.js +122 -0
  20. package/dist/bin/build-tailwind-manifest/graph.d.ts +9 -0
  21. package/dist/bin/build-tailwind-manifest/graph.d.ts.map +1 -0
  22. package/dist/bin/build-tailwind-manifest/graph.js +405 -0
  23. package/dist/bin/build-tailwind-manifest/index.d.ts +1 -0
  24. package/dist/bin/build-tailwind-manifest/index.js +6 -0
  25. package/dist/bin/build-tailwind-manifest/manifest-generator.d.ts +7 -0
  26. package/dist/bin/build-tailwind-manifest/manifest-generator.d.ts.map +1 -0
  27. package/dist/bin/build-tailwind-manifest/manifest-generator.js +85 -0
  28. package/dist/bin/build-tailwind-manifest/path-utils.d.ts +6 -0
  29. package/dist/bin/build-tailwind-manifest/path-utils.d.ts.map +1 -0
  30. package/dist/bin/build-tailwind-manifest/path-utils.js +41 -0
  31. package/dist/bin/build-tailwind-manifest/types.d.ts +15 -0
  32. package/dist/bin/build-tailwind-manifest/types.d.ts.map +1 -0
  33. package/dist/bin/build-tailwind-manifest/types.js +1 -0
  34. package/dist/index.d.ts +29 -19
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/tailwind-sources.manifest.jsonc +193 -3
  37. package/dist/vite/vite-plugin-component-source-collector.d.ts.map +1 -1
  38. package/dist/vite/vite-plugin-component-source-collector.js +1 -6
  39. package/package.json +7 -5
  40. package/src/lib/api/form.svelte.ts +27 -34
  41. package/src/lib/api/query/entrypoint.svelte.ts +28 -11
  42. package/src/lib/api/query/entrypoint.unit.test.ts +25 -27
  43. package/src/lib/api/query/query.svelte.ts +18 -17
  44. package/src/lib/api/query/query.unit.test.ts +25 -35
  45. package/src/lib/api/query/utils.svelte.ts +5 -4
  46. package/src/lib/bin/build-tailwind-manifest/build-tailwind-manifest.unit.test.ts +591 -0
  47. package/src/lib/bin/build-tailwind-manifest/cli.ts +147 -0
  48. package/src/lib/bin/build-tailwind-manifest/graph.ts +521 -0
  49. package/src/lib/bin/build-tailwind-manifest/index.ts +8 -0
  50. package/src/lib/bin/build-tailwind-manifest/manifest-generator.ts +119 -0
  51. package/src/lib/bin/build-tailwind-manifest/path-utils.ts +53 -0
  52. package/src/lib/bin/build-tailwind-manifest/types.ts +18 -0
  53. package/src/lib/vite/vite-plugin-component-source-collector.ts +1 -6
  54. package/dist/bin/build-tailwind-manifest.d.ts +0 -15
  55. package/dist/bin/build-tailwind-manifest.d.ts.map +0 -1
  56. package/dist/bin/build-tailwind-manifest.js +0 -581
  57. package/dist/bin/build-tailwind-manifest.unit.test.d.ts.map +0 -1
  58. package/dist/bin/build-tailwind-manifest.unit.test.js +0 -208
  59. package/src/lib/bin/build-tailwind-manifest.ts +0 -757
  60. package/src/lib/bin/build-tailwind-manifest.unit.test.ts +0 -309
  61. /package/dist/bin/{build-tailwind-manifest.unit.test.d.ts → build-tailwind-manifest/build-tailwind-manifest.unit.test.d.ts} +0 -0
@@ -0,0 +1,405 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { Visitor, parseSync } from 'oxc-parser';
4
+ import { parse as parseSvelte } from 'svelte/compiler';
5
+ import { ensureRelativeManifestSourcePath } from '../../vite/tailwind-sources-manifest.js';
6
+ import { isPathInside, isRelativeSpecifier, resolveLocalImportPath, toPosixPath } from './path-utils.js';
7
+ const CLASS_COLLECTOR_CALLS = new Set(['cn', 'clsx', 'cva', 'tv']);
8
+ export function createGraphScanner(packageDir) {
9
+ const analysisCache = new Map();
10
+ const graphScanCache = new Map();
11
+ const symbolTargetCache = new Map();
12
+ const resolvedImportCache = new Map();
13
+ const resolveCachedImportPath = (specifier, importerPath) => {
14
+ const cacheKey = `${importerPath}\0${specifier}`;
15
+ const cached = resolvedImportCache.get(cacheKey);
16
+ if (cached !== undefined)
17
+ return cached;
18
+ const resolved = resolveLocalImportPath(specifier, importerPath);
19
+ resolvedImportCache.set(cacheKey, resolved);
20
+ return resolved;
21
+ };
22
+ const analyzeFile = (filePath) => {
23
+ let cached = analysisCache.get(filePath);
24
+ if (!cached) {
25
+ cached = (async () => {
26
+ const source = await readFile(filePath, 'utf8');
27
+ const classes = new Set();
28
+ const localSpecifiers = new Set();
29
+ const directLocalExports = new Set();
30
+ const importBindings = new Map();
31
+ const indirectExports = [];
32
+ const importedLocalExports = new Map();
33
+ collectClassNamesFromSource(filePath, source, classes);
34
+ for (const statement of getModuleStatements(filePath, source)) {
35
+ const specifier = getModuleRequest(statement);
36
+ if (statement.type === 'ImportDeclaration') {
37
+ if (specifier && isRelativeSpecifier(specifier) && statement.importKind !== 'type') {
38
+ localSpecifiers.add(specifier);
39
+ }
40
+ collectImportBindings(statement, importBindings);
41
+ continue;
42
+ }
43
+ if (specifier && isRelativeSpecifier(specifier) && statement.exportKind !== 'type') {
44
+ localSpecifiers.add(specifier);
45
+ if (statement.type === 'ExportAllDeclaration' && statement.exported === null) {
46
+ indirectExports.push({ kind: 'all', specifier });
47
+ continue;
48
+ }
49
+ if (statement.type === 'ExportAllDeclaration') {
50
+ const exportName = getNodeName(statement.exported);
51
+ if (exportName) {
52
+ indirectExports.push({ kind: 'namespace', exportName, specifier });
53
+ }
54
+ continue;
55
+ }
56
+ for (const specifierNode of statement.specifiers) {
57
+ if ('exportKind' in specifierNode && specifierNode.exportKind === 'type')
58
+ continue;
59
+ const exportName = getNodeName(specifierNode.exported) ?? getNodeName(specifierNode.local);
60
+ if (exportName) {
61
+ indirectExports.push({ kind: 'named', exportName, specifier });
62
+ }
63
+ }
64
+ continue;
65
+ }
66
+ if (statement.type !== 'ExportNamedDeclaration' || statement.exportKind === 'type') {
67
+ continue;
68
+ }
69
+ collectExportedDeclarationNames(statement.declaration, directLocalExports);
70
+ for (const specifierNode of statement.specifiers) {
71
+ if ('exportKind' in specifierNode && specifierNode.exportKind === 'type')
72
+ continue;
73
+ const exportName = getNodeName(specifierNode.exported) ?? getNodeName(specifierNode.local);
74
+ const localName = getNodeName(specifierNode.local);
75
+ if (exportName && localName) {
76
+ importedLocalExports.set(exportName, localName);
77
+ directLocalExports.add(exportName);
78
+ }
79
+ }
80
+ }
81
+ for (const match of source.matchAll(/@import\s+['"]([^'"]+)['"]/g)) {
82
+ if (match[1] && isRelativeSpecifier(match[1])) {
83
+ localSpecifiers.add(match[1]);
84
+ }
85
+ }
86
+ return {
87
+ classes,
88
+ manifestSourcePath: filePath.endsWith('.css')
89
+ ? ensureRelativeManifestSourcePath(toPosixPath(path.relative(packageDir, filePath)))
90
+ : null,
91
+ localSpecifiers: [...localSpecifiers],
92
+ directLocalExports,
93
+ importBindings,
94
+ indirectExports,
95
+ importedLocalExports
96
+ };
97
+ })();
98
+ analysisCache.set(filePath, cached);
99
+ }
100
+ return cached;
101
+ };
102
+ const scanFromRoot = async (entryFile, visiting) => {
103
+ if (visiting.has(entryFile) || !isPathInside(packageDir, entryFile)) {
104
+ return createEmptyScan();
105
+ }
106
+ const cached = graphScanCache.get(entryFile);
107
+ if (cached) {
108
+ return cloneGraphScan(cached);
109
+ }
110
+ const nextVisiting = new Set(visiting);
111
+ nextVisiting.add(entryFile);
112
+ const analysis = await analyzeFile(entryFile);
113
+ const scan = {
114
+ classes: new Set(analysis.classes),
115
+ sources: analysis.manifestSourcePath ? new Set([analysis.manifestSourcePath]) : new Set()
116
+ };
117
+ for (const specifier of analysis.localSpecifiers) {
118
+ const resolvedPath = resolveCachedImportPath(specifier, entryFile);
119
+ if (!resolvedPath)
120
+ continue;
121
+ mergeGraphScan(scan, await scanFromRoot(resolvedPath, nextVisiting));
122
+ }
123
+ graphScanCache.set(entryFile, cloneGraphScan(scan));
124
+ return scan;
125
+ };
126
+ const readTargets = async (entryFile, visiting) => {
127
+ if (visiting.has(entryFile))
128
+ return new Map();
129
+ const cached = symbolTargetCache.get(entryFile);
130
+ if (cached) {
131
+ return new Map(cached);
132
+ }
133
+ const nextVisiting = new Set(visiting);
134
+ nextVisiting.add(entryFile);
135
+ const analysis = await analyzeFile(entryFile);
136
+ const symbolTargets = new Map();
137
+ for (const exportNode of analysis.indirectExports) {
138
+ const targetFile = resolveCachedImportPath(exportNode.specifier, entryFile);
139
+ if (!targetFile)
140
+ continue;
141
+ if (exportNode.kind === 'all') {
142
+ for (const [symbolName, nestedTargetFile] of await readTargets(targetFile, nextVisiting)) {
143
+ if (!symbolTargets.has(symbolName)) {
144
+ symbolTargets.set(symbolName, nestedTargetFile);
145
+ }
146
+ }
147
+ continue;
148
+ }
149
+ if (!symbolTargets.has(exportNode.exportName)) {
150
+ symbolTargets.set(exportNode.exportName, targetFile);
151
+ }
152
+ }
153
+ for (const [exportName, localName] of analysis.importedLocalExports) {
154
+ const specifier = analysis.importBindings.get(localName);
155
+ if (!specifier || symbolTargets.has(exportName))
156
+ continue;
157
+ const targetFile = resolveCachedImportPath(specifier, entryFile);
158
+ if (targetFile) {
159
+ symbolTargets.set(exportName, targetFile);
160
+ }
161
+ }
162
+ for (const exportName of analysis.directLocalExports) {
163
+ if (!symbolTargets.has(exportName)) {
164
+ symbolTargets.set(exportName, entryFile);
165
+ }
166
+ }
167
+ symbolTargetCache.set(entryFile, new Map(symbolTargets));
168
+ return symbolTargets;
169
+ };
170
+ return {
171
+ async scanFileGraph(entryFiles) {
172
+ const scan = createEmptyScan();
173
+ for (const entryFile of entryFiles) {
174
+ mergeGraphScan(scan, await scanFromRoot(entryFile, new Set()));
175
+ }
176
+ return scan;
177
+ },
178
+ async readEntrySymbolTargets(entryFile) {
179
+ return readTargets(entryFile, new Set());
180
+ }
181
+ };
182
+ }
183
+ export async function readEntrySymbolTargets(entryFile, visited = new Set()) {
184
+ if (visited.has(entryFile))
185
+ return new Map();
186
+ void visited;
187
+ const scanner = createGraphScanner(path.dirname(entryFile));
188
+ return scanner.readEntrySymbolTargets(entryFile);
189
+ }
190
+ export async function scanFileGraph(entryFiles, packageDir) {
191
+ return createGraphScanner(packageDir).scanFileGraph(entryFiles);
192
+ }
193
+ function createEmptyScan() {
194
+ return { classes: new Set(), sources: new Set() };
195
+ }
196
+ function cloneGraphScan(scan) {
197
+ return { classes: new Set(scan.classes), sources: new Set(scan.sources) };
198
+ }
199
+ function mergeGraphScan(target, source) {
200
+ for (const className of source.classes)
201
+ target.classes.add(className);
202
+ for (const sourcePath of source.sources)
203
+ target.sources.add(sourcePath);
204
+ }
205
+ function collectClassNamesFromSource(filePath, source, out) {
206
+ const collectTailwindStrings = (snippet) => {
207
+ const program = parseSync(filePath, snippet, getOxcParserOptions(filePath)).program;
208
+ new Visitor({
209
+ CallExpression(node) {
210
+ const calleeName = getCallExpressionName(node);
211
+ if (calleeName !== '' && CLASS_COLLECTOR_CALLS.has(calleeName)) {
212
+ collectStringLiteralsFromExpression(node, out);
213
+ }
214
+ },
215
+ Property(node) {
216
+ if (!isObjectPropertyNode(node))
217
+ return;
218
+ const keyName = getObjectPropertyKeyName(node);
219
+ if (keyName && /class/i.test(keyName)) {
220
+ collectStringLiteralsFromExpression(node.value, out);
221
+ }
222
+ }
223
+ }).visit(program);
224
+ };
225
+ const markupSource = filePath.endsWith('.svelte') ? source.replace(/<!--[\s\S]*?-->/g, '') : source;
226
+ for (const match of markupSource.matchAll(/(?:class|className)\s*=\s*(['"`])([\s\S]*?)\1/g)) {
227
+ for (const token of (match[2] ?? '').split(/\s+/)) {
228
+ if (token !== '' && !token.includes('${'))
229
+ out.add(token);
230
+ }
231
+ }
232
+ for (const match of markupSource.matchAll(/(?:class|className)\s*=\s*\{([\s\S]*?)\}/g)) {
233
+ const expression = match[1]?.trim();
234
+ if (expression) {
235
+ collectTailwindStrings(`(${expression})`);
236
+ }
237
+ }
238
+ for (const scriptBlock of getModuleSnippets(filePath, source)) {
239
+ collectTailwindStrings(scriptBlock);
240
+ }
241
+ }
242
+ function getModuleSnippets(filePath, source) {
243
+ if (!filePath.endsWith('.svelte')) {
244
+ return [source];
245
+ }
246
+ try {
247
+ const ast = parseSvelte(source, { filename: filePath, modern: true });
248
+ return [ast.module, ast.instance].filter(Boolean).map((script) => {
249
+ const content = script.content;
250
+ return source.slice(content.start, content.end);
251
+ });
252
+ }
253
+ catch {
254
+ return [source];
255
+ }
256
+ }
257
+ function getModuleStatements(filePath, source) {
258
+ return getModuleSnippets(filePath, source).flatMap((snippet) => parseSync(filePath, snippet, getOxcParserOptions(filePath)).program.body.filter(isModuleStatement));
259
+ }
260
+ function getOxcParserOptions(filePath) {
261
+ return {
262
+ lang: filePath.endsWith('.js') || filePath.endsWith('.mjs') || filePath.endsWith('.cjs')
263
+ ? 'js'
264
+ : filePath.endsWith('.jsx')
265
+ ? 'jsx'
266
+ : filePath.endsWith('.tsx')
267
+ ? 'tsx'
268
+ : filePath.endsWith('.d.ts')
269
+ ? 'dts'
270
+ : 'ts',
271
+ sourceType: 'module'
272
+ };
273
+ }
274
+ function isModuleStatement(statement) {
275
+ return (statement.type === 'ImportDeclaration' ||
276
+ statement.type === 'ExportNamedDeclaration' ||
277
+ statement.type === 'ExportAllDeclaration');
278
+ }
279
+ function collectExportedDeclarationNames(declaration, exportNames) {
280
+ if (!declaration)
281
+ return;
282
+ if ('id' in declaration && declaration.id) {
283
+ const declarationName = getNodeName(declaration.id);
284
+ if (declarationName)
285
+ exportNames.add(declarationName);
286
+ return;
287
+ }
288
+ if (declaration.type !== 'VariableDeclaration')
289
+ return;
290
+ for (const declarator of declaration.declarations) {
291
+ collectBindingNames(declarator.id, exportNames);
292
+ }
293
+ }
294
+ function collectBindingNames(node, names) {
295
+ const nodeName = getNodeName(node);
296
+ if (nodeName) {
297
+ names.add(nodeName);
298
+ return;
299
+ }
300
+ if ('properties' in node && Array.isArray(node.properties)) {
301
+ for (const property of node.properties) {
302
+ if (!property || typeof property !== 'object')
303
+ continue;
304
+ if ('value' in property && property.value && typeof property.value === 'object') {
305
+ collectBindingNames(property.value, names);
306
+ }
307
+ else if ('key' in property && property.key && typeof property.key === 'object') {
308
+ collectBindingNames(property.key, names);
309
+ }
310
+ }
311
+ }
312
+ if ('elements' in node && Array.isArray(node.elements)) {
313
+ for (const element of node.elements) {
314
+ if (element && typeof element === 'object') {
315
+ collectBindingNames(element, names);
316
+ }
317
+ }
318
+ }
319
+ }
320
+ function collectImportBindings(statement, importBindings) {
321
+ const specifier = getModuleRequest(statement);
322
+ if (!specifier || !isRelativeSpecifier(specifier) || statement.importKind === 'type')
323
+ return;
324
+ for (const specifierNode of statement.specifiers ?? []) {
325
+ if (specifierNode.type === 'ImportSpecifier' && specifierNode.importKind === 'type') {
326
+ continue;
327
+ }
328
+ importBindings.set(specifierNode.local.name, specifier);
329
+ }
330
+ }
331
+ function getModuleRequest(statement) {
332
+ if (statement.source === null)
333
+ return null;
334
+ return typeof statement.source.value === 'string' ? statement.source.value : null;
335
+ }
336
+ function getNodeName(node) {
337
+ if (node === null)
338
+ return null;
339
+ if ('name' in node && typeof node.name === 'string')
340
+ return node.name;
341
+ if ('value' in node && typeof node.value === 'string')
342
+ return node.value;
343
+ return null;
344
+ }
345
+ function getCallExpressionName(node) {
346
+ if (node.callee.type === 'Identifier') {
347
+ return node.callee.name;
348
+ }
349
+ if (node.callee.type === 'MemberExpression' && !node.callee.computed && node.callee.property.type === 'Identifier') {
350
+ return node.callee.property.name;
351
+ }
352
+ return '';
353
+ }
354
+ function getObjectPropertyKeyName(node) {
355
+ if (node.key.type === 'Identifier') {
356
+ return node.key.name;
357
+ }
358
+ if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
359
+ return node.key.value;
360
+ }
361
+ return null;
362
+ }
363
+ function isObjectPropertyNode(node) {
364
+ return node.type === 'Property' && 'value' in node && 'method' in node;
365
+ }
366
+ function collectStringLiteralsFromExpression(expression, out) {
367
+ new Visitor({
368
+ Literal(literal) {
369
+ if (literal.type === 'Literal' && typeof literal.value === 'string') {
370
+ addClassTokens(literal, out);
371
+ }
372
+ },
373
+ TemplateLiteral(template) {
374
+ if (template.expressions.length === 0) {
375
+ addClassTokens(template, out);
376
+ }
377
+ }
378
+ }).visit(createProgramFromExpression(expression));
379
+ }
380
+ function addClassTokens(node, out) {
381
+ const rawValue = node.type === 'Literal' ? node.value : node.quasis.map((quasi) => quasi.value.cooked ?? quasi.value.raw).join('');
382
+ if (typeof rawValue !== 'string')
383
+ return;
384
+ for (const token of rawValue.split(/\s+/)) {
385
+ if (token !== '' && !token.includes('${'))
386
+ out.add(token);
387
+ }
388
+ }
389
+ function createProgramFromExpression(expression) {
390
+ const statement = {
391
+ type: 'ExpressionStatement',
392
+ expression,
393
+ directive: null,
394
+ start: expression.start,
395
+ end: expression.end
396
+ };
397
+ return {
398
+ type: 'Program',
399
+ body: [statement],
400
+ sourceType: 'module',
401
+ hashbang: null,
402
+ start: expression.start,
403
+ end: expression.end
404
+ };
405
+ }
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,6 @@
1
+ import process from 'node:process';
2
+ import { main } from './cli.js';
3
+ void main().catch((error) => {
4
+ console.error(error);
5
+ process.exitCode = 1;
6
+ });
@@ -0,0 +1,7 @@
1
+ import type { GeneratorOptions } from './types.js';
2
+ export declare function generateTailwindManifestForPackage(packageDir: string, options: GeneratorOptions): Promise<{
3
+ didWrite: boolean;
4
+ outputFile: string;
5
+ exportCount: number;
6
+ }>;
7
+ //# sourceMappingURL=manifest-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest-generator.d.ts","sourceRoot":"","sources":["../../../src/lib/bin/build-tailwind-manifest/manifest-generator.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAA6B,MAAM,YAAY,CAAC;AAE9E,wBAAsB,kCAAkC,CACtD,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAiCzE"}
@@ -0,0 +1,85 @@
1
+ import path from 'node:path';
2
+ import { readPackageJson, writeIfDifferent } from 'ts-ag';
3
+ import { getTailwindSourcesManifestPath, serializeTailwindSourceManifest, shouldIncludeManifestExport } from '../../vite/tailwind-sources-manifest.js';
4
+ import { createGraphScanner } from './graph.js';
5
+ import { resolvePackageEntryFile } from './path-utils.js';
6
+ export async function generateTailwindManifestForPackage(packageDir, options) {
7
+ const packageJson = (await readPackageJson(path.join(packageDir, 'package.json')));
8
+ if (!packageJson)
9
+ throw new Error(`No package.json found in ${packageDir}`);
10
+ const manifest = { version: 1, exports: {} };
11
+ const exports = collectPackageExportEntries(packageJson.exports).filter(([exportKey]) => shouldIncludeManifestExport(exportKey, options.exportFilters));
12
+ const graphScanner = createGraphScanner(packageDir);
13
+ await Promise.all(exports.map(async ([exportKey, exportTarget]) => {
14
+ if (exportKey.includes('*') || hasWildcardTarget(exportTarget)) {
15
+ console.warn(`[tailwind-manifest] Skipping wildcard export ${exportKey} in ${packageDir}`);
16
+ }
17
+ else {
18
+ const entryFiles = collectRuntimeTargets(exportTarget)
19
+ .map((target) => resolvePackageEntryFile(packageDir, target))
20
+ .filter((targetPath) => targetPath !== null);
21
+ if (entryFiles.length === 0)
22
+ return;
23
+ const manifestEntry = toManifestLeaf(await graphScanner.scanFileGraph(entryFiles));
24
+ const symbols = await collectExportSymbols(entryFiles, graphScanner);
25
+ manifest.exports[exportKey] = Object.keys(symbols).length > 0 ? { ...manifestEntry, symbols } : manifestEntry;
26
+ }
27
+ }));
28
+ const outputFile = getTailwindSourcesManifestPath(packageDir, packageJson);
29
+ const didWrite = await writeIfDifferent(outputFile, serializeTailwindSourceManifest(manifest));
30
+ return { didWrite, outputFile, exportCount: Object.keys(manifest.exports).length };
31
+ }
32
+ async function collectExportSymbols(entryFiles, graphScanner) {
33
+ const symbols = new Map();
34
+ for (const entryFile of entryFiles) {
35
+ const targets = await graphScanner.readEntrySymbolTargets(entryFile);
36
+ await Promise.all(targets.entries().map(async ([symbolName, targetFile]) => {
37
+ const scan = await graphScanner.scanFileGraph([targetFile]);
38
+ const existing = symbols.get(symbolName);
39
+ if (existing) {
40
+ for (const className of scan.classes)
41
+ existing.classes.add(className);
42
+ for (const sourcePath of scan.sources)
43
+ existing.sources.add(sourcePath);
44
+ }
45
+ else {
46
+ symbols.set(symbolName, { classes: new Set(scan.classes), sources: new Set(scan.sources) });
47
+ }
48
+ }));
49
+ }
50
+ return Object.fromEntries([...symbols.entries()]
51
+ .sort(([left], [right]) => left.localeCompare(right))
52
+ .map(([symbolName, scan]) => [symbolName, toManifestLeaf(scan)]));
53
+ }
54
+ function toManifestLeaf(scan) {
55
+ return { classes: [...scan.classes].sort(), sources: [...scan.sources].sort() };
56
+ }
57
+ function collectRuntimeTargets(target) {
58
+ if (target === null)
59
+ return [];
60
+ if (typeof target === 'string') {
61
+ return target.endsWith('.d.ts') ? [] : [target];
62
+ }
63
+ if (Array.isArray(target)) {
64
+ return target.flatMap(collectRuntimeTargets);
65
+ }
66
+ return Object.entries(target).flatMap(([key, value]) => (key === 'types' ? [] : collectRuntimeTargets(value)));
67
+ }
68
+ function hasWildcardTarget(target) {
69
+ if (target === null)
70
+ return false;
71
+ return typeof target === 'string'
72
+ ? target.includes('*')
73
+ : Array.isArray(target)
74
+ ? target.some(hasWildcardTarget)
75
+ : Object.values(target).some(hasWildcardTarget);
76
+ }
77
+ function collectPackageExportEntries(exports) {
78
+ if (exports === undefined)
79
+ return [];
80
+ if (exports === null || typeof exports === 'string' || Array.isArray(exports))
81
+ return [['.', exports]];
82
+ const entries = Object.entries(exports);
83
+ const hasSubpathExports = entries.some(([key]) => key === '.' || key.startsWith('./'));
84
+ return hasSubpathExports ? entries : [['.', exports]];
85
+ }
@@ -0,0 +1,6 @@
1
+ export declare function isRelativeSpecifier(specifier: string): boolean;
2
+ export declare function resolveLocalImportPath(specifier: string, importerPath: string): string | null;
3
+ export declare function resolvePackageEntryFile(packageDir: string, entryTarget: string): string | null;
4
+ export declare function isPathInside(parentPath: string, childPath: string): boolean;
5
+ export declare function toPosixPath(filePath: string): string;
6
+ //# sourceMappingURL=path-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/bin/build-tailwind-manifest/path-utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE7F;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9F;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAG3E;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,41 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ export function isRelativeSpecifier(specifier) {
4
+ return specifier.startsWith('./') || specifier.startsWith('../') || specifier.startsWith('/');
5
+ }
6
+ export function resolveLocalImportPath(specifier, importerPath) {
7
+ return resolveFileCandidate(path.resolve(path.dirname(importerPath), specifier.split(/[?#]/, 1)[0] ?? specifier));
8
+ }
9
+ export function resolvePackageEntryFile(packageDir, entryTarget) {
10
+ return resolveFileCandidate(path.resolve(packageDir, entryTarget.startsWith('./') ? entryTarget : `./${entryTarget}`));
11
+ }
12
+ export function isPathInside(parentPath, childPath) {
13
+ const relativePath = path.relative(parentPath, childPath);
14
+ return relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath));
15
+ }
16
+ export function toPosixPath(filePath) {
17
+ return filePath.replaceAll('\\', '/');
18
+ }
19
+ function resolveFileCandidate(targetPath) {
20
+ for (const candidate of [
21
+ ...buildBaseCandidates(targetPath),
22
+ ...buildBaseCandidates(path.join(targetPath, 'index'))
23
+ ]) {
24
+ if (existsSync(candidate) && statSync(candidate).isFile()) {
25
+ return candidate;
26
+ }
27
+ }
28
+ return null;
29
+ }
30
+ function buildBaseCandidates(basePath) {
31
+ const candidates = new Set([basePath, `${basePath}.js`, `${basePath}.mjs`, `${basePath}.cjs`]);
32
+ for (const candidateBase of [basePath.replace(/\.(?:mjs|cjs|js)$/i, ''), basePath]) {
33
+ candidates.add(`${candidateBase}.ts`);
34
+ candidates.add(`${candidateBase}.tsx`);
35
+ candidates.add(`${candidateBase}.jsx`);
36
+ candidates.add(`${candidateBase}.svelte`);
37
+ candidates.add(`${candidateBase}.svelte.ts`);
38
+ candidates.add(`${candidateBase}.css`);
39
+ }
40
+ return [...candidates];
41
+ }
@@ -0,0 +1,15 @@
1
+ import type { TailwindSourceManifestLeaf } from '../../vite/tailwind-sources-manifest.js';
2
+ export type GeneratorOptions = {
3
+ exportFilters: string[];
4
+ };
5
+ export type GraphScan = {
6
+ classes: Set<string>;
7
+ sources: Set<string>;
8
+ };
9
+ export type CliOptions = {
10
+ exportFilters: string[];
11
+ packagePatterns: string[];
12
+ watch: boolean;
13
+ };
14
+ export type SymbolManifest = Record<string, TailwindSourceManifestLeaf>;
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/bin/build-tailwind-manifest/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAC;AAE1F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};