From 023081d01fb70ea09b9e2fd1f7d76c5e49880ed9 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 02:02:28 +0100 Subject: [PATCH] Feature: `app.html` is now transformed. --- .changeset/chilly-news-jam.md | 5 ++ packages/skeleton-cli/package.json | 3 + .../migrate/migrations/skeleton-3/index.ts | 39 +++++++++--- .../transformers/transform-app.test.ts | 54 +++++++++++++++++ .../skeleton-3/transformers/transform-app.ts | 30 ++++++++++ .../transformers/transform-module.test.ts | 14 ++--- .../transformers/transform-module.ts | 15 ++--- .../transformers/transform-package.test.ts | 20 +++---- .../transformers/transform-package.ts | 15 ++--- .../transformers/transform-svelte.test.ts | 36 +++++------ .../transformers/transform-svelte.ts | 15 ++--- .../transform-tailwind-config.test.ts | 24 ++++---- .../transformers/transform-tailwind-config.ts | 60 ++++++++++++------- pnpm-lock.yaml | 23 +++++++ 14 files changed, 245 insertions(+), 108 deletions(-) create mode 100644 .changeset/chilly-news-jam.md create mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts create mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.ts diff --git a/.changeset/chilly-news-jam.md b/.changeset/chilly-news-jam.md new file mode 100644 index 000000000..8a4049def --- /dev/null +++ b/.changeset/chilly-news-jam.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: `app.html` is now transformed. diff --git a/packages/skeleton-cli/package.json b/packages/skeleton-cli/package.json index 1a99048dd..a3304491e 100644 --- a/packages/skeleton-cli/package.json +++ b/packages/skeleton-cli/package.json @@ -27,6 +27,7 @@ "test:watch": "vitest watch" }, "devDependencies": { + "@types/jsdom": "^21.1.7", "@types/node": "^22.1.0", "@types/semver": "^7.5.8", "type-fest": "^4.27.0", @@ -42,9 +43,11 @@ "detect-indent": "^7.0.1", "estree-walker": "^3.0.3", "fast-glob": "^3.3.1", + "jsdom": "^25.0.1", "latest-version": "^9.0.0", "magic-string": "^0.30.17", "package-manager-detector": "^0.2.8", + "parse5": "^7.2.1", "semver": "^7.6.3", "svelte": "^5.17.3", "ts-morph": "^25.0.0" diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/index.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/index.ts index c017fd845..d47364355 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/index.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/index.ts @@ -7,6 +7,8 @@ import { cli } from '../../../../index.js'; import { extname } from 'node:path'; import { transformSvelte } from './transformers/transform-svelte'; import { transformModule } from './transformers/transform-module'; +import { transformApp } from './transformers/transform-app'; +import { readFile, writeFile } from 'node:fs/promises'; export default async function (options: MigrateOptions) { const cwd = options.cwd ?? process.cwd(); @@ -19,8 +21,12 @@ export default async function (options: MigrateOptions) { matcher: 'tailwind.config.{js,mjs,ts,mts}', paths: await fg('tailwind.config.{js,mjs,ts,mts}', { cwd }) }; + const app = { + matcher: 'src/app.html', + paths: await fg('src/app.html', { cwd }) + }; - for (const file of [pkg, tailwindConfig]) { + for (const file of [pkg, tailwindConfig, app]) { if (file.paths.length === 0) { cli.error(`"${file.matcher}" not found in directory "${cwd}".`); } @@ -43,13 +49,26 @@ export default async function (options: MigrateOptions) { const packageSpinner = spinner(); packageSpinner.start(`Migrating ${pkg.matcher}...`); - await transformPackage(pkg.paths[0]); + const pkgCode = await readFile(pkg.paths[0], 'utf-8'); + const transformedPkg = await transformPackage(pkgCode); + await writeFile(pkg.paths[0], transformedPkg.code); packageSpinner.stop(`Successfully migrated ${pkg.matcher}`); - const tailwindConfigSpinner = spinner(); - tailwindConfigSpinner.start(`Migrating ${tailwindConfig.matcher}...`); - await transformTailwindConfig(tailwindConfig.paths[0]); - tailwindConfigSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`); + const tailwindSpinner = spinner(); + tailwindSpinner.start(`Migrating ${tailwindConfig.matcher}...`); + const tailwindCode = await readFile(tailwindConfig.paths[0], 'utf-8'); + const transformedTailwind = transformTailwindConfig(tailwindCode); + await writeFile(tailwindConfig.paths[0], transformedTailwind.code); + tailwindSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`); + + const theme = transformedTailwind.meta.themes.find((theme) => theme.type === 'preset'); + + const appSpinner = spinner(); + appSpinner.start(`Migrating ${app.matcher}...`); + const appCode = await readFile(app.paths[0], 'utf-8'); + const transformedApp = transformApp(appCode, theme?.name ?? 'cerberus'); + await writeFile(app.paths[0], transformedApp.code); + appSpinner.stop(`Successfully migrated ${app.matcher}`); const sourceFileMatcher = `{${sourceFolders.join(',')}}/**/*.{js,mjs,ts,mts,svelte}`; const sourceFiles = await fg(sourceFileMatcher, { cwd, ignore: ['node_modules', 'dist', 'build', 'public'] }); @@ -60,9 +79,13 @@ export default async function (options: MigrateOptions) { sourceFilesSpinner.message(`Migrating ${sourceFile}...`); const extension = extname(sourceFile); if (extension === '.svelte') { - await transformSvelte(sourceFile); + const svelteCode = await readFile(sourceFile, 'utf-8'); + const transformedSvelte = transformSvelte(svelteCode); + await writeFile(sourceFile, transformedSvelte.code); } else { - await transformModule(sourceFile); + const moduleCode = await readFile(sourceFile, 'utf-8'); + const transformedModule = transformModule(moduleCode); + await writeFile(sourceFile, transformedModule.code); } sourceFilesSpinner.message(`Successfully migrated ${sourceFile}`); } diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts new file mode 100644 index 000000000..3e1198392 --- /dev/null +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest'; +import { transformApp } from './transform-app.js'; + +describe('transformsApp', () => { + it('edits the `data-them` attribute when already present', () => { + expect( + transformApp( + ` + +foo + + + + `, + 'cerberus' + ) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + +foo + + + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it('adds the `data-theme` attribute ', () => { + expect( + transformApp( + ` + +foo + + + `, + 'cerberus' + ) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + +foo + + + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); +}); diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.ts new file mode 100644 index 000000000..7f7eae17e --- /dev/null +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.ts @@ -0,0 +1,30 @@ +import { AST, parse } from 'svelte/compiler'; +import { walk, type Node } from 'estree-walker'; +import MagicString from 'magic-string'; + +function transformApp(code: string, theme: string) { + const s = new MagicString(code); + const ast = parse(code, { + modern: true + }); + walk(ast.fragment as unknown as Node, { + enter(node: AST.SvelteNode) { + if (node.type === 'RegularElement' && node.name === 'body') { + const dataThemeAttribute = node.attributes.find((attribute) => { + return attribute.type === 'Attribute' && attribute.name === 'data-theme'; + }); + if (dataThemeAttribute) { + s.update(dataThemeAttribute.start, dataThemeAttribute.end, `data-theme="${theme}"`); + } else { + s.appendRight(node.start + ' { it('transforms imports', () => { expect( - transformModuleContent(` + transformModule(` import { Avatar } from "@skeletonlabs/skeleton"; Avatar; `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -23,10 +23,10 @@ Avatar; }); it('transforms classes in strings', () => { expect( - transformModuleContent(` + transformModule(` const foo = "rounded-token"; `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -38,12 +38,12 @@ const foo = "rounded"; }); it('does not transform classes in imports', () => { expect( - transformModuleContent(` + transformModule(` import foo from "rounded-token"; foo; `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.ts index 087894050..5b171de83 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.ts @@ -1,9 +1,8 @@ -import { readFile, writeFile } from 'node:fs/promises'; import { Node } from 'ts-morph'; import { transformClasses } from './transform-classes.js'; import { createSourceFile } from '../../../../../utility/create-source-file.js'; -function transformModuleContent(code: string) { +function transformModule(code: string) { const file = createSourceFile(code); for (const importDeclaration of file.getImportDeclarations()) { const moduleSpecifier = importDeclaration.getModuleSpecifier(); @@ -18,13 +17,9 @@ function transformModuleContent(code: string) { node.setLiteralValue(transformClasses(node.getLiteralValue())); }); file.fixUnusedIdentifiers(); - return file.getFullText(); + return { + code: file.getFullText() + }; } -async function transformModule(path: string) { - const code = await readFile(path, 'utf-8'); - const transformed = transformModuleContent(code); - await writeFile(path, transformed); -} - -export { transformModuleContent, transformModule }; +export { transformModule }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts index 0cfc86155..8ae995511 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts @@ -1,4 +1,4 @@ -import { transformPackageContent } from './transform-package.js'; +import { transformPackage } from './transform-package.js'; import getLatestVersion from 'latest-version'; import { describe, it, expect, vi } from 'vitest'; @@ -8,19 +8,19 @@ vi.mock('latest-version', () => { }; }); -describe('transformPackageContent', () => { +describe('transformPackage', () => { it('updates the "@skeletonlabs/tw-plugin" dependency', async () => { vi.mocked(getLatestVersion).mockReturnValue(Promise.resolve('3.0.0')); expect( ( - await transformPackageContent(` + await transformPackage(` { "dependencies": { "@skeletonlabs/tw-plugin": "^1.0.0" } } `) - ) + ).code .trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( @@ -40,14 +40,14 @@ describe('transformPackageContent', () => { expect( ( - await transformPackageContent(` + await transformPackage(` { "dependencies": { "@skeletonlabs/skeleton": "^2.0.0" } } `) - ) + ).code .trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( @@ -74,7 +74,7 @@ describe('transformPackageContent', () => { }); expect( ( - await transformPackageContent(` + await transformPackage(` { "dependencies": { "@skeletonlabs/tw-plugin": "^1.0.0", @@ -82,7 +82,7 @@ describe('transformPackageContent', () => { } } `) - ) + ).code .trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( @@ -102,14 +102,14 @@ describe('transformPackageContent', () => { vi.mocked(getLatestVersion).mockReturnValue(Promise.resolve('3.0.0')); expect( ( - await transformPackageContent(` + await transformPackage(` { "dependencies": { "@skeletonlabs/skeleton": "^3.0.0" } } `) - ) + ).code .trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.ts index d368d00b5..adf749e6d 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.ts @@ -1,11 +1,10 @@ -import { readFile, writeFile } from 'fs/promises'; import type { PackageJson } from 'type-fest'; import getLatestVersion from 'latest-version'; import { coerce, lt } from 'semver'; import { sortPropertiesAlphabetically } from '../../../../../utility/sort-properties-alphabetically'; import detectIndent from 'detect-indent'; -async function transformPackageContent(code: string) { +async function transformPackage(code: string) { const pkg = JSON.parse(code) as PackageJson; const skeletonVersion = await getLatestVersion('@skeletonlabs/skeleton', { version: '>=3.0.0-0 <4.0.0' }); const skeletonSvelteVersion = await getLatestVersion('@skeletonlabs/skeleton-svelte', { version: '>=1.0.0-0 <2.0.0' }); @@ -24,13 +23,9 @@ async function transformPackageContent(code: string) { } pkg[field] = sortPropertiesAlphabetically(pkg[field] as Record); } - return JSON.stringify(pkg, null, detectIndent(code).indent || '\t'); + return { + code: JSON.stringify(pkg, null, detectIndent(code).indent || '\t') + }; } -async function transformPackage(path: string) { - const code = await readFile(path, 'utf-8'); - const transformed = await transformPackageContent(code); - await writeFile(path, transformed); -} - -export { transformPackageContent, transformPackage }; +export { transformPackage }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts index e60eda6f6..fc094dc16 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts @@ -1,15 +1,15 @@ import { describe, expect, it } from 'vitest'; -import { transformSvelteContent } from './transform-svelte.js'; +import { transformSvelte } from './transform-svelte.js'; -describe('transformSvelteContent', () => { +describe('transformSvelte', () => { it('transforms imports in instance script', () => { expect( - transformSvelteContent(` + transformSvelte(` `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -23,12 +23,12 @@ describe('transformSvelteContent', () => { }); it('transforms imports in module script', () => { expect( - transformSvelteContent(` + transformSvelte(` `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -42,12 +42,12 @@ describe('transformSvelteContent', () => { }); it('transforms classes in instance script', () => { expect( - transformSvelteContent(` + transformSvelte(` `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -61,12 +61,12 @@ describe('transformSvelteContent', () => { }); it('transforms classes in module script', () => { expect( - transformSvelteContent(` + transformSvelte(` `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -80,10 +80,10 @@ describe('transformSvelteContent', () => { }); it('transforms classes in an attribute', () => { expect( - transformSvelteContent(` + transformSvelte(`
`) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -95,10 +95,10 @@ describe('transformSvelteContent', () => { }); it('transforms classes in an expression attribute', () => { expect( - transformSvelteContent(` + transformSvelte(`
`) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -110,10 +110,10 @@ describe('transformSvelteContent', () => { }); it('transforms classes in the class: directive', () => { expect( - transformSvelteContent(` + transformSvelte(`
`) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -125,10 +125,10 @@ describe('transformSvelteContent', () => { }); it('ignores classes in the class: directive that are also an identifier', () => { expect( - transformSvelteContent(` + transformSvelte(`
`) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.ts index b5fcf12ce..343e28ab3 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.ts @@ -1,4 +1,3 @@ -import { readFile, writeFile } from 'node:fs/promises'; import { AST, parse } from 'svelte/compiler'; import { walk, type Node } from 'estree-walker'; import MagicString from 'magic-string'; @@ -8,7 +7,7 @@ function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; } -function transformSvelteContent(code: string) { +function transformSvelte(code: string) { const s = new MagicString(code); const ast = parse(code, { modern: true @@ -45,13 +44,9 @@ function transformSvelteContent(code: string) { } }); } - return s.toString(); + return { + code: s.toString() + }; } -async function transformSvelte(path: string) { - const code = await readFile(path, 'utf-8'); - const transformed = transformSvelteContent(code); - await writeFile(path, transformed); -} - -export { transformSvelteContent, transformSvelte }; +export { transformSvelte }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts index 502483557..6d2d2cfe9 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it } from 'vitest'; -import { transformTailwindConfigContent } from './transform-tailwind-config.js'; +import { transformTailwindConfig } from './transform-tailwind-config.js'; -describe('transformTailwindConfigContent', () => { +describe('transformTailwindConfig', () => { it('transforms a config', () => { expect( - transformTailwindConfigContent(` + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; @@ -22,7 +22,7 @@ export default { ] } `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -47,7 +47,7 @@ export default { }); it('transforms a config with alternative content ordering', () => { expect( - transformTailwindConfigContent(` + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; @@ -65,7 +65,7 @@ export default { ] } `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -90,7 +90,7 @@ export default { }); it('transforms a config with alternative preset notation', () => { expect( - transformTailwindConfigContent(` + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; @@ -108,7 +108,7 @@ export default { ] } `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -133,7 +133,7 @@ export default { }); it('transforms a config with custom themes', () => { expect( - transformTailwindConfigContent(` + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; @@ -151,7 +151,7 @@ export default { ] } `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` @@ -184,7 +184,7 @@ export default { it('transforms a config while preserving other plugin options', () => { expect( - transformTailwindConfigContent(` + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; @@ -204,7 +204,7 @@ export default { ] } `) - .trim() + .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.ts index 0bdad9833..2f2261847 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.ts @@ -1,4 +1,3 @@ -import { readFile, writeFile } from 'node:fs/promises'; import { CallExpression, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph'; import { getDefaultExportObject } from '../../../../../utility/get-default-export-object'; import { THEME_MAPPINGS } from '../utility/theme-mappings'; @@ -124,7 +123,10 @@ function extractPresetThemes(node: ObjectLiteralExpression) { if (!themeName) { return null; } - return `themes.${themeName}`; + return { + type: 'preset', + name: themeName + }; }) .filter((node) => node !== null); } @@ -144,11 +146,17 @@ function extractCustomThemes(node: ObjectLiteralExpression) { if (!Node.isIdentifier(node)) { return null; } - return `/* ${node.getFullText()} */`; + return { + type: 'custom', + name: node.getText() + }; }) .filter((node) => node !== null); if (themes.length > 0) { - themes.push('themes.cerberus'); + themes.push({ + type: 'preset', + name: 'cerberus' + }); } return themes; } @@ -156,31 +164,31 @@ function extractCustomThemes(node: ObjectLiteralExpression) { function transformSkeletonThemesOption(file: SourceFile) { const defaultExportObject = getDefaultExportObject(file); if (!defaultExportObject) { - return; + return []; } const pluginsProperty = defaultExportObject.getProperty('plugins'); if (!(pluginsProperty && Node.isPropertyAssignment(pluginsProperty))) { - return; + return []; } const pluginsArray = pluginsProperty.getInitializer(); if (!(pluginsArray && Node.isArrayLiteralExpression(pluginsArray))) { - return; + return []; } const skeletonPluginCallExpression = pluginsArray.getElements().find(isSkeletonPluginCallExpression); if (!skeletonPluginCallExpression) { - return; + return []; } const skeletonConfigObject = skeletonPluginCallExpression.getArguments().at(0); if (!(skeletonConfigObject && Node.isObjectLiteralExpression(skeletonConfigObject))) { - return; + return []; } const themesProperty = skeletonConfigObject.getProperty('themes'); if (!(themesProperty && Node.isPropertyAssignment(themesProperty))) { - return; + return []; } const themesObject = themesProperty.getInitializer(); if (!(themesObject && Node.isObjectLiteralExpression(themesObject))) { - return; + return []; } const presetThemes = extractPresetThemes(themesObject); const customThemes = extractCustomThemes(themesObject); @@ -196,27 +204,33 @@ function transformSkeletonThemesOption(file: SourceFile) { ); } const themes = [...new Set([...presetThemes, ...customThemes])]; - if (themes.some((theme) => theme.startsWith('themes.'))) { + if (themes.some((theme) => theme.type === 'preset')) { file.addImportDeclaration({ moduleSpecifier: '@skeletonlabs/skeleton/themes', namespaceImport: 'themes' }); } - themesProperty.setInitializer(`[${themes.join(', ')}]`); + themesProperty.setInitializer( + `[${themes + .map((theme) => { + return theme.type === 'preset' ? `themes.${theme.name}` : `/* ${theme.name} */`; + }) + .join(', ')}]` + ); + return themes; } -function transformTailwindConfigContent(code: string) { +function transformTailwindConfig(code: string) { const file = createSourceFile(code); transformTailwindContentOption(file); - transformSkeletonThemesOption(file); + const themes = transformSkeletonThemesOption(file); file.fixUnusedIdentifiers(); - return file.getFullText(); -} - -async function transformTailwindConfig(path: string) { - const code = await readFile(path, 'utf-8'); - const transformed = transformTailwindConfigContent(code); - await writeFile(path, transformed); + return { + code: file.getFullText(), + meta: { + themes: themes + } + }; } -export { transformTailwindConfigContent, transformTailwindConfig }; +export { transformTailwindConfig }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b075e5835..7578634fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -254,6 +254,9 @@ importers: fast-glob: specifier: ^3.3.1 version: 3.3.2 + jsdom: + specifier: ^25.0.1 + version: 25.0.1 latest-version: specifier: ^9.0.0 version: 9.0.0 @@ -263,6 +266,9 @@ importers: package-manager-detector: specifier: ^0.2.8 version: 0.2.8 + parse5: + specifier: ^7.2.1 + version: 7.2.1 semver: specifier: ^7.6.3 version: 7.6.3 @@ -273,6 +279,9 @@ importers: specifier: ^25.0.0 version: 25.0.0 devDependencies: + '@types/jsdom': + specifier: ^21.1.7 + version: 21.1.7 '@types/node': specifier: ^22.1.0 version: 22.10.1 @@ -2452,6 +2461,9 @@ packages: '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} @@ -2494,6 +2506,9 @@ packages: '@types/tar@6.1.13': resolution: {integrity: sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -8793,6 +8808,12 @@ snapshots: '@types/http-cache-semantics@4.0.4': {} + '@types/jsdom@21.1.7': + dependencies: + '@types/node': 22.10.1 + '@types/tough-cookie': 4.0.5 + parse5: 7.2.1 + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 @@ -8839,6 +8860,8 @@ snapshots: '@types/node': 22.10.1 minipass: 4.2.8 + '@types/tough-cookie@4.0.5': {} + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {}