From 059d3d20216d6911b321ff4ab18551e372d2e99e Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Mon, 13 Jan 2025 21:09:40 +0100 Subject: [PATCH 01/26] Removed unused imports after transformation --- .../transformers/transform-tailwind-config.test.ts | 5 ----- .../skeleton-3/transformers/transform-tailwind-config.ts | 4 +++- 2 files changed, 3 insertions(+), 6 deletions(-) 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 8ec69209b..502483557 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 @@ -26,7 +26,6 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { join } from "path"; import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; @@ -70,7 +69,6 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { join } from "path"; import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; @@ -114,7 +112,6 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { join } from "path"; import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; @@ -165,7 +162,6 @@ export default { * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. */ -import { join } from "path"; import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; @@ -212,7 +208,6 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { join } from "path"; import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; 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 39077c947..0bdad9833 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 @@ -82,7 +82,8 @@ function transformTailwindContentOption(file: SourceFile) { } joinCallExpression.replaceWithText('contentPath(import.meta.url, "svelte")'); for (const importDeclaration of file.getImportDeclarations()) { - if (importDeclaration.getModuleSpecifierValue() === '@skeletonlabs/tw-plugin') { + const moduleSpecifier = importDeclaration.getModuleSpecifierValue(); + if (moduleSpecifier === '@skeletonlabs/tw-plugin') { importDeclaration.setModuleSpecifier('@skeletonlabs/skeleton/plugin'); importDeclaration.addNamedImport('contentPath'); } @@ -208,6 +209,7 @@ function transformTailwindConfigContent(code: string) { const file = createSourceFile(code); transformTailwindContentOption(file); transformSkeletonThemesOption(file); + file.fixUnusedIdentifiers(); return file.getFullText(); } From 6e202f5475c26d1ea57edbf3b5ea0d6045906231 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Mon, 13 Jan 2025 23:52:06 +0100 Subject: [PATCH 02/26] Feature: class: attributes will also be transformed when they're not also an identifier. --- .changeset/afraid-geckos-try.md | 5 +++ .../transformers/transform-svelte.test.ts | 34 +++++++++++++++++-- .../transformers/transform-svelte.ts | 4 +++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 .changeset/afraid-geckos-try.md diff --git a/.changeset/afraid-geckos-try.md b/.changeset/afraid-geckos-try.md new file mode 100644 index 000000000..a6eed510c --- /dev/null +++ b/.changeset/afraid-geckos-try.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: class: attributes will also be transformed when they're not also an identifier. 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 be28c2c25..e60eda6f6 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 @@ -78,7 +78,7 @@ describe('transformSvelteContent', () => { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms classes in template attributes', () => { + it('transforms classes in an attribute', () => { expect( transformSvelteContent(`
@@ -93,7 +93,7 @@ describe('transformSvelteContent', () => { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms classes in template attribute expressions', () => { + it('transforms classes in an expression attribute', () => { expect( transformSvelteContent(`
@@ -108,4 +108,34 @@ describe('transformSvelteContent', () => { .replace(/\r\n|\r|\n/g, '\n') ); }); + it('transforms classes in the class: directive', () => { + expect( + transformSvelteContent(` +
+ `) + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +
+ ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it('ignores classes in the class: directive that are also an identifier', () => { + expect( + transformSvelteContent(` +
+ `) + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +
+ ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); }); 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 1ac934c57..b5fcf12ce 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 @@ -38,6 +38,10 @@ function transformSvelteContent(code: string) { if (node.type === 'Text' && hasRange(node)) { s.update(node.start, node.end, transformClasses(node.data)); } + if (node.type === 'ClassDirective' && node.expression.type !== 'Identifier' && hasRange(node)) { + const adjustedStart = node.start + 'class:'.length; + s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name)); + } } }); } From dc6ba342132110d67a0834e58fdc76b3fa9057d0 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Mon, 13 Jan 2025 23:57:29 +0100 Subject: [PATCH 03/26] Bugfix: transformations on the package.json now preserve the original indentation. --- .changeset/big-radios-pretend.md | 5 +++++ packages/skeleton-cli/package.json | 1 + .../skeleton-3/transformers/transform-package.ts | 3 ++- pnpm-lock.yaml | 9 +++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .changeset/big-radios-pretend.md diff --git a/.changeset/big-radios-pretend.md b/.changeset/big-radios-pretend.md new file mode 100644 index 000000000..f63d09a8f --- /dev/null +++ b/.changeset/big-radios-pretend.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Bugfix: transformations on the package.json now preserve the original indentation. diff --git a/packages/skeleton-cli/package.json b/packages/skeleton-cli/package.json index 057c80ded..1a99048dd 100644 --- a/packages/skeleton-cli/package.json +++ b/packages/skeleton-cli/package.json @@ -39,6 +39,7 @@ "@clack/prompts": "^0.7.0", "colorette": "^2.0.20", "commander": "^13.0.0", + "detect-indent": "^7.0.1", "estree-walker": "^3.0.3", "fast-glob": "^3.3.1", "latest-version": "^9.0.0", 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 57a532358..d368d00b5 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 @@ -3,6 +3,7 @@ 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) { const pkg = JSON.parse(code) as PackageJson; @@ -23,7 +24,7 @@ async function transformPackageContent(code: string) { } pkg[field] = sortPropertiesAlphabetically(pkg[field] as Record); } - return JSON.stringify(pkg, null, '\t'); + return JSON.stringify(pkg, null, detectIndent(code).indent || '\t'); } async function transformPackage(path: string) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8562e0e25..b075e5835 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -245,6 +245,9 @@ importers: commander: specifier: ^13.0.0 version: 13.0.0 + detect-indent: + specifier: ^7.0.1 + version: 7.0.1 estree-walker: specifier: ^3.0.3 version: 3.0.3 @@ -3494,6 +3497,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -10209,6 +10216,8 @@ snapshots: detect-indent@6.1.0: {} + detect-indent@7.0.1: {} + detect-libc@2.0.3: optional: true From 844ef63bd1b1ecc22a7953e803074372c682f506 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 00:00:23 +0100 Subject: [PATCH 04/26] fix changeset --- .changeset/afraid-geckos-try.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/afraid-geckos-try.md b/.changeset/afraid-geckos-try.md index a6eed510c..885a6e994 100644 --- a/.changeset/afraid-geckos-try.md +++ b/.changeset/afraid-geckos-try.md @@ -2,4 +2,4 @@ '@skeletonlabs/skeleton-cli': patch --- -Feature: class: attributes will also be transformed when they're not also an identifier. +Feature: The `class:` directive will also be transformed when they're not also an identifier. From 023081d01fb70ea09b9e2fd1f7d76c5e49880ed9 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 02:02:28 +0100 Subject: [PATCH 05/26] 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': {} From 7e29a8c8a92f4c1069a329f3d670bb91f54402ee Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 13:05:29 +0100 Subject: [PATCH 06/26] Transform classes is now compliant with other transformers --- .../skeleton-3/transformers/transform-app.ts | 1 - .../transformers/transform-classes.test.ts | 20 +++++++++---------- .../transformers/transform-classes.ts | 8 +++++--- .../transformers/transform-module.ts | 2 +- .../transformers/transform-svelte.ts | 6 +++--- 5 files changed, 19 insertions(+), 18 deletions(-) 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 index 7f7eae17e..1434467cc 100644 --- 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 @@ -21,7 +21,6 @@ function transformApp(code: string, theme: string) { } } }); - return { code: s.toString() }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts index 440715222..89c178b76 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts @@ -19,7 +19,7 @@ describe('transformClasses', () => { ); for (const { v2, v3 } of createColorPairingMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -43,7 +43,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createBackgroundMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -70,7 +70,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createBorderRadiusMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -89,7 +89,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createBorderMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -108,7 +108,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createRingMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -143,7 +143,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createTextMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -158,7 +158,7 @@ describe('transformClasses', () => { for (const { v2, v3 } of createDecorationMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -171,7 +171,7 @@ describe('transformClasses', () => { for (const { v2, v3 } of createAccentMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -220,7 +220,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createPresetMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); @@ -253,7 +253,7 @@ describe('transformClasses', () => { ]; for (const { v2, v3 } of createTailwindMappings()) { it(`transforms ${v2}`, () => { - expect(transformClasses(v2)).toBe(v3); + expect(transformClasses(v2).code).toBe(v3); }); } }); diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.ts index 59a70759a..3144ec2f1 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.ts @@ -214,9 +214,11 @@ const CLASS_REGEXES = [ ]; function transformClasses(code: string) { - return CLASS_REGEXES.reduce((result, migration) => { - return result.replace(migration.find, migration.replace); - }, code); + return { + code: CLASS_REGEXES.reduce((result, migration) => { + return result.replace(migration.find, migration.replace); + }, code) + }; } export { transformClasses }; 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 5b171de83..414a7c23a 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 @@ -14,7 +14,7 @@ function transformModule(code: string) { if (!(Node.isStringLiteral(node) && !Node.isImportDeclaration(node.getParent()))) { return; } - node.setLiteralValue(transformClasses(node.getLiteralValue())); + node.setLiteralValue(transformClasses(node.getLiteralValue()).code); }); file.fixUnusedIdentifiers(); return { 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 343e28ab3..b27b6822c 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 @@ -32,14 +32,14 @@ function transformSvelte(code: string) { hasRange(node) ) { // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes - s.update(node.start + 1, node.end - 1, transformClasses(node.value)); + s.update(node.start + 1, node.end - 1, transformClasses(node.value).code); } if (node.type === 'Text' && hasRange(node)) { - s.update(node.start, node.end, transformClasses(node.data)); + s.update(node.start, node.end, transformClasses(node.data).code); } if (node.type === 'ClassDirective' && node.expression.type !== 'Identifier' && hasRange(node)) { const adjustedStart = node.start + 'class:'.length; - s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name)); + s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); } } }); From e0950e8e510514fd545a8959525dc231737feba0 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 14:38:11 +0100 Subject: [PATCH 07/26] Feature: ` install` is now ran at the end of the migration. Feature: Better error handling is now in place. --- .changeset/early-suns-cry.md | 5 + .changeset/itchy-knives-try.md | 5 + .../migrate/migrations/skeleton-3/index.ts | 115 +++++++++++++----- .../transformers/transform-app.test.ts | 4 +- .../skeleton-3/transformers/transform-app.ts | 5 +- .../src/utility/install-dependencies.ts | 18 +++ packages/skeleton-cli/tsconfig.json | 1 + pnpm-lock.yaml | 51 -------- 8 files changed, 116 insertions(+), 88 deletions(-) create mode 100644 .changeset/early-suns-cry.md create mode 100644 .changeset/itchy-knives-try.md create mode 100644 packages/skeleton-cli/src/utility/install-dependencies.ts diff --git a/.changeset/early-suns-cry.md b/.changeset/early-suns-cry.md new file mode 100644 index 000000000..13618ca2e --- /dev/null +++ b/.changeset/early-suns-cry.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: Better error handling is now in place. diff --git a/.changeset/itchy-knives-try.md b/.changeset/itchy-knives-try.md new file mode 100644 index 000000000..ab74dc56b --- /dev/null +++ b/.changeset/itchy-knives-try.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: ` install` is now ran at the end of the migration. 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 d47364355..128658e21 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 @@ -5,10 +5,11 @@ import type { MigrateOptions } from '../../index.js'; import { isCancel, multiselect, spinner } from '@clack/prompts'; 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 { transformSvelte } from './transformers/transform-svelte.js'; +import { transformModule } from './transformers/transform-module.js'; +import { transformApp } from './transformers/transform-app.js'; import { readFile, writeFile } from 'node:fs/promises'; +import { installDependencies } from '../../../../utility/install-dependencies.js'; export default async function (options: MigrateOptions) { const cwd = options.cwd ?? process.cwd(); @@ -35,7 +36,11 @@ export default async function (options: MigrateOptions) { } } - const availableSourceFolders = await fg('*', { cwd, onlyDirectories: true, ignore: ['node_modules'] }); + const availableSourceFolders = await fg('*', { + cwd: cwd, + onlyDirectories: true, + ignore: ['node_modules'] + }); const sourceFolders = await multiselect({ message: 'What folders contain usage of Skeleton? (classes, imports, etc.)', options: availableSourceFolders.map((folder) => ({ label: folder, value: folder })), @@ -43,51 +48,95 @@ export default async function (options: MigrateOptions) { }); if (isCancel(sourceFolders)) { - cli.error('Migration cancelled.'); + cli.error('Migration cancelled by user.'); return; } const packageSpinner = spinner(); packageSpinner.start(`Migrating ${pkg.matcher}...`); - 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}`); + try { + 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}`); + } catch (e) { + if (e instanceof Error) { + packageSpinner.stop(`Failed to migrate ${pkg.matcher}: ${e.message}`); + } + packageSpinner.stop(`Failed to migrate ${pkg.matcher}`); + } + + let themeName: string | null = null; 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'); + try { + const tailwindCode = await readFile(tailwindConfig.paths[0], 'utf-8'); + const transformedTailwind = transformTailwindConfig(tailwindCode); + themeName = transformedTailwind.meta.themes.find((theme) => theme.type === 'preset')?.name ?? null; + await writeFile(tailwindConfig.paths[0], transformedTailwind.code); + tailwindSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`); + } catch (e) { + if (e instanceof Error) { + tailwindSpinner.stop(`Failed to migrate ${tailwindConfig.matcher}: ${e.message}`); + } + tailwindSpinner.stop(`Failed to migrate ${tailwindConfig.matcher}`); + } 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}`); + try { + const appCode = await readFile(app.paths[0], 'utf-8'); + const transformedApp = transformApp(appCode, themeName ?? 'cerberus'); + await writeFile(app.paths[0], transformedApp.code); + appSpinner.stop(`Successfully migrated ${app.matcher}!`); + } catch (e) { + if (e instanceof Error) { + appSpinner.stop(`Failed to migrate ${app.matcher}: ${e.message}`); + } + appSpinner.stop(`Failed to migrate ${app.matcher}.`); + } const sourceFileMatcher = `{${sourceFolders.join(',')}}/**/*.{js,mjs,ts,mts,svelte}`; - const sourceFiles = await fg(sourceFileMatcher, { cwd, ignore: ['node_modules', 'dist', 'build', 'public'] }); + const sourceFiles = await fg(sourceFileMatcher, { + cwd: cwd, + ignore: ['node_modules'] + }); const sourceFilesSpinner = spinner(); sourceFilesSpinner.start(`Migrating source files...`); - for (const sourceFile of sourceFiles) { - sourceFilesSpinner.message(`Migrating ${sourceFile}...`); - const extension = extname(sourceFile); - if (extension === '.svelte') { - const svelteCode = await readFile(sourceFile, 'utf-8'); - const transformedSvelte = transformSvelte(svelteCode); - await writeFile(sourceFile, transformedSvelte.code); - } else { - const moduleCode = await readFile(sourceFile, 'utf-8'); - const transformedModule = transformModule(moduleCode); - await writeFile(sourceFile, transformedModule.code); + try { + for (const sourceFile of sourceFiles) { + sourceFilesSpinner.message(`Migrating ${sourceFile}...`); + const extension = extname(sourceFile); + if (extension === '.svelte') { + const svelteCode = await readFile(sourceFile, 'utf-8'); + const transformedSvelte = transformSvelte(svelteCode); + await writeFile(sourceFile, transformedSvelte.code); + } else { + const moduleCode = await readFile(sourceFile, 'utf-8'); + const transformedModule = transformModule(moduleCode); + await writeFile(sourceFile, transformedModule.code); + } + sourceFilesSpinner.message(`Successfully migrated ${sourceFile}!`); + } + sourceFilesSpinner.stop('Successfully migrated all source files!'); + } catch (error) { + if (error instanceof Error) { + sourceFilesSpinner.stop(`Failed to migrate source files: ${error.message}`); + } + sourceFilesSpinner.stop('Failed to migrate source files.'); + } + + const installDependenciesSpinner = spinner(); + installDependenciesSpinner.start('Installing dependencies...'); + try { + await installDependencies(cwd); + installDependenciesSpinner.stop('Successfully installed dependencies!'); + } catch (e) { + if (e instanceof Error) { + installDependenciesSpinner.stop(`Failed to install dependencies: ${e.message}`); } - sourceFilesSpinner.message(`Successfully migrated ${sourceFile}`); + installDependenciesSpinner.stop('Failed to install dependencies.'); } - sourceFilesSpinner.stop('Successfully migrated all source files'); } 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 index 3e1198392..32e07ac24 100644 --- 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 @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest'; import { transformApp } from './transform-app.js'; describe('transformsApp', () => { - it('edits the `data-them` attribute when already present', () => { + it('transforms the `data-them` attribute when present', () => { expect( transformApp( ` @@ -27,7 +27,7 @@ describe('transformsApp', () => { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('adds the `data-theme` attribute ', () => { + it('adds the `data-theme` attribute', () => { expect( transformApp( ` 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 index 1434467cc..ce7071ae0 100644 --- 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 @@ -13,10 +13,11 @@ function transformApp(code: string, theme: string) { const dataThemeAttribute = node.attributes.find((attribute) => { return attribute.type === 'Attribute' && attribute.name === 'data-theme'; }); + const newDataThemeAttribute = `data-theme="${theme}"`; if (dataThemeAttribute) { - s.update(dataThemeAttribute.start, dataThemeAttribute.end, `data-theme="${theme}"`); + s.update(dataThemeAttribute.start, dataThemeAttribute.end, newDataThemeAttribute); } else { - s.appendRight(node.start + ' Date: Tue, 14 Jan 2025 14:50:17 +0100 Subject: [PATCH 08/26] Fixed bug where class: directives that were referencing regular identifiers were not being transformed, now they only aren't transformed when the identifier is the same name and doesn't have a `loc` property. --- .../transformers/transform-svelte.test.ts | 23 ++++++++++++++++++- .../transformers/transform-svelte.ts | 4 ++-- 2 files changed, 24 insertions(+), 3 deletions(-) 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 fc094dc16..0b5e52871 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 @@ -123,7 +123,28 @@ describe('transformSvelte', () => { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('ignores classes in the class: directive that are also an identifier', () => { + it('ignores classes in the class: directive that equal an identifier', () => { + expect( + transformSvelte(` + +
+ `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + +
+ ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it('ignores classes in the class: directive that are also the identifier', () => { expect( transformSvelte(`
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 b27b6822c..ad0e63d07 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,4 @@ -import { AST, parse } from 'svelte/compiler'; +import { type AST, parse } from 'svelte/compiler'; import { walk, type Node } from 'estree-walker'; import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; @@ -37,7 +37,7 @@ function transformSvelte(code: string) { if (node.type === 'Text' && hasRange(node)) { s.update(node.start, node.end, transformClasses(node.data).code); } - if (node.type === 'ClassDirective' && node.expression.type !== 'Identifier' && hasRange(node)) { + if (node.type === 'ClassDirective' && !(node.expression.type === 'Identifier' && !('loc' in node.expression) && node.name === node.expression.name) && hasRange(node)) { const adjustedStart = node.start + 'class:'.length; s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); } From 8f4ed9c16bbba91b6281e1982b018ff5cedaf558 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 15:13:56 +0100 Subject: [PATCH 09/26] Replaced `estree-walker` with `zimmerframe` due to more readable code. --- packages/skeleton-cli/package.json | 7 +- .../skeleton-3/transformers/transform-app.ts | 33 +++++---- .../transformers/transform-svelte.ts | 67 ++++++++++--------- pnpm-lock.yaml | 66 +++++++++++++++--- 4 files changed, 116 insertions(+), 57 deletions(-) diff --git a/packages/skeleton-cli/package.json b/packages/skeleton-cli/package.json index a3304491e..6b30bf5ba 100644 --- a/packages/skeleton-cli/package.json +++ b/packages/skeleton-cli/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "@types/jsdom": "^21.1.7", + "@types/estree": "^1.0.6", "@types/node": "^22.1.0", "@types/semver": "^7.5.8", "type-fest": "^4.27.0", @@ -41,15 +42,13 @@ "colorette": "^2.0.20", "commander": "^13.0.0", "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" + "ts-morph": "^25.0.0", + "zimmerframe": "^1.1.2" } } 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 index ce7071ae0..ec262b669 100644 --- 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 @@ -1,27 +1,32 @@ -import { AST, parse } from 'svelte/compiler'; -import { walk, type Node } from 'estree-walker'; +import { type AST, parse } from 'svelte/compiler'; import MagicString from 'magic-string'; +import { walk } from 'zimmerframe'; 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'; - }); - const newDataThemeAttribute = `data-theme="${theme}"`; - if (dataThemeAttribute) { - s.update(dataThemeAttribute.start, dataThemeAttribute.end, newDataThemeAttribute); - } else { - s.appendLeft(node.start + ' { + return attribute.type === 'Attribute' && attribute.name === 'data-theme'; + }); + const newDataThemeAttribute = `data-theme="${theme}"`; + if (dataThemeAttribute) { + s.update(dataThemeAttribute.start, dataThemeAttribute.end, newDataThemeAttribute); + } else { + s.appendLeft(node.start + ' !!node); - for (const root of roots) { - walk(root as unknown as Node, { - enter(node: Node | AST.SvelteNode, parent: Node | AST.SvelteNode | null) { - if ( - node.type === 'ImportDeclaration' && - node.source.type === 'Literal' && - node.source.value === '@skeletonlabs/skeleton' && - hasRange(node.source) - ) { - // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes - s.update(node.source.start + 1, node.source.end - 1, '@skeletonlabs/skeleton-svelte'); - } - if ( - !(parent && parent.type === 'ImportDeclaration') && - node.type === 'Literal' && - typeof node.value === 'string' && - hasRange(node) - ) { - // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes - s.update(node.start + 1, node.end - 1, transformClasses(node.value).code); - } - if (node.type === 'Text' && hasRange(node)) { + const asts = [root.instance, root.module, root.fragment].filter((node) => !!node); + for (const ast of asts) { + walk( + ast as Node | AST.SvelteNode, + {}, + { + ImportDeclaration(node, ctx) { + if (node.source.type === 'Literal' && node.source.value === '@skeletonlabs/skeleton' && hasRange(node.source)) { + // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes + s.update(node.source.start + 1, node.source.end - 1, '@skeletonlabs/skeleton-svelte'); + } + ctx.next(); + }, + Literal(node, ctx) { + const parent = ctx.path.at(-1); + if (typeof node.value === 'string' && !(parent && parent.type === 'ImportDeclaration') && hasRange(node)) { + // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes + s.update(node.start + 1, node.end - 1, transformClasses(node.value).code); + } + ctx.next(); + }, + Text(node, ctx) { s.update(node.start, node.end, transformClasses(node.data).code); - } - if (node.type === 'ClassDirective' && !(node.expression.type === 'Identifier' && !('loc' in node.expression) && node.name === node.expression.name) && hasRange(node)) { - const adjustedStart = node.start + 'class:'.length; - s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); + ctx.next(); + }, + ClassDirective(node, ctx) { + if ( + !(node.expression.type === 'Identifier' && !('loc' in node.expression) && node.name === node.expression.name) && + hasRange(node) + ) { + const adjustedStart = node.start + 'class:'.length; + s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); + } + ctx.next(); } } - }); + ); } return { code: s.toString() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8507776c1..6d2ab4c4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,57 @@ settings: catalogs: default: + '@zag-js/accordion': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/avatar': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/combobox': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/dialog': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/file-upload': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/pagination': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/popover': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/progress': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/radio-group': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/rating-group': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/react': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/slider': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/svelte': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/switch': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/tabs': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/tags-input': + specifier: ^0.78.3 + version: 0.78.3 + '@zag-js/tooltip': + specifier: ^0.78.3 + version: 0.78.3 typescript: specifier: ^5.6.3 version: 5.6.3 @@ -197,15 +248,9 @@ importers: detect-indent: specifier: ^7.0.1 version: 7.0.1 - estree-walker: - specifier: ^3.0.3 - version: 3.0.3 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 @@ -215,9 +260,6 @@ 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 @@ -227,7 +269,13 @@ importers: ts-morph: specifier: ^25.0.0 version: 25.0.0 + zimmerframe: + specifier: ^1.1.2 + version: 1.1.2 devDependencies: + '@types/estree': + specifier: ^1.0.6 + version: 1.0.6 '@types/jsdom': specifier: ^21.1.7 version: 21.1.7 From cef470530bcc9ac32940b2afee425430747f2176 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 17:24:18 +0100 Subject: [PATCH 10/26] Add additional test cases for all preset themes for the app tests. --- .../transformers/transform-app.test.ts | 65 ++++++++++--------- 1 file changed, 34 insertions(+), 31 deletions(-) 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 index 32e07ac24..3a469afb8 100644 --- 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 @@ -1,54 +1,57 @@ import { describe, expect, it } from 'vitest'; import { transformApp } from './transform-app.js'; +import { THEME_MAPPINGS } from '../utility/theme-mappings.js'; describe('transformsApp', () => { - it('transforms the `data-them` attribute when present', () => { - expect( - transformApp( - ` + for (const [oldTheme, newTheme] of Object.entries(THEME_MAPPINGS)) { + it(`transforms the \`data-theme="${oldTheme}"\` attribute to \`data-theme="${newTheme}"\``, () => { + expect( + transformApp( + ` foo - + `, - 'cerberus' - ) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` + newTheme + ) + .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( - ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`adds the \`data-theme="${newTheme}"\` attribute`, () => { + expect( + transformApp( + ` foo `, - 'cerberus' - ) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` + newTheme + ) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` foo - + ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } }); From 03215576442cada9d0199f12d67de3e40ae7ace8 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 20:15:49 +0100 Subject: [PATCH 11/26] Tailwind transforms are much more correct now. --- .../migrate/migrations/skeleton-3/index.ts | 7 +- .../transform-tailwind-config.test.ts | 228 ++++++++++++------ .../transformers/transform-tailwind-config.ts | 154 +++++++----- .../skeleton-3/utility/theme-mappings.ts | 4 +- 4 files changed, 243 insertions(+), 150 deletions(-) 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 128658e21..f62421890 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 @@ -10,6 +10,7 @@ import { transformModule } from './transformers/transform-module.js'; import { transformApp } from './transformers/transform-app.js'; import { readFile, writeFile } from 'node:fs/promises'; import { installDependencies } from '../../../../utility/install-dependencies.js'; +import { DEFAULT_THEME } from './utility/theme-mappings.js'; export default async function (options: MigrateOptions) { const cwd = options.cwd ?? process.cwd(); @@ -66,14 +67,14 @@ export default async function (options: MigrateOptions) { packageSpinner.stop(`Failed to migrate ${pkg.matcher}`); } - let themeName: string | null = null; + let theme: string | null = null; const tailwindSpinner = spinner(); tailwindSpinner.start(`Migrating ${tailwindConfig.matcher}...`); try { const tailwindCode = await readFile(tailwindConfig.paths[0], 'utf-8'); const transformedTailwind = transformTailwindConfig(tailwindCode); - themeName = transformedTailwind.meta.themes.find((theme) => theme.type === 'preset')?.name ?? null; + theme = transformedTailwind.meta.themes.preset.at(0) ?? null; await writeFile(tailwindConfig.paths[0], transformedTailwind.code); tailwindSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`); } catch (e) { @@ -87,7 +88,7 @@ export default async function (options: MigrateOptions) { appSpinner.start(`Migrating ${app.matcher}...`); try { const appCode = await readFile(app.paths[0], 'utf-8'); - const transformedApp = transformApp(appCode, themeName ?? 'cerberus'); + const transformedApp = transformApp(appCode, theme ?? DEFAULT_THEME); await writeFile(app.paths[0], transformedApp.code); appSpinner.stop(`Successfully migrated ${app.matcher}!`); } catch (e) { 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 6d2d2cfe9..8d6dd5bc8 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,24 +1,17 @@ import { describe, expect, it } from 'vitest'; import { transformTailwindConfig } from './transform-tailwind-config.js'; +import { THEME_MAPPINGS } from '../utility/theme-mappings.js'; describe('transformTailwindConfig', () => { - it('transforms a config', () => { + it('transforms content path', () => { expect( transformTailwindConfig(` import { join } from "path"; -import { skeleton } from "@skeletonlabs/tw-plugin"; export default { content: [ "./src/**/*.{html,js,svelte,ts}", join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") - ], - plugins: [ - skeleton({ - themes: { - preset: ["skeleton"] - } - }) ] } `) @@ -26,18 +19,12 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; +import { contentPath } from "@skeletonlabs/skeleton/plugin"; export default { content: [ "./src/**/*.{html,js,svelte,ts}", contentPath(import.meta.url, "svelte") - ], - plugins: [ - skeleton({ - themes: [themes.legacy] - }) ] } ` @@ -45,23 +32,15 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms a config with alternative content ordering', () => { + it('transforms content path with at different index', () => { expect( transformTailwindConfig(` import { join } from "path"; -import { skeleton } from "@skeletonlabs/tw-plugin"; export default { content: [ join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}"), "./src/**/*.{html,js,svelte,ts}" - ], - plugins: [ - skeleton({ - themes: { - preset: ["skeleton"] - } - }) ] } `) @@ -69,18 +48,12 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; +import { contentPath } from "@skeletonlabs/skeleton/plugin"; export default { content: [ contentPath(import.meta.url, "svelte"), "./src/**/*.{html,js,svelte,ts}" - ], - plugins: [ - skeleton({ - themes: [themes.legacy] - }) ] } ` @@ -88,67 +61,142 @@ export default { .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms a config with alternative preset notation', () => { - expect( - transformTailwindConfig(` + for (const [oldTheme, newTheme] of Object.entries(THEME_MAPPINGS)) { + it(`transforms a config with ${oldTheme} theme`, () => { + expect( + transformTailwindConfig(` +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + themes: { + preset: ["${oldTheme}"] + } + }) + ], +} + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.${newTheme}] + }) + ], +} + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`transforms a config with ${oldTheme} theme using the object theme format`, () => { + expect( + transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") + plugins: [ + skeleton({ + themes: { + preset: [ + { + name: "${oldTheme}", + enhancements: true + } + ] + } + }) + ], +} + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.${newTheme}] + }) ], +} + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } + it('transforms a config with custom themes', () => { + expect( + transformTailwindConfig(` +import { skeleton } from "@skeletonlabs/tw-plugin"; +import myCustomTheme from "./my-custom-theme.js"; + +export default { plugins: [ skeleton({ themes: { - preset: [{ name: "skeleton", enhancements: true }] + custom: [myCustomTheme] } }) - ] + ], } `) .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; +/** + * SKELETON MIGRATION NOTICE + * + * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: + * + * - myCustomTheme + * + * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. + */ + +import { skeleton } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - contentPath(import.meta.url, "svelte") - ], plugins: [ skeleton({ - themes: [themes.legacy] + themes: [themes.cerberus /* myCustomTheme */] }) - ] + ], } ` .trim() .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms a config with custom themes', () => { + it('transforms a config with multiple custom themes', () => { expect( transformTailwindConfig(` -import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; +import myCustomTheme from "./my-custom-theme.js"; +import myCustomThemeTwo from "./my-custom-theme-two.js"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") - ], plugins: [ skeleton({ themes: { - custom: [myCustomTheme] + custom: [myCustomTheme, myCustomThemeTwo] } }) - ] + ], } `) .code.trim() @@ -158,71 +206,91 @@ export default { /** * SKELETON MIGRATION NOTICE * - * Custom themes were detected and commented out due to them not being compatible with the V3 theme format. + * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: + * + * - myCustomTheme + * - myCustomThemeTwo + * * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. */ -import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; +import { skeleton } from "@skeletonlabs/skeleton/plugin"; import * as themes from "@skeletonlabs/skeleton/themes"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - contentPath(import.meta.url, "svelte") - ], plugins: [ skeleton({ - themes: [/* myCustomTheme */, themes.cerberus] + themes: [themes.cerberus /* myCustomTheme, myCustomThemeTwo */] }) - ] + ], } ` .trim() .replace(/\r\n|\r|\n/g, '\n') ); }); - - it('transforms a config while preserving other plugin options', () => { + it('does not add a themes import when no themes are set', () => { expect( transformTailwindConfig(` import { join } from "path"; import { skeleton } from "@skeletonlabs/tw-plugin"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") + plugins: [ + skeleton({ + themes: {} + }) + ], +} + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { skeleton } from "@skeletonlabs/skeleton/plugin"; + +export default { + plugins: [ + skeleton({ + themes: [] + }) ], +} + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it('keeps other skeleton configuration options', () => { + expect( + transformTailwindConfig(` +import { join } from "path"; +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { plugins: [ skeleton({ base: true, - themes: { - preset: ["skeleton"] - }, + themes: {}, prefix: "sk-" }) - ] + ], } `) .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` -import { skeleton, contentPath } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; +import { skeleton } from "@skeletonlabs/skeleton/plugin"; export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - contentPath(import.meta.url, "svelte") - ], plugins: [ skeleton({ base: true, - themes: [themes.legacy], + themes: [], prefix: "sk-" }) - ] + ], } ` .trim() 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 2f2261847..e92ffce5e 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,6 +1,6 @@ import { CallExpression, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph'; import { getDefaultExportObject } from '../../../../../utility/get-default-export-object'; -import { THEME_MAPPINGS } from '../utility/theme-mappings'; +import { DEFAULT_THEME, THEME_MAPPINGS } from '../utility/theme-mappings'; import { createSourceFile } from '../../../../../utility/create-source-file'; function isJoinCallExpression(node: Node): node is CallExpression { @@ -80,12 +80,15 @@ function transformTailwindContentOption(file: SourceFile) { return; } joinCallExpression.replaceWithText('contentPath(import.meta.url, "svelte")'); - for (const importDeclaration of file.getImportDeclarations()) { - const moduleSpecifier = importDeclaration.getModuleSpecifierValue(); - if (moduleSpecifier === '@skeletonlabs/tw-plugin') { - importDeclaration.setModuleSpecifier('@skeletonlabs/skeleton/plugin'); - importDeclaration.addNamedImport('contentPath'); - } + file.getImportDeclaration('@skeletonlabs/tw-plugin')?.remove(); + const skeletonPluginImportDeclaration = file.getImportDeclaration('@skeletonlabs/skeleton/plugin'); + if (skeletonPluginImportDeclaration) { + skeletonPluginImportDeclaration.addNamedImport('contentPath'); + } else { + file.addImportDeclaration({ + moduleSpecifier: '@skeletonlabs/skeleton/plugin', + namedImports: ['contentPath'] + }); } } @@ -108,55 +111,39 @@ function getThemeName(node: Node) { } function extractPresetThemes(node: ObjectLiteralExpression) { + const themes = new Set(); const presetThemesProperty = node.getProperty('preset'); if (!(presetThemesProperty && Node.isPropertyAssignment(presetThemesProperty))) { - return []; + return themes; } const presetThemesArray = presetThemesProperty.getInitializer(); if (!(presetThemesArray && Node.isArrayLiteralExpression(presetThemesArray))) { - return []; - } - return presetThemesArray - .getElements() - .map((node) => { - const themeName = getThemeName(node); - if (!themeName) { - return null; - } - return { - type: 'preset', - name: themeName - }; - }) - .filter((node) => node !== null); + return themes; + } + for (const element of presetThemesArray.getElements()) { + const themeName = getThemeName(element); + if (themeName) { + themes.add(themeName); + } + } + return themes; } function extractCustomThemes(node: ObjectLiteralExpression) { + const themes = new Set(); const customThemesProperty = node.getProperty('custom'); if (!(customThemesProperty && Node.isPropertyAssignment(customThemesProperty))) { - return []; + return themes; } const customThemeArray = customThemesProperty.getInitializer(); if (!(customThemeArray && Node.isArrayLiteralExpression(customThemeArray))) { - return []; - } - const themes = customThemeArray - .getElements() - .map((node) => { - if (!Node.isIdentifier(node)) { - return null; - } - return { - type: 'custom', - name: node.getText() - }; - }) - .filter((node) => node !== null); - if (themes.length > 0) { - themes.push({ - type: 'preset', - name: 'cerberus' - }); + return themes; + } + for (const element of customThemeArray.getElements()) { + if (!Node.isIdentifier(element)) { + continue; + } + themes.add(element.getText()); } return themes; } @@ -164,60 +151,95 @@ function extractCustomThemes(node: ObjectLiteralExpression) { function transformSkeletonThemesOption(file: SourceFile) { const defaultExportObject = getDefaultExportObject(file); if (!defaultExportObject) { - return []; + return { + preset: [], + custom: [] + }; } const pluginsProperty = defaultExportObject.getProperty('plugins'); if (!(pluginsProperty && Node.isPropertyAssignment(pluginsProperty))) { - return []; + return { + preset: [], + custom: [] + }; } const pluginsArray = pluginsProperty.getInitializer(); if (!(pluginsArray && Node.isArrayLiteralExpression(pluginsArray))) { - return []; + return { + preset: [], + custom: [] + }; } const skeletonPluginCallExpression = pluginsArray.getElements().find(isSkeletonPluginCallExpression); if (!skeletonPluginCallExpression) { - return []; + return { + preset: [], + custom: [] + }; + } + file.getImportDeclaration('@skeletonlabs/tw-plugin')?.remove(); + const skeletonPluginImportDeclaration = file.getImportDeclaration('@skeletonlabs/skeleton/plugin'); + if (skeletonPluginImportDeclaration) { + skeletonPluginImportDeclaration.addNamedImport('skeleton'); + } else { + file.addImportDeclaration({ + moduleSpecifier: '@skeletonlabs/skeleton/plugin', + namedImports: ['skeleton'] + }); } const skeletonConfigObject = skeletonPluginCallExpression.getArguments().at(0); if (!(skeletonConfigObject && Node.isObjectLiteralExpression(skeletonConfigObject))) { - return []; + return { + preset: [], + custom: [] + }; } const themesProperty = skeletonConfigObject.getProperty('themes'); if (!(themesProperty && Node.isPropertyAssignment(themesProperty))) { - return []; + return { + preset: [], + custom: [] + }; } const themesObject = themesProperty.getInitializer(); if (!(themesObject && Node.isObjectLiteralExpression(themesObject))) { - return []; + return { + preset: [], + custom: [] + }; } const presetThemes = extractPresetThemes(themesObject); const customThemes = extractCustomThemes(themesObject); - if (customThemes.length > 0) { + if ((presetThemes.size > 0 || customThemes.size > 0)) { + file.addImportDeclaration({ + moduleSpecifier: '@skeletonlabs/skeleton/themes', + namespaceImport: 'themes' + }); + } + if (customThemes.size > 0) { file.insertStatements( 0, `/** * SKELETON MIGRATION NOTICE * - * Custom themes were detected and commented out due to them not being compatible with the V3 theme format. + * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: + * +${[...customThemes].map((theme) => ` * - ${theme}`).join('\n')} + * * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. */` ); } - const themes = [...new Set([...presetThemes, ...customThemes])]; - if (themes.some((theme) => theme.type === 'preset')) { - file.addImportDeclaration({ - moduleSpecifier: '@skeletonlabs/skeleton/themes', - namespaceImport: 'themes' - }); + if (customThemes.size > 0 && presetThemes.size === 0) { + presetThemes.add(DEFAULT_THEME); } - themesProperty.setInitializer( - `[${themes - .map((theme) => { - return theme.type === 'preset' ? `themes.${theme.name}` : `/* ${theme.name} */`; - }) - .join(', ')}]` - ); - return themes; + const presetThemesString = [...presetThemes].map((theme) => `themes.${theme}`).join(', '); + const customThemesString = customThemes.size > 0 ? `/* ${[...customThemes].join(', ')} */` : null; + themesProperty.setInitializer(`[${presetThemesString}${customThemesString ? ` ${customThemesString}` : ''}]`); + return { + preset: [...presetThemes], + custom: [...customThemes] + }; } function transformTailwindConfig(code: string) { diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts index 6a0398957..a88ae637e 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts @@ -11,4 +11,6 @@ const THEME_MAPPINGS: Record = { crimson: 'crimson' }; -export { THEME_MAPPINGS }; +const DEFAULT_THEME = 'cerberus'; + +export { THEME_MAPPINGS, DEFAULT_THEME }; From 8b4aa60752ee9fa1ee238cd722b9724d1f896b08 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 20:20:24 +0100 Subject: [PATCH 12/26] Tailwind transforms are much more correct now, as well as being tested against many more edge cases --- .../transform-tailwind-config.test.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) 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 8d6dd5bc8..dddc96759 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 @@ -137,6 +137,40 @@ export default { ); }); } + it(`transforms a config with multiple preset themes`, () => { + expect( + transformTailwindConfig(` +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + themes: { + preset: ["skeleton", "gold-nouveau"] + } + }) + ], +} + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.legacy, themes.nouveau] + }) + ], +} + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); it('transforms a config with custom themes', () => { expect( transformTailwindConfig(` From eb739aafe8826868089e84b0a4b99bc36f8efb3c Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 20:22:32 +0100 Subject: [PATCH 13/26] format --- .../skeleton-3/transformers/transform-tailwind-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e92ffce5e..26b739e6d 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 @@ -210,7 +210,7 @@ function transformSkeletonThemesOption(file: SourceFile) { } const presetThemes = extractPresetThemes(themesObject); const customThemes = extractCustomThemes(themesObject); - if ((presetThemes.size > 0 || customThemes.size > 0)) { + if (presetThemes.size > 0 || customThemes.size > 0) { file.addImportDeclaration({ moduleSpecifier: '@skeletonlabs/skeleton/themes', namespaceImport: 'themes' From 4976bdcea4515c9efc6e07b4d846a63d60cf6456 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 22:01:34 +0100 Subject: [PATCH 14/26] cleanup, added component mappings --- .../migrate/migrations/skeleton-3/index.ts | 4 ++-- .../transformers/transform-svelte.test.ts | 8 ++++++++ .../transformers/transform-tailwind-config.ts | 5 +++-- .../skeleton-3/utility/component-mappings.ts | 14 ++++++++++++++ .../migrations/skeleton-3/utility/constants.ts | 3 +++ .../skeleton-3/utility/theme-mappings.ts | 4 +--- 6 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts create mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/constants.ts 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 f62421890..09a2de8bf 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 @@ -10,7 +10,7 @@ import { transformModule } from './transformers/transform-module.js'; import { transformApp } from './transformers/transform-app.js'; import { readFile, writeFile } from 'node:fs/promises'; import { installDependencies } from '../../../../utility/install-dependencies.js'; -import { DEFAULT_THEME } from './utility/theme-mappings.js'; +import { FALLBACK_THEME } from './utility/constants'; export default async function (options: MigrateOptions) { const cwd = options.cwd ?? process.cwd(); @@ -88,7 +88,7 @@ export default async function (options: MigrateOptions) { appSpinner.start(`Migrating ${app.matcher}...`); try { const appCode = await readFile(app.paths[0], 'utf-8'); - const transformedApp = transformApp(appCode, theme ?? DEFAULT_THEME); + const transformedApp = transformApp(appCode, theme ?? FALLBACK_THEME); await writeFile(app.paths[0], transformedApp.code); appSpinner.stop(`Successfully migrated ${app.matcher}!`); } catch (e) { 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 0b5e52871..c7f92e263 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 @@ -8,6 +8,8 @@ describe('transformSvelte', () => { + + `) .code.trim() .replace(/\r\n|\r|\n/g, '\n') @@ -16,6 +18,8 @@ describe('transformSvelte', () => { + + ` .trim() .replace(/\r\n|\r|\n/g, '\n') @@ -27,6 +31,8 @@ describe('transformSvelte', () => { + + `) .code.trim() .replace(/\r\n|\r|\n/g, '\n') @@ -35,6 +41,8 @@ describe('transformSvelte', () => { + + ` .trim() .replace(/\r\n|\r|\n/g, '\n') 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 26b739e6d..441e6b943 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,7 +1,8 @@ import { CallExpression, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph'; import { getDefaultExportObject } from '../../../../../utility/get-default-export-object'; -import { DEFAULT_THEME, THEME_MAPPINGS } from '../utility/theme-mappings'; +import { THEME_MAPPINGS } from '../utility/theme-mappings'; import { createSourceFile } from '../../../../../utility/create-source-file'; +import { FALLBACK_THEME } from '../utility/constants'; function isJoinCallExpression(node: Node): node is CallExpression { if (!Node.isCallExpression(node)) { @@ -231,7 +232,7 @@ ${[...customThemes].map((theme) => ` * - ${theme}`).join('\n')} ); } if (customThemes.size > 0 && presetThemes.size === 0) { - presetThemes.add(DEFAULT_THEME); + presetThemes.add(FALLBACK_THEME); } const presetThemesString = [...presetThemes].map((theme) => `themes.${theme}`).join(', '); const customThemesString = customThemes.size > 0 ? `/* ${[...customThemes].join(', ')} */` : null; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts new file mode 100644 index 000000000..1e30da119 --- /dev/null +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts @@ -0,0 +1,14 @@ +const COMPONENT_MAPPINGS: Record = { + AppRail: 'Navigation', + FileButton: 'FileUpload', + FileDropzone: 'FileUpload', + InputChip: 'TagsInputs', + Paginator: 'Pagination', + ProgressBar: 'Progress', + ProgressRadial: 'ProgressRing', + RadioGroup: 'Segment', + RangeSlider: 'Slider', + SlideToggle: 'Switch' +}; + +export { COMPONENT_MAPPINGS }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/constants.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/constants.ts new file mode 100644 index 000000000..6e9774e3a --- /dev/null +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/constants.ts @@ -0,0 +1,3 @@ +const FALLBACK_THEME = 'cerberus'; + +export { FALLBACK_THEME }; diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts index a88ae637e..6a0398957 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/theme-mappings.ts @@ -11,6 +11,4 @@ const THEME_MAPPINGS: Record = { crimson: 'crimson' }; -const DEFAULT_THEME = 'cerberus'; - -export { THEME_MAPPINGS, DEFAULT_THEME }; +export { THEME_MAPPINGS }; From 3b3baebf5b5638de7a961039207c4561a51c273a Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 22:28:04 +0100 Subject: [PATCH 15/26] Feature: Rename all components imports and usages. --- .changeset/modern-pianos-sparkle.md | 5 + .../transformers/transform-module.test.ts | 33 ++--- .../transformers/transform-module.ts | 32 +++-- .../transformers/transform-svelte.test.ts | 117 +++++++----------- .../transformers/transform-svelte.ts | 21 ++++ 5 files changed, 110 insertions(+), 98 deletions(-) create mode 100644 .changeset/modern-pianos-sparkle.md diff --git a/.changeset/modern-pianos-sparkle.md b/.changeset/modern-pianos-sparkle.md new file mode 100644 index 000000000..fb37c5adf --- /dev/null +++ b/.changeset/modern-pianos-sparkle.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: Rename all components imports and usages. diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts index 9ecd46e51..c0ac53796 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts @@ -1,26 +1,29 @@ import { describe, expect, it } from 'vitest'; import { transformModule } from './transform-module.js'; +import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; describe('transformModuleContent', () => { - it('transforms imports', () => { - expect( - transformModule(` -import { Avatar } from "@skeletonlabs/skeleton"; + for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { + it(`transforms the \`${oldComponent}\` import and its usages`, () => { + expect( + transformModule(` +import { ${oldComponent} } from "@skeletonlabs/skeleton"; -Avatar; +${oldComponent}; `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { Avatar } from "@skeletonlabs/skeleton-svelte"; + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { ${newComponent} } from "@skeletonlabs/skeleton-svelte"; -Avatar; +${newComponent}; ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } it('transforms classes in strings', () => { expect( transformModule(` 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 414a7c23a..f8ba530f7 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,20 +1,34 @@ import { Node } from 'ts-morph'; import { transformClasses } from './transform-classes.js'; import { createSourceFile } from '../../../../../utility/create-source-file.js'; +import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; function transformModule(code: string) { const file = createSourceFile(code); - for (const importDeclaration of file.getImportDeclarations()) { - const moduleSpecifier = importDeclaration.getModuleSpecifier(); - if (moduleSpecifier.getLiteralText() === '@skeletonlabs/skeleton') { - importDeclaration.setModuleSpecifier('@skeletonlabs/skeleton-svelte'); - } - } + file.forEachDescendant((node) => { - if (!(Node.isStringLiteral(node) && !Node.isImportDeclaration(node.getParent()))) { - return; + if (Node.isImportDeclaration(node)) { + const moduleSpecifier = node.getModuleSpecifier(); + if (moduleSpecifier.getLiteralText() === '@skeletonlabs/skeleton') { + node.setModuleSpecifier('@skeletonlabs/skeleton-svelte'); + } + for (const importSpecifier of node.getNamedImports()) { + const importedName = importSpecifier.getNameNode(); + const name = importedName.getText(); + if (name in COMPONENT_MAPPINGS) { + importedName.replaceWithText(COMPONENT_MAPPINGS[name]); + } + } + } + if (Node.isIdentifier(node)) { + const name = node.getText(); + if (name in COMPONENT_MAPPINGS) { + node.replaceWithText(COMPONENT_MAPPINGS[name]); + } + } + if (Node.isStringLiteral(node) && !Node.isImportDeclaration(node.getParent())) { + node.setLiteralValue(transformClasses(node.getLiteralValue()).code); } - node.setLiteralValue(transformClasses(node.getLiteralValue()).code); }); file.fixUnusedIdentifiers(); return { 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 c7f92e263..709b125cf 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,106 +1,75 @@ import { describe, expect, it } from 'vitest'; import { transformSvelte } from './transform-svelte.js'; +import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; describe('transformSvelte', () => { - it('transforms imports in instance script', () => { - expect( - transformSvelte(` - + for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { + for (const script of ['instance', 'module']) { + it(`transforms the \`${oldComponent}\` import and its usages in the \`${script}\` script`, () => { + expect( + transformSvelte(` + + import { ${oldComponent} } from "@skeletonlabs/skeleton"; - - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms imports in module script', () => { - expect( - transformSvelte(` - - - +<${oldComponent} /> `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - +<${newComponent} /> ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms classes in instance script', () => { + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } + } + it('transforms classes in an attribute', () => { expect( transformSvelte(` - +
`) .code.trim() .replace(/\r\n|\r|\n/g, '\n') ).toBe( ` - +
` .trim() .replace(/\r\n|\r|\n/g, '\n') ); }); - it('transforms classes in module script', () => { - expect( - transformSvelte(` - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms classes in an attribute', () => { - expect( - transformSvelte(` -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } it('transforms classes in an expression attribute', () => { expect( transformSvelte(` 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 545e9c968..aae91370a 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 @@ -3,6 +3,7 @@ import type { Node } from 'estree'; import { walk } from 'zimmerframe'; import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; +import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; @@ -26,6 +27,26 @@ function transformSvelte(code: string) { } ctx.next(); }, + Identifier(node, ctx) { + if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { + s.update(node.start, node.end, COMPONENT_MAPPINGS[node.name]); + } + ctx.next(); + }, + Component(node, ctx) { + if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { + // Adjusts for the opening tag (`<`) + const adjustedStart = node.start + 1; + s.update(adjustedStart, adjustedStart + node.name.length, COMPONENT_MAPPINGS[node.name]); + } + ctx.next(); + }, + ImportSpecifier(node, ctx) { + if (node.imported.type === 'Identifier' && node.imported.name in COMPONENT_MAPPINGS && hasRange(node.imported)) { + s.update(node.imported.start, node.imported.end, COMPONENT_MAPPINGS[node.imported.name]); + } + ctx.next(); + }, Literal(node, ctx) { const parent = ctx.path.at(-1); if (typeof node.value === 'string' && !(parent && parent.type === 'ImportDeclaration') && hasRange(node)) { From 86969ce5abd6789e1194b0655d5afb7bfb0e2cbc Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Tue, 14 Jan 2025 23:52:15 +0100 Subject: [PATCH 16/26] Feature: Removed components have their imports removed. --- .changeset/wicked-maps-rest.md | 5 + .../transformers/transform-module.test.ts | 65 +++++++++++ .../transformers/transform-module.ts | 29 +++-- .../transformers/transform-svelte.test.ts | 105 +++++++++++++++++- .../transformers/transform-svelte.ts | 63 ++++++++++- .../skeleton-3/utility/removed-components.ts | 3 + 6 files changed, 257 insertions(+), 13 deletions(-) create mode 100644 .changeset/wicked-maps-rest.md create mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/removed-components.ts diff --git a/.changeset/wicked-maps-rest.md b/.changeset/wicked-maps-rest.md new file mode 100644 index 000000000..db217f0e9 --- /dev/null +++ b/.changeset/wicked-maps-rest.md @@ -0,0 +1,5 @@ +--- +'@skeletonlabs/skeleton-cli': patch +--- + +Feature: Removed components have their imports removed. diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts index c0ac53796..8fa12b489 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts @@ -1,8 +1,73 @@ import { describe, expect, it } from 'vitest'; import { transformModule } from './transform-module.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; +import { REMOVED_COMPONENTS } from '../utility/removed-components.js'; describe('transformModuleContent', () => { + for (const removedComponent of REMOVED_COMPONENTS) { + it(`removes the \`${removedComponent}\` named import and import declaration`, () => { + expect( + transformModule(` +import { ${removedComponent} } from "@skeletonlabs/skeleton"; + +${removedComponent}; + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + + +${removedComponent}; + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`removes the \`${removedComponent}\` named import and keeps the other named imports`, () => { + expect( + transformModule(` +import { Foo, ${removedComponent} } from "@skeletonlabs/skeleton"; + +Foo; +${removedComponent}; + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import { Foo } from "@skeletonlabs/skeleton-svelte"; + +Foo; +${removedComponent}; + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`removes the \`${removedComponent}\` named import and keeps the default import`, () => { + expect( + transformModule(` +import Foo, { ${removedComponent} } from "@skeletonlabs/skeleton"; + +Foo; +${removedComponent}; + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` +import Foo from "@skeletonlabs/skeleton-svelte"; + +Foo; +${removedComponent}; + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } + for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { it(`transforms the \`${oldComponent}\` import and its usages`, () => { expect( 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 f8ba530f7..5e880f23d 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 @@ -2,31 +2,44 @@ import { Node } from 'ts-morph'; import { transformClasses } from './transform-classes.js'; import { createSourceFile } from '../../../../../utility/create-source-file.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; +import { REMOVED_COMPONENTS } from '../utility/removed-components'; function transformModule(code: string) { const file = createSourceFile(code); - file.forEachDescendant((node) => { if (Node.isImportDeclaration(node)) { const moduleSpecifier = node.getModuleSpecifier(); if (moduleSpecifier.getLiteralText() === '@skeletonlabs/skeleton') { node.setModuleSpecifier('@skeletonlabs/skeleton-svelte'); } - for (const importSpecifier of node.getNamedImports()) { - const importedName = importSpecifier.getNameNode(); - const name = importedName.getText(); - if (name in COMPONENT_MAPPINGS) { - importedName.replaceWithText(COMPONENT_MAPPINGS[name]); + } + if (Node.isImportSpecifier(node)) { + const importedName = node.getNameNode(); + const name = importedName.getText(); + if (name in COMPONENT_MAPPINGS) { + importedName.replaceWithText(COMPONENT_MAPPINGS[name]); + } + if (REMOVED_COMPONENTS.includes(name)) { + const parent = node.getParent().getParent().getParent(); + if ( + Node.isImportDeclaration(parent) && + parent.getNamedImports().length === 1 && + !parent.getDefaultImport() && + !parent.getNamespaceImport() + ) { + parent.remove(); + } else { + node.remove(); } } } - if (Node.isIdentifier(node)) { + if (!node.wasForgotten() && Node.isIdentifier(node)) { const name = node.getText(); if (name in COMPONENT_MAPPINGS) { node.replaceWithText(COMPONENT_MAPPINGS[name]); } } - if (Node.isStringLiteral(node) && !Node.isImportDeclaration(node.getParent())) { + if (!node.wasForgotten() && Node.isStringLiteral(node) && !Node.isImportDeclaration(node.getParent())) { node.setLiteralValue(transformClasses(node.getLiteralValue()).code); } }); 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 709b125cf..a610c3d07 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,11 +1,110 @@ import { describe, expect, it } from 'vitest'; import { transformSvelte } from './transform-svelte.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; +import { REMOVED_COMPONENTS } from '../utility/removed-components.js'; describe('transformSvelte', () => { + for (const removedComponent of REMOVED_COMPONENTS) { + for (const script of ['instance', 'module']) { + it(`removes the \`${removedComponent}\` named import and import declaration (${script})`, () => { + expect( + transformSvelte(` + + import { ${removedComponent} } from "@skeletonlabs/skeleton"; + + ${removedComponent}; + + +<${removedComponent} /> + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + +\t + + ${removedComponent}; + + +<${removedComponent} /> + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`removes the \`${removedComponent}\` named import and keeps the other named imports (${script})`, () => { + expect( + transformSvelte(` + + import { Foo, +${removedComponent} } from "@skeletonlabs/skeleton"; + + Foo; + ${removedComponent}; + + + +<${removedComponent} /> + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + + import { Foo } from "@skeletonlabs/skeleton-svelte"; + + Foo; + ${removedComponent}; + + + +<${removedComponent} /> + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + it(`removes the \`${removedComponent}\` named import and keeps the default import (${script})`, () => { + expect( + transformSvelte(` + + import Foo, { ${removedComponent}, Bar } from "@skeletonlabs/skeleton"; + + Foo; + ${removedComponent}; + Bar; + + + +<${removedComponent} /> + + `) + .code.trim() + .replace(/\r\n|\r|\n/g, '\n') + ).toBe( + ` + + import Foo, { Bar } from "@skeletonlabs/skeleton-svelte"; + + Foo; + ${removedComponent}; + Bar; + + + +<${removedComponent} /> + + ` + .trim() + .replace(/\r\n|\r|\n/g, '\n') + ); + }); + } + } for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { for (const script of ['instance', 'module']) { - it(`transforms the \`${oldComponent}\` import and its usages in the \`${script}\` script`, () => { + it(`transforms the \`${oldComponent}\` import and its usages (${script})`, () => { expect( transformSvelte(` @@ -54,7 +153,7 @@ describe('transformSvelte', () => { expect( transformSvelte(` - const classes = "rounded-token"; + const foo = "rounded-token"; `) .code.trim() @@ -62,7 +161,7 @@ describe('transformSvelte', () => { ).toBe( ` - const classes = "rounded"; + const foo = "rounded"; ` .trim() 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 aae91370a..71f562f11 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 @@ -4,6 +4,7 @@ import { walk } from 'zimmerframe'; import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; +import { REMOVED_COMPONENTS } from '../utility/removed-components'; function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; @@ -42,8 +43,66 @@ function transformSvelte(code: string) { ctx.next(); }, ImportSpecifier(node, ctx) { - if (node.imported.type === 'Identifier' && node.imported.name in COMPONENT_MAPPINGS && hasRange(node.imported)) { - s.update(node.imported.start, node.imported.end, COMPONENT_MAPPINGS[node.imported.name]); + if (node.imported.type === 'Identifier') { + if (node.imported.name in COMPONENT_MAPPINGS && hasRange(node.imported)) { + s.update(node.imported.start, node.imported.end, COMPONENT_MAPPINGS[node.imported.name]); + } + if (REMOVED_COMPONENTS.includes(node.imported.name) && hasRange(node.imported) && hasRange(node)) { + const parent = ctx.path.at(-1); + if (parent && parent.type === 'ImportDeclaration' && hasRange(parent)) { + const hasDefaultImport = parent.specifiers.some((s) => s.type === 'ImportDefaultSpecifier'); + if (parent.specifiers.length === 1) { + s.remove(parent.start, parent.end); + } else if (parent.specifiers.length === 2 && hasDefaultImport) { + // If we're removing the last named import and there's a default import, + // keep the default import but remove the named import block entirely + const defaultSpecifier = parent.specifiers.find((s) => s.type === 'ImportDefaultSpecifier'); + const importStart = parent.start; + const importEnd = parent.end; + if (defaultSpecifier && hasRange(defaultSpecifier)) { + s.overwrite(importStart, importEnd, `import ${defaultSpecifier.local.name} from "${parent.source.value}";`); + } + } else { + const specifierIndex = parent.specifiers.findIndex((s) => s === node); + // Handle the removal of import specifiers while preserving commas + if (specifierIndex === (hasDefaultImport ? 1 : 0)) { + // First named specifier (after default import if present) + const nextSpecifier = parent.specifiers[specifierIndex + 1]; + if (hasRange(nextSpecifier)) { + s.remove(node.start, nextSpecifier.start); + } + } else if (specifierIndex === parent.specifiers.length - 1) { + // Last specifier + const previousSpecifier = parent.specifiers[specifierIndex - 1]; + if (hasRange(previousSpecifier)) { + s.remove(previousSpecifier.end, node.end); + } + } else { + // Middle specifier + const previousSpecifier = parent.specifiers[specifierIndex - 1]; + const nextSpecifier = parent.specifiers[specifierIndex + 1]; + if (hasRange(previousSpecifier) && hasRange(nextSpecifier)) { + s.overwrite( + previousSpecifier.end, + nextSpecifier.start, + ', ' // Ensure consistent formatting + ); + } + } + // Check if we've removed all named imports and need to clean up the empty brackets + const remainingNamedImports = parent.specifiers.filter((s) => s.type !== 'ImportDefaultSpecifier').length - 1; // -1 for the one we're removing + if (remainingNamedImports === 0 && hasDefaultImport && hasRange(parent.source)) { + // Find the start of the named imports block (after the default import) + const defaultSpecifier = parent.specifiers.find((s) => s.type === 'ImportDefaultSpecifier'); + if (defaultSpecifier && hasRange(defaultSpecifier)) { + // Remove everything from after the default import name to before the 'from' + const fromKeyword = parent.source.start - 6; // 6 = length of ' from ' + s.remove(defaultSpecifier.end, fromKeyword); + } + } + } + } + } } ctx.next(); }, diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/removed-components.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/removed-components.ts new file mode 100644 index 000000000..8daa7f56d --- /dev/null +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/removed-components.ts @@ -0,0 +1,3 @@ +const REMOVED_COMPONENTS = ['AppShell', 'Autocomplete', 'ConicGradient', 'Lightswitch', 'ListBox', 'Stepper', 'Table']; + +export { REMOVED_COMPONENTS }; From f91af073c690fc21f5b578caf4a250e7fe172cc0 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 08:19:09 +0100 Subject: [PATCH 17/26] Moving to fixtures, much easier to add test cases, although less dynamic --- .../migrate/migrations/skeleton-3/index.ts | 5 +- .../transformers/transform-package.test.ts | 127 ------- .../transformers/transform-package.ts | 5 +- .../transform-tailwind-config.test.ts | 334 ------------------ .../migrate/skeleton-3/classes.test.ts} | 2 +- .../test/migrate/skeleton-3/fixtures.test.ts | 64 ++++ .../fixtures/package/update-skeleton | 5 + .../package/update-skeleton-and-tw-plugin | 6 + .../fixtures/package/update-tw-plugin | 5 + .../fixtures/svelte/remove-component-import | 7 + .../fixtures/svelte/rename-component-import | 7 + .../fixtures/tailwind-config/content-path | 8 + .../content-path-different-index | 8 + .../fixtures/tailwind-config/custom-theme | 13 + .../fixtures/tailwind-config/no-themes | 10 + .../fixtures/tailwind-config/perserve-config | 12 + .../preset-theme-object-notation | 53 +++ .../preset-theme-string-notation | 11 + .../results/package/update-skeleton | 5 + .../package/update-skeleton-and-tw-plugin | 6 + .../results/package/update-tw-plugin | 5 + .../results/svelte/remove-component-import | 7 + .../results/svelte/rename-component-import | 7 + .../results/tailwind-config/content-path | 8 + .../content-path-different-index | 8 + .../results/tailwind-config/custom-theme | 20 ++ .../results/tailwind-config/no-themes | 9 + .../results/tailwind-config/perserve-config | 11 + .../preset-theme-object-notation | 10 + .../preset-theme-string-notation | 10 + 30 files changed, 321 insertions(+), 467 deletions(-) delete mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts delete mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts rename packages/skeleton-cli/{src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts => test/migrate/skeleton-3/classes.test.ts} (98%) create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton-and-tw-plugin create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-tw-plugin create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path-different-index create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/custom-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/no-themes create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/perserve-config create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-object-notation create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-string-notation create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton-and-tw-plugin create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-tw-plugin create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path-different-index create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/custom-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/no-themes create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/perserve-config create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-object-notation create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-string-notation 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 09a2de8bf..04a4ee9ea 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 @@ -11,6 +11,7 @@ import { transformApp } from './transformers/transform-app.js'; import { readFile, writeFile } from 'node:fs/promises'; import { installDependencies } from '../../../../utility/install-dependencies.js'; import { FALLBACK_THEME } from './utility/constants'; +import getLatestVersion from 'latest-version'; export default async function (options: MigrateOptions) { const cwd = options.cwd ?? process.cwd(); @@ -57,7 +58,9 @@ export default async function (options: MigrateOptions) { packageSpinner.start(`Migrating ${pkg.matcher}...`); try { const pkgCode = await readFile(pkg.paths[0], 'utf-8'); - const transformedPkg = await transformPackage(pkgCode); + 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' }); + const transformedPkg = transformPackage(pkgCode, skeletonVersion, skeletonSvelteVersion); await writeFile(pkg.paths[0], transformedPkg.code); packageSpinner.stop(`Successfully migrated ${pkg.matcher}`); } catch (e) { 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 deleted file mode 100644 index 8ae995511..000000000 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-package.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { transformPackage } from './transform-package.js'; -import getLatestVersion from 'latest-version'; -import { describe, it, expect, vi } from 'vitest'; - -vi.mock('latest-version', () => { - return { - default: vi.fn() - }; -}); - -describe('transformPackage', () => { - it('updates the "@skeletonlabs/tw-plugin" dependency', async () => { - vi.mocked(getLatestVersion).mockReturnValue(Promise.resolve('3.0.0')); - expect( - ( - await transformPackage(` -{ - "dependencies": { - "@skeletonlabs/tw-plugin": "^1.0.0" - } -} - `) - ).code - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -{ - "dependencies": { - "@skeletonlabs/skeleton": "^3.0.0" - } -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('updates the "@skeletonlabs/skeleton" dependency', async () => { - vi.mocked(getLatestVersion).mockReturnValue(Promise.resolve('3.0.0')); - - expect( - ( - await transformPackage(` -{ - "dependencies": { - "@skeletonlabs/skeleton": "^2.0.0" - } -} - `) - ).code - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -{ - "dependencies": { - "@skeletonlabs/skeleton-svelte": "^3.0.0" - } -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('updates both "@skeletonlabs/tw-plugin" and "@skeletonlabs/skeleton" dependencies', async () => { - vi.mocked(getLatestVersion).mockImplementation((pkg) => { - switch (pkg) { - case '@skeletonlabs/skeleton-svelte': - return Promise.resolve('1.0.0'); - case '@skeletonlabs/skeleton': - return Promise.resolve('3.0.0'); - } - return Promise.resolve('0.0.0'); - }); - expect( - ( - await transformPackage(` -{ - "dependencies": { - "@skeletonlabs/tw-plugin": "^1.0.0", - "@skeletonlabs/skeleton": "^2.0.0" - } -} - `) - ).code - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -{ - "dependencies": { - "@skeletonlabs/skeleton": "^3.0.0", - "@skeletonlabs/skeleton-svelte": "^1.0.0" - } -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('does not update "@skeletonlabs/skeleton" if version is >=3.0.0', async () => { - vi.mocked(getLatestVersion).mockReturnValue(Promise.resolve('3.0.0')); - expect( - ( - await transformPackage(` -{ - "dependencies": { - "@skeletonlabs/skeleton": "^3.0.0" - } -} - `) - ).code - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -{ - "dependencies": { - "@skeletonlabs/skeleton": "^3.0.0" - } -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); -}); 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 adf749e6d..646333567 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,13 +1,10 @@ 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 transformPackage(code: string) { +function transformPackage(code: string, skeletonVersion: string, skeletonSvelteVersion: 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' }); for (const field of ['dependencies', 'devDependencies'] as const) { if (!pkg[field]) { continue; 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 deleted file mode 100644 index dddc96759..000000000 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.test.ts +++ /dev/null @@ -1,334 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { transformTailwindConfig } from './transform-tailwind-config.js'; -import { THEME_MAPPINGS } from '../utility/theme-mappings.js'; - -describe('transformTailwindConfig', () => { - it('transforms content path', () => { - expect( - transformTailwindConfig(` -import { join } from "path"; - -export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") - ] -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { contentPath } from "@skeletonlabs/skeleton/plugin"; - -export default { - content: [ - "./src/**/*.{html,js,svelte,ts}", - contentPath(import.meta.url, "svelte") - ] -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms content path with at different index', () => { - expect( - transformTailwindConfig(` -import { join } from "path"; - -export default { - content: [ - join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}"), - "./src/**/*.{html,js,svelte,ts}" - ] -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { contentPath } from "@skeletonlabs/skeleton/plugin"; - -export default { - content: [ - contentPath(import.meta.url, "svelte"), - "./src/**/*.{html,js,svelte,ts}" - ] -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - for (const [oldTheme, newTheme] of Object.entries(THEME_MAPPINGS)) { - it(`transforms a config with ${oldTheme} theme`, () => { - expect( - transformTailwindConfig(` -import { skeleton } from "@skeletonlabs/tw-plugin"; - -export default { - plugins: [ - skeleton({ - themes: { - preset: ["${oldTheme}"] - } - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { skeleton } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; - -export default { - plugins: [ - skeleton({ - themes: [themes.${newTheme}] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`transforms a config with ${oldTheme} theme using the object theme format`, () => { - expect( - transformTailwindConfig(` -import { join } from "path"; -import { skeleton } from "@skeletonlabs/tw-plugin"; - -export default { - plugins: [ - skeleton({ - themes: { - preset: [ - { - name: "${oldTheme}", - enhancements: true - } - ] - } - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { skeleton } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; - -export default { - plugins: [ - skeleton({ - themes: [themes.${newTheme}] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - it(`transforms a config with multiple preset themes`, () => { - expect( - transformTailwindConfig(` -import { skeleton } from "@skeletonlabs/tw-plugin"; - -export default { - plugins: [ - skeleton({ - themes: { - preset: ["skeleton", "gold-nouveau"] - } - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { skeleton } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; - -export default { - plugins: [ - skeleton({ - themes: [themes.legacy, themes.nouveau] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms a config with custom themes', () => { - expect( - transformTailwindConfig(` -import { skeleton } from "@skeletonlabs/tw-plugin"; -import myCustomTheme from "./my-custom-theme.js"; - -export default { - plugins: [ - skeleton({ - themes: { - custom: [myCustomTheme] - } - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -/** - * SKELETON MIGRATION NOTICE - * - * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: - * - * - myCustomTheme - * - * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. - */ - -import { skeleton } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; - -export default { - plugins: [ - skeleton({ - themes: [themes.cerberus /* myCustomTheme */] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms a config with multiple custom themes', () => { - expect( - transformTailwindConfig(` -import { skeleton } from "@skeletonlabs/tw-plugin"; -import myCustomTheme from "./my-custom-theme.js"; -import myCustomThemeTwo from "./my-custom-theme-two.js"; - -export default { - plugins: [ - skeleton({ - themes: { - custom: [myCustomTheme, myCustomThemeTwo] - } - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -/** - * SKELETON MIGRATION NOTICE - * - * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: - * - * - myCustomTheme - * - myCustomThemeTwo - * - * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. - */ - -import { skeleton } from "@skeletonlabs/skeleton/plugin"; -import * as themes from "@skeletonlabs/skeleton/themes"; - -export default { - plugins: [ - skeleton({ - themes: [themes.cerberus /* myCustomTheme, myCustomThemeTwo */] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('does not add a themes import when no themes are set', () => { - expect( - transformTailwindConfig(` -import { join } from "path"; -import { skeleton } from "@skeletonlabs/tw-plugin"; - -export default { - plugins: [ - skeleton({ - themes: {} - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { skeleton } from "@skeletonlabs/skeleton/plugin"; - -export default { - plugins: [ - skeleton({ - themes: [] - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('keeps other skeleton configuration options', () => { - expect( - transformTailwindConfig(` -import { join } from "path"; -import { skeleton } from "@skeletonlabs/tw-plugin"; - -export default { - plugins: [ - skeleton({ - base: true, - themes: {}, - prefix: "sk-" - }) - ], -} - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { skeleton } from "@skeletonlabs/skeleton/plugin"; - -export default { - plugins: [ - skeleton({ - base: true, - themes: [], - prefix: "sk-" - }) - ], -} - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); -}); diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts b/packages/skeleton-cli/test/migrate/skeleton-3/classes.test.ts similarity index 98% rename from packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts rename to packages/skeleton-cli/test/migrate/skeleton-3/classes.test.ts index 89c178b76..cacfda259 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.test.ts +++ b/packages/skeleton-cli/test/migrate/skeleton-3/classes.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { transformClasses } from './transform-classes.js'; +import { transformClasses } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-classes.js'; describe('transformClasses', () => { const COLORS = ['primary', 'secondary', 'tertiary', 'success', 'warning', 'error', 'surface']; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts new file mode 100644 index 000000000..3f8942423 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts @@ -0,0 +1,64 @@ +import { fileURLToPath, resolve } from 'node:url'; +import { describe, expect, test } from 'vitest'; +import { readFile } from 'node:fs/promises'; +import { transformSvelte } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.js'; +import { transformModule } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-module.js'; +import { transformTailwindConfig } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-tailwind-config.js'; +import { transformApp } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-app.js'; +import { transformPackage } from '../../../src/commands/migrate/migrations/skeleton-3/transformers/transform-package.js'; + +const TRANSFORMER_MAP = { + svelte: transformSvelte, + module: transformModule, + 'tailwind-config': transformTailwindConfig, + app: transformApp, + package: transformPackage +}; + +const fixturesTest = import.meta.glob('./fixtures/**/*', { + query: '?raw' +}); + +function getResult(code: string, transformer: keyof typeof TRANSFORMER_MAP) { + switch (transformer) { + case 'svelte': + case 'module': + case 'tailwind-config': + return TRANSFORMER_MAP[transformer](code).code; + case 'app': + return TRANSFORMER_MAP[transformer](code, 'cerberus').code; + case 'package': + return TRANSFORMER_MAP[transformer](code, '3.0.0', '1.0.0').code; + } +} + +const testCases: Record = {}; + +for (const path of Object.keys(fixturesTest)) { + const name = path.split('/').at(-1); + const transformerName = path.split('/').at(-2) as keyof typeof TRANSFORMER_MAP | undefined; + if (!name || !transformerName || !(transformerName in TRANSFORMER_MAP)) { + continue; + } + if (!testCases[transformerName]) { + testCases[transformerName] = []; + } + testCases[transformerName].push({ name, path }); +} + +describe('fixtures', () => { + for (const [transformerName, cases] of Object.entries(testCases)) { + describe(transformerName, () => { + for (const { name, path } of cases) { + test(name, async () => { + const result = getResult( + await readFile(resolve(fileURLToPath(import.meta.url), path), 'utf-8'), + transformerName as keyof typeof TRANSFORMER_MAP + ); + const expected = await readFile(resolve(fileURLToPath(import.meta.url), path.replace('fixtures', 'results')), 'utf-8'); + expect(result.trim()).toEqual(expected.trim()); + }); + } + }); + } +}); diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton new file mode 100644 index 000000000..9dd58e016 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@skeletonlabs/skeleton": "^2.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton-and-tw-plugin b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton-and-tw-plugin new file mode 100644 index 000000000..8cb401573 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-skeleton-and-tw-plugin @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@skeletonlabs/tw-plugin": "^1.0.0", + "@skeletonlabs/skeleton": "^2.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-tw-plugin b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-tw-plugin new file mode 100644 index 000000000..85abfea77 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/package/update-tw-plugin @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@skeletonlabs/tw-plugin": "^1.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import new file mode 100644 index 000000000..2da568e03 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import @@ -0,0 +1,7 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import new file mode 100644 index 000000000..a3cbc8fb7 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import @@ -0,0 +1,7 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path new file mode 100644 index 000000000..1a25bb17f --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path @@ -0,0 +1,8 @@ +import { join } from "path"; + +export default { + content: [ + "./src/**/*.{html,js,svelte,ts}", + join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}") + ] +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path-different-index b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path-different-index new file mode 100644 index 000000000..957d5f276 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/content-path-different-index @@ -0,0 +1,8 @@ +import { join } from "path"; + +export default { + content: [ + join(require.resolve("@skeletonlabs/skeleton"), "../**/*.{html,js,svelte,ts}"), + "./src/**/*.{html,js,svelte,ts}" + ] +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/custom-theme b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/custom-theme new file mode 100644 index 000000000..829c9270f --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/custom-theme @@ -0,0 +1,13 @@ +import { skeleton } from "@skeletonlabs/tw-plugin"; +import myCustomTheme from "./my-custom-theme.js"; +import myCustomThemeTwo from "./my-custom-theme-two.js"; + +export default { + plugins: [ + skeleton({ + themes: { + custom: [myCustomTheme, myCustomThemeTwo] + } + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/no-themes b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/no-themes new file mode 100644 index 000000000..837693c39 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/no-themes @@ -0,0 +1,10 @@ +import { join } from "path"; +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + themes: {} + }) + ], +} \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/perserve-config b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/perserve-config new file mode 100644 index 000000000..6390e7f70 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/perserve-config @@ -0,0 +1,12 @@ +import { join } from "path"; +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + base: true, + themes: {}, + prefix: "sk-" + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-object-notation b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-object-notation new file mode 100644 index 000000000..d5bfdea86 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-object-notation @@ -0,0 +1,53 @@ +import { join } from "path"; +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + themes: { + preset: [ + { + name: "skeleton", + enhancements: true + }, + { + name: "gold-nouveau", + enhancements: true + }, + { + name: "wintry", + enhancements: true + }, + { + name: "modern", + enhancements: true + }, + { + name: "rocket", + enhancements: true + }, + { + name: "seafoam", + enhancements: true + }, + { + name: "vintage", + enhancements: true + }, + { + name: "sahara", + enhancements: true + }, + { + name: "hamlindigo", + enhancements: true + }, + { + name: "crimson", + enhancements: true + } + ] + } + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-string-notation b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-string-notation new file mode 100644 index 000000000..5b2ba8748 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/tailwind-config/preset-theme-string-notation @@ -0,0 +1,11 @@ +import { skeleton } from "@skeletonlabs/tw-plugin"; + +export default { + plugins: [ + skeleton({ + themes: { + preset: ["skeleton", "gold-nouveau", "wintry", "modern", "rocket", "seafoam", "vintage", "sahara", "hamlindigo", "crimson"] + } + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton new file mode 100644 index 000000000..c972ea9ba --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@skeletonlabs/skeleton-svelte": "^1.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton-and-tw-plugin b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton-and-tw-plugin new file mode 100644 index 000000000..e8246862a --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-skeleton-and-tw-plugin @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@skeletonlabs/skeleton": "^3.0.0", + "@skeletonlabs/skeleton-svelte": "^1.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-tw-plugin b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-tw-plugin new file mode 100644 index 000000000..c971fb3f8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/package/update-tw-plugin @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@skeletonlabs/skeleton": "^3.0.0" + } +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import new file mode 100644 index 000000000..4b15a7337 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import @@ -0,0 +1,7 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import new file mode 100644 index 000000000..e571c88e1 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import @@ -0,0 +1,7 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path new file mode 100644 index 000000000..136216ed8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path @@ -0,0 +1,8 @@ +import { contentPath } from "@skeletonlabs/skeleton/plugin"; + +export default { + content: [ + "./src/**/*.{html,js,svelte,ts}", + contentPath(import.meta.url, "svelte") + ] +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path-different-index b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path-different-index new file mode 100644 index 000000000..d951766f8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/content-path-different-index @@ -0,0 +1,8 @@ +import { contentPath } from "@skeletonlabs/skeleton/plugin"; + +export default { + content: [ + contentPath(import.meta.url, "svelte"), + "./src/**/*.{html,js,svelte,ts}" + ] +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/custom-theme b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/custom-theme new file mode 100644 index 000000000..fbb1cfad5 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/custom-theme @@ -0,0 +1,20 @@ +/** + * SKELETON MIGRATION NOTICE + * + * The following custom themes were detected and commented out due to them not being compatible with the V3 theme format: + * + * - myCustomTheme + * - myCustomThemeTwo + * + * See https://github.com/skeletonlabs/skeleton/discussions/2921 for info on how to migrate these yourself. + */ +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.cerberus /* myCustomTheme, myCustomThemeTwo */] + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/no-themes b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/no-themes new file mode 100644 index 000000000..a4473cff1 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/no-themes @@ -0,0 +1,9 @@ +import { skeleton } from "@skeletonlabs/skeleton/plugin"; + +export default { + plugins: [ + skeleton({ + themes: [] + }) + ], +} \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/perserve-config b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/perserve-config new file mode 100644 index 000000000..021ea3d4a --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/perserve-config @@ -0,0 +1,11 @@ +import { skeleton } from "@skeletonlabs/skeleton/plugin"; + +export default { + plugins: [ + skeleton({ + base: true, + themes: [], + prefix: "sk-" + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-object-notation b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-object-notation new file mode 100644 index 000000000..59c3b6b60 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-object-notation @@ -0,0 +1,10 @@ +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.legacy, themes.nouveau, themes.wintry, themes.modern, themes.rocket, themes.seafoam, themes.vintage, themes.sahara, themes.hamlindigo, themes.crimson] + }) + ], +} diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-string-notation b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-string-notation new file mode 100644 index 000000000..59c3b6b60 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/tailwind-config/preset-theme-string-notation @@ -0,0 +1,10 @@ +import { skeleton } from "@skeletonlabs/skeleton/plugin"; +import * as themes from "@skeletonlabs/skeleton/themes"; + +export default { + plugins: [ + skeleton({ + themes: [themes.legacy, themes.nouveau, themes.wintry, themes.modern, themes.rocket, themes.seafoam, themes.vintage, themes.sahara, themes.hamlindigo, themes.crimson] + }) + ], +} From 0e3d28f4f3542b5631955cce9a1f747b0171b00e Mon Sep 17 00:00:00 2001 From: Hugo Korte <63101006+Hugos68@users.noreply.github.com> Date: Wed, 15 Jan 2025 08:53:54 +0100 Subject: [PATCH 18/26] Fix tab? --- .../migrate/skeleton-3/results/svelte/remove-component-import | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import index 4b15a7337..934f15210 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import @@ -1,5 +1,5 @@ From 70604cc7d763cabf133e79187d1852e8ddc99ef5 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 10:58:25 +0100 Subject: [PATCH 19/26] Add tests --- .../test/migrate/skeleton-3/fixtures.test.ts | 18 +++++++++--------- .../fixtures/svelte/remove-component-import | 2 -- .../remove-component-import-keep-default | 5 +++++ .../remove-component-import-keep-named-imports | 5 +++++ .../results/svelte/remove-component-import | 2 -- .../remove-component-import-keep-default | 5 +++++ .../remove-component-import-keep-named-imports | 5 +++++ 7 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts index 3f8942423..edc53498f 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts @@ -15,7 +15,7 @@ const TRANSFORMER_MAP = { package: transformPackage }; -const fixturesTest = import.meta.glob('./fixtures/**/*', { +const fixtures = import.meta.glob('./fixtures/**/*', { query: '?raw' }); @@ -32,22 +32,22 @@ function getResult(code: string, transformer: keyof typeof TRANSFORMER_MAP) { } } -const testCases: Record = {}; +const fixtureTests: Record = {}; -for (const path of Object.keys(fixturesTest)) { +for (const path of Object.keys(fixtures)) { const name = path.split('/').at(-1); - const transformerName = path.split('/').at(-2) as keyof typeof TRANSFORMER_MAP | undefined; - if (!name || !transformerName || !(transformerName in TRANSFORMER_MAP)) { + const transformer = path.split('/').at(-2) as keyof typeof TRANSFORMER_MAP | undefined; + if (!name || !transformer || !(transformer in TRANSFORMER_MAP)) { continue; } - if (!testCases[transformerName]) { - testCases[transformerName] = []; + if (!fixtureTests[transformer]) { + fixtureTests[transformer] = []; } - testCases[transformerName].push({ name, path }); + fixtureTests[transformer].push({ name, path }); } describe('fixtures', () => { - for (const [transformerName, cases] of Object.entries(testCases)) { + for (const [transformerName, cases] of Object.entries(fixtureTests)) { describe(transformerName, () => { for (const { name, path } of cases) { test(name, async () => { diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import index 2da568e03..e76e36a82 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import @@ -1,7 +1,5 @@ diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default new file mode 100644 index 000000000..44272db14 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default @@ -0,0 +1,5 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports new file mode 100644 index 000000000..61bf26a4d --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports @@ -0,0 +1,5 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import index 934f15210..a82d4b9af 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import @@ -1,7 +1,5 @@ diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default new file mode 100644 index 000000000..575e77891 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default @@ -0,0 +1,5 @@ + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports new file mode 100644 index 000000000..9ac4c0025 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports @@ -0,0 +1,5 @@ + + + From 734ec0dc0283d286f0fbdd77815b7950af958eeb Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 11:58:34 +0100 Subject: [PATCH 20/26] Move testing to fixtures --- packages/skeleton-cli/package.json | 6 +- .../transformers/transform-app.test.ts | 57 ----- .../transformers/transform-module.test.ts | 126 ---------- .../transformers/transform-svelte.test.ts | 238 ------------------ .../skeleton-3/utility/component-mappings.ts | 2 +- .../test/migrate/skeleton-3/fixtures.test.ts | 6 +- .../skeleton-3/fixtures/app/add-data-theme | 1 + .../fixtures/app/replace-data-theme | 1 + .../fixtures/module/classes-in-identifiers | 1 + .../fixtures/module/remove-component-import | 9 + .../remove-component-import-keep-default | 10 + ...remove-component-import-keep-named-imports | 11 + .../fixtures/module/rename-component-import | 12 + .../fixtures/svelte/classes-in-attribute | 1 + .../svelte/classes-in-class-directive | 1 + ...classes-in-class-directive-with-identifier | 5 + .../classes-in-class-directive-with-literal | 1 + .../svelte/classes-in-expression-attribute | 1 + .../fixtures/svelte/classes-in-identifiers | 3 + .../fixtures/svelte/remove-component-import | 8 +- .../remove-component-import-keep-default | 9 +- ...remove-component-import-keep-named-imports | 10 +- .../fixtures/svelte/rename-component-import | 20 +- .../skeleton-3/results/app/add-data-theme | 1 + .../skeleton-3/results/app/replace-data-theme | 1 + .../results/module/classes-in-identifiers | 1 + .../results/module/remove-component-import | 9 + .../remove-component-import-keep-default | 10 + ...remove-component-import-keep-named-imports | 11 + .../results/module/rename-component-import | 12 + .../results/svelte/classes-in-attribute | 1 + .../results/svelte/classes-in-class-directive | 1 + ...classes-in-class-directive-with-identifier | 5 + .../classes-in-class-directive-with-literal | 1 + .../svelte/classes-in-expression-attribute | 1 + .../results/svelte/classes-in-identifiers | 3 + .../results/svelte/remove-component-import | 8 +- .../remove-component-import-keep-default | 9 +- ...remove-component-import-keep-named-imports | 8 + .../results/svelte/rename-component-import | 20 +- pnpm-lock.yaml | 18 +- 41 files changed, 218 insertions(+), 441 deletions(-) delete mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts delete mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts delete mode 100644 packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/add-data-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/replace-data-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/classes-in-identifiers create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-default create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-named-imports create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/rename-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-attribute create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-identifier create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-literal create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-expression-attribute create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/app/add-data-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/app/replace-data-theme create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/module/classes-in-identifiers create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-default create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-named-imports create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/module/rename-component-import create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-attribute create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-identifier create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-literal create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-expression-attribute create mode 100644 packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers diff --git a/packages/skeleton-cli/package.json b/packages/skeleton-cli/package.json index 6b30bf5ba..1cd5fd9ee 100644 --- a/packages/skeleton-cli/package.json +++ b/packages/skeleton-cli/package.json @@ -17,8 +17,7 @@ "bin": "./dist/index.mjs", "types": "./dist/index.d.ts", "files": [ - "dist", - "!**/*.test.*" + "dist" ], "scripts": { "package": "unbuild", @@ -27,8 +26,8 @@ "test:watch": "vitest watch" }, "devDependencies": { - "@types/jsdom": "^21.1.7", "@types/estree": "^1.0.6", + "@types/jsdom": "^21.1.7", "@types/node": "^22.1.0", "@types/semver": "^7.5.8", "type-fest": "^4.27.0", @@ -42,6 +41,7 @@ "colorette": "^2.0.20", "commander": "^13.0.0", "detect-indent": "^7.0.1", + "esrap": "^1.4.3", "fast-glob": "^3.3.1", "latest-version": "^9.0.0", "magic-string": "^0.30.17", 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 deleted file mode 100644 index 3a469afb8..000000000 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-app.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { transformApp } from './transform-app.js'; -import { THEME_MAPPINGS } from '../utility/theme-mappings.js'; - -describe('transformsApp', () => { - for (const [oldTheme, newTheme] of Object.entries(THEME_MAPPINGS)) { - it(`transforms the \`data-theme="${oldTheme}"\` attribute to \`data-theme="${newTheme}"\``, () => { - expect( - transformApp( - ` - -foo - - - - `, - newTheme - ) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - -foo - - - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`adds the \`data-theme="${newTheme}"\` attribute`, () => { - expect( - transformApp( - ` - -foo - - - `, - newTheme - ) - .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-module.test.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts deleted file mode 100644 index 8fa12b489..000000000 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-module.test.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { transformModule } from './transform-module.js'; -import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; -import { REMOVED_COMPONENTS } from '../utility/removed-components.js'; - -describe('transformModuleContent', () => { - for (const removedComponent of REMOVED_COMPONENTS) { - it(`removes the \`${removedComponent}\` named import and import declaration`, () => { - expect( - transformModule(` -import { ${removedComponent} } from "@skeletonlabs/skeleton"; - -${removedComponent}; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - -${removedComponent}; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`removes the \`${removedComponent}\` named import and keeps the other named imports`, () => { - expect( - transformModule(` -import { Foo, ${removedComponent} } from "@skeletonlabs/skeleton"; - -Foo; -${removedComponent}; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { Foo } from "@skeletonlabs/skeleton-svelte"; - -Foo; -${removedComponent}; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`removes the \`${removedComponent}\` named import and keeps the default import`, () => { - expect( - transformModule(` -import Foo, { ${removedComponent} } from "@skeletonlabs/skeleton"; - -Foo; -${removedComponent}; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import Foo from "@skeletonlabs/skeleton-svelte"; - -Foo; -${removedComponent}; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - - for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { - it(`transforms the \`${oldComponent}\` import and its usages`, () => { - expect( - transformModule(` -import { ${oldComponent} } from "@skeletonlabs/skeleton"; - -${oldComponent}; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import { ${newComponent} } from "@skeletonlabs/skeleton-svelte"; - -${newComponent}; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - it('transforms classes in strings', () => { - expect( - transformModule(` -const foo = "rounded-token"; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -const foo = "rounded"; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('does not transform classes in imports', () => { - expect( - transformModule(` -import foo from "rounded-token"; - -foo; - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -import foo from "rounded-token"; - -foo; - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); -}); 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 deleted file mode 100644 index a610c3d07..000000000 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/transformers/transform-svelte.test.ts +++ /dev/null @@ -1,238 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import { transformSvelte } from './transform-svelte.js'; -import { COMPONENT_MAPPINGS } from '../utility/component-mappings.js'; -import { REMOVED_COMPONENTS } from '../utility/removed-components.js'; - -describe('transformSvelte', () => { - for (const removedComponent of REMOVED_COMPONENTS) { - for (const script of ['instance', 'module']) { - it(`removes the \`${removedComponent}\` named import and import declaration (${script})`, () => { - expect( - transformSvelte(` - - import { ${removedComponent} } from "@skeletonlabs/skeleton"; - - ${removedComponent}; - - -<${removedComponent} /> - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - -\t - - ${removedComponent}; - - -<${removedComponent} /> - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`removes the \`${removedComponent}\` named import and keeps the other named imports (${script})`, () => { - expect( - transformSvelte(` - - import { Foo, -${removedComponent} } from "@skeletonlabs/skeleton"; - - Foo; - ${removedComponent}; - - - -<${removedComponent} /> - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - import { Foo } from "@skeletonlabs/skeleton-svelte"; - - Foo; - ${removedComponent}; - - - -<${removedComponent} /> - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it(`removes the \`${removedComponent}\` named import and keeps the default import (${script})`, () => { - expect( - transformSvelte(` - - import Foo, { ${removedComponent}, Bar } from "@skeletonlabs/skeleton"; - - Foo; - ${removedComponent}; - Bar; - - - -<${removedComponent} /> - - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - import Foo, { Bar } from "@skeletonlabs/skeleton-svelte"; - - Foo; - ${removedComponent}; - Bar; - - - -<${removedComponent} /> - - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - } - for (const [oldComponent, newComponent] of Object.entries(COMPONENT_MAPPINGS)) { - for (const script of ['instance', 'module']) { - it(`transforms the \`${oldComponent}\` import and its usages (${script})`, () => { - expect( - transformSvelte(` - - import { ${oldComponent} } from "@skeletonlabs/skeleton"; - - ${oldComponent}; - - -<${oldComponent} /> - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - import { ${newComponent} } from "@skeletonlabs/skeleton-svelte"; - - ${newComponent}; - - -<${newComponent} /> - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - } - it('transforms classes in an attribute', () => { - expect( - transformSvelte(` -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - for (const script of ['instance', 'module']) { - it(`transforms classes in the \`${script}\` script`, () => { - expect( - transformSvelte(` - - const foo = "rounded-token"; - - `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - - const foo = "rounded"; - - ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - } - it('transforms classes in an expression attribute', () => { - expect( - transformSvelte(` -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('transforms classes in the class: directive', () => { - expect( - transformSvelte(` -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('ignores classes in the class: directive that equal an identifier', () => { - expect( - transformSvelte(` - -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` - -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); - it('ignores classes in the class: directive that are also the identifier', () => { - expect( - transformSvelte(` -
- `) - .code.trim() - .replace(/\r\n|\r|\n/g, '\n') - ).toBe( - ` -
- ` - .trim() - .replace(/\r\n|\r|\n/g, '\n') - ); - }); -}); diff --git a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts index 1e30da119..0865c4401 100644 --- a/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts +++ b/packages/skeleton-cli/src/commands/migrate/migrations/skeleton-3/utility/component-mappings.ts @@ -2,7 +2,7 @@ const COMPONENT_MAPPINGS: Record = { AppRail: 'Navigation', FileButton: 'FileUpload', FileDropzone: 'FileUpload', - InputChip: 'TagsInputs', + InputChip: 'TagsInput', Paginator: 'Pagination', ProgressBar: 'Progress', ProgressRadial: 'ProgressRing', diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts index edc53498f..29991d89e 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures.test.ts @@ -32,6 +32,10 @@ function getResult(code: string, transformer: keyof typeof TRANSFORMER_MAP) { } } +function clean(code: string) { + return code.trim().replace(/\r\n|\r|\n/g, '\n'); +} + const fixtureTests: Record = {}; for (const path of Object.keys(fixtures)) { @@ -56,7 +60,7 @@ describe('fixtures', () => { transformerName as keyof typeof TRANSFORMER_MAP ); const expected = await readFile(resolve(fileURLToPath(import.meta.url), path.replace('fixtures', 'results')), 'utf-8'); - expect(result.trim()).toEqual(expected.trim()); + expect(clean(result)).toEqual(clean(expected)); }); } }); diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/add-data-theme b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/add-data-theme new file mode 100644 index 000000000..cc675a47d --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/add-data-theme @@ -0,0 +1 @@ + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/replace-data-theme b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/replace-data-theme new file mode 100644 index 000000000..c8b7661f4 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/app/replace-data-theme @@ -0,0 +1 @@ + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/classes-in-identifiers new file mode 100644 index 000000000..a6a72adc8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/classes-in-identifiers @@ -0,0 +1 @@ +const foo = "rounded-token"; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import new file mode 100644 index 000000000..5b9d28e1a --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import @@ -0,0 +1,9 @@ +import { AppShell, Autocomplete, ConicGradient, Lightswitch, ListBox, Stepper, Table } from "@skeletonlabs/skeleton"; + +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-default new file mode 100644 index 000000000..dd64b4945 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-default @@ -0,0 +1,10 @@ +import Foo, { AppShell, Autocomplete, ConicGradient, Lightswitch, ListBox, Stepper, Table } from "@skeletonlabs/skeleton"; + +Foo; +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-named-imports new file mode 100644 index 000000000..c8839813a --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/remove-component-import-keep-named-imports @@ -0,0 +1,11 @@ +import { Foo, AppShell, Autocomplete, ConicGradient, Lightswitch, ListBox, Stepper, Table, Bar } from "@skeletonlabs/skeleton"; + +Foo; +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; +Bar; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/rename-component-import new file mode 100644 index 000000000..84f9c1419 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/module/rename-component-import @@ -0,0 +1,12 @@ +import { AppRail, FileButton, FileDropzone, InputChip, Paginator, ProgressBar, ProgressRadial, RadioGroup, RangeSlider, SlideToggle } from "@skeletonlabs/skeleton"; + +AppRail; +FileButton; +FileDropzone; +InputChip; +Paginator; +ProgressBar; +ProgressRadial; +RadioGroup; +RangeSlider; +SlideToggle; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-attribute b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-attribute new file mode 100644 index 000000000..8ea1ca3ed --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-attribute @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive new file mode 100644 index 000000000..856a360a8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-identifier b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-identifier new file mode 100644 index 000000000..ffd99487b --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-identifier @@ -0,0 +1,5 @@ + + +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-literal b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-literal new file mode 100644 index 000000000..0b8ef1af1 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-class-directive-with-literal @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-expression-attribute b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-expression-attribute new file mode 100644 index 000000000..09d1115db --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-expression-attribute @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers new file mode 100644 index 000000000..892e6b1ae --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import index e76e36a82..9694d1a80 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import @@ -1,5 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default index 44272db14..d2de522a0 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default @@ -1,5 +1,12 @@ + + + + + + +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports index 61bf26a4d..cf445be12 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports @@ -1,5 +1,13 @@ + + + + + + +
+ \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import index a3cbc8fb7..288c29ca1 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import @@ -1,7 +1,25 @@ + + + + + + + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/app/add-data-theme b/packages/skeleton-cli/test/migrate/skeleton-3/results/app/add-data-theme new file mode 100644 index 000000000..76ee86b81 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/app/add-data-theme @@ -0,0 +1 @@ + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/app/replace-data-theme b/packages/skeleton-cli/test/migrate/skeleton-3/results/app/replace-data-theme new file mode 100644 index 000000000..76ee86b81 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/app/replace-data-theme @@ -0,0 +1 @@ + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/module/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/classes-in-identifiers new file mode 100644 index 000000000..a4dfd8efc --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/classes-in-identifiers @@ -0,0 +1 @@ +const foo = "rounded"; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import new file mode 100644 index 000000000..7549cb271 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import @@ -0,0 +1,9 @@ + + +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-default new file mode 100644 index 000000000..5675d63f2 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-default @@ -0,0 +1,10 @@ +import Foo from "@skeletonlabs/skeleton-svelte"; + +Foo; +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-named-imports new file mode 100644 index 000000000..636264cd0 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/remove-component-import-keep-named-imports @@ -0,0 +1,11 @@ +import { Foo, Bar } from "@skeletonlabs/skeleton-svelte"; + +Foo; +AppShell; +Autocomplete; +ConicGradient; +Lightswitch; +ListBox; +Stepper; +Table; +Bar; \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/module/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/rename-component-import new file mode 100644 index 000000000..631bd037d --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/module/rename-component-import @@ -0,0 +1,12 @@ +import { Navigation, FileUpload, TagsInput, Pagination, Progress, ProgressRing, Segment, Slider, Switch } from "@skeletonlabs/skeleton-svelte"; + +Navigation; +FileUpload; +FileUpload; +TagsInput; +Pagination; +Progress; +ProgressRing; +Segment; +Slider; +Switch; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-attribute b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-attribute new file mode 100644 index 000000000..95495758f --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-attribute @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive new file mode 100644 index 000000000..856a360a8 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-identifier b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-identifier new file mode 100644 index 000000000..b1d451ae0 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-identifier @@ -0,0 +1,5 @@ + + +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-literal b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-literal new file mode 100644 index 000000000..b2ce78b01 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-class-directive-with-literal @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-expression-attribute b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-expression-attribute new file mode 100644 index 000000000..7604aaaa9 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-expression-attribute @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers new file mode 100644 index 000000000..1b3e9d236 --- /dev/null +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import index a82d4b9af..a444a317d 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import @@ -1,5 +1,11 @@ + + + + + +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default index 575e77891..2ef6ed9d3 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default @@ -1,5 +1,12 @@ + + + + + + +
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports index 9ac4c0025..de41d1e32 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports @@ -2,4 +2,12 @@ import { Foo, Bar } from "@skeletonlabs/skeleton-svelte"; + + + + + + +
+ \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import index e571c88e1..8fb9b8767 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import @@ -1,7 +1,25 @@ + + + + + + + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d2ab4c4f..ce58314fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -248,6 +248,9 @@ importers: detect-indent: specifier: ^7.0.1 version: 7.0.1 + esrap: + specifier: ^1.4.3 + version: 1.4.3 fast-glob: specifier: ^3.3.1 version: 3.3.2 @@ -3797,12 +3800,12 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@1.2.3: - resolution: {integrity: sha512-ZlQmCCK+n7SGoqo7DnfKaP1sJZa49P01/dXzmjCASSo04p72w8EksT2NMK8CEX8DhKsfJXANioIw8VyHNsBfvQ==} - esrap@1.4.2: resolution: {integrity: sha512-FhVlJzvTw7ZLxYZ7RyHwQCFE64dkkpzGNNnphaGCLwjqGk1SQcqzbgdx9FowPCktx6NOSHkzvcZ3vsvdH54YXA==} + esrap@1.4.3: + resolution: {integrity: sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==} + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -10727,12 +10730,11 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@1.2.3: + esrap@1.4.2: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - esrap@1.4.2: + esrap@1.4.3: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -13597,7 +13599,7 @@ snapshots: axobject-query: 4.1.0 clsx: 2.1.1 esm-env: 1.2.1 - esrap: 1.4.2 + esrap: 1.4.3 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.17 @@ -13613,7 +13615,7 @@ snapshots: aria-query: 5.3.2 axobject-query: 4.1.0 esm-env: 1.2.1 - esrap: 1.2.3 + esrap: 1.4.2 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.17 From 6a5c22f7fdd870835e702cb02724c3d8459aae64 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 12:15:23 +0100 Subject: [PATCH 21/26] cleanup --- .../migrations/skeleton-3/transformers/transform-module.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 5e880f23d..4891f387e 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,8 +1,8 @@ -import { Node } from 'ts-morph'; import { transformClasses } from './transform-classes.js'; import { createSourceFile } from '../../../../../utility/create-source-file.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; import { REMOVED_COMPONENTS } from '../utility/removed-components'; +import { Node } from 'ts-morph'; function transformModule(code: string) { const file = createSourceFile(code); @@ -14,10 +14,9 @@ function transformModule(code: string) { } } if (Node.isImportSpecifier(node)) { - const importedName = node.getNameNode(); - const name = importedName.getText(); + const name = node.getName(); if (name in COMPONENT_MAPPINGS) { - importedName.replaceWithText(COMPONENT_MAPPINGS[name]); + node.setName(COMPONENT_MAPPINGS[name]); } if (REMOVED_COMPONENTS.includes(name)) { const parent = node.getParent().getParent().getParent(); From 63c1db772e3833bcd3a1be74a636da391f954697 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 12:53:41 +0100 Subject: [PATCH 22/26] Stuff --- .../transformers/transform-module.ts | 8 +++--- .../transformers/transform-tailwind-config.ts | 27 +++++-------------- .../src/utility/is-module-used.ts | 0 .../src/utility/ts-morph/add-named-import.ts | 20 ++++++++++++++ .../get-default-export-object.ts | 0 .../parse-source-file.ts} | 4 +-- 6 files changed, 33 insertions(+), 26 deletions(-) delete mode 100644 packages/skeleton-cli/src/utility/is-module-used.ts create mode 100644 packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts rename packages/skeleton-cli/src/utility/{ => ts-morph}/get-default-export-object.ts (100%) rename packages/skeleton-cli/src/utility/{create-source-file.ts => ts-morph/parse-source-file.ts} (69%) 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 4891f387e..9643244f3 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,11 +1,12 @@ import { transformClasses } from './transform-classes.js'; -import { createSourceFile } from '../../../../../utility/create-source-file.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; import { REMOVED_COMPONENTS } from '../utility/removed-components'; import { Node } from 'ts-morph'; +import {addNamedImport} from "../../../../../utility/ts-morph/add-named-import"; +import {parseSourceFile} from "../../../../../utility/ts-morph/parse-source-file"; function transformModule(code: string) { - const file = createSourceFile(code); + const file = parseSourceFile(code); file.forEachDescendant((node) => { if (Node.isImportDeclaration(node)) { const moduleSpecifier = node.getModuleSpecifier(); @@ -16,7 +17,8 @@ function transformModule(code: string) { if (Node.isImportSpecifier(node)) { const name = node.getName(); if (name in COMPONENT_MAPPINGS) { - node.setName(COMPONENT_MAPPINGS[name]); + node.remove(); + addNamedImport(file, '@skeletonlabs/skeleton-svelte', COMPONENT_MAPPINGS[name]); } if (REMOVED_COMPONENTS.includes(name)) { const parent = node.getParent().getParent().getParent(); 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 441e6b943..33c645db6 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,8 +1,9 @@ import { CallExpression, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph'; -import { getDefaultExportObject } from '../../../../../utility/get-default-export-object'; import { THEME_MAPPINGS } from '../utility/theme-mappings'; -import { createSourceFile } from '../../../../../utility/create-source-file'; import { FALLBACK_THEME } from '../utility/constants'; +import {addNamedImport} from "../../../../../utility/ts-morph/add-named-import"; +import {getDefaultExportObject} from "../../../../../utility/ts-morph/get-default-export-object"; +import {parseSourceFile} from "../../../../../utility/ts-morph/parse-source-file"; function isJoinCallExpression(node: Node): node is CallExpression { if (!Node.isCallExpression(node)) { @@ -82,15 +83,7 @@ function transformTailwindContentOption(file: SourceFile) { } joinCallExpression.replaceWithText('contentPath(import.meta.url, "svelte")'); file.getImportDeclaration('@skeletonlabs/tw-plugin')?.remove(); - const skeletonPluginImportDeclaration = file.getImportDeclaration('@skeletonlabs/skeleton/plugin'); - if (skeletonPluginImportDeclaration) { - skeletonPluginImportDeclaration.addNamedImport('contentPath'); - } else { - file.addImportDeclaration({ - moduleSpecifier: '@skeletonlabs/skeleton/plugin', - namedImports: ['contentPath'] - }); - } + addNamedImport(file, '@skeletonlabs/skeleton/plugin', 'contentPath'); } function getThemeName(node: Node) { @@ -179,15 +172,7 @@ function transformSkeletonThemesOption(file: SourceFile) { }; } file.getImportDeclaration('@skeletonlabs/tw-plugin')?.remove(); - const skeletonPluginImportDeclaration = file.getImportDeclaration('@skeletonlabs/skeleton/plugin'); - if (skeletonPluginImportDeclaration) { - skeletonPluginImportDeclaration.addNamedImport('skeleton'); - } else { - file.addImportDeclaration({ - moduleSpecifier: '@skeletonlabs/skeleton/plugin', - namedImports: ['skeleton'] - }); - } + addNamedImport(file, '@skeletonlabs/skeleton/plugin', 'skeleton'); const skeletonConfigObject = skeletonPluginCallExpression.getArguments().at(0); if (!(skeletonConfigObject && Node.isObjectLiteralExpression(skeletonConfigObject))) { return { @@ -244,7 +229,7 @@ ${[...customThemes].map((theme) => ` * - ${theme}`).join('\n')} } function transformTailwindConfig(code: string) { - const file = createSourceFile(code); + const file = parseSourceFile(code); transformTailwindContentOption(file); const themes = transformSkeletonThemesOption(file); file.fixUnusedIdentifiers(); diff --git a/packages/skeleton-cli/src/utility/is-module-used.ts b/packages/skeleton-cli/src/utility/is-module-used.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts b/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts new file mode 100644 index 000000000..9fda180a9 --- /dev/null +++ b/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts @@ -0,0 +1,20 @@ +import { SourceFile } from "ts-morph"; + +function addNamedImport(file: SourceFile, specifier: string, name: string) { + const existingImportDeclaration = file.getImportDeclaration((importDeclaration) => { + const moduleSpecifier = importDeclaration.getModuleSpecifier().getLiteralText(); + return moduleSpecifier === specifier; + }); + if (existingImportDeclaration) { + if (!existingImportDeclaration.getNamedImports().some((namedImport) => namedImport.getName() === name)) { + existingImportDeclaration.addNamedImport(name); + } + } else { + file.addImportDeclaration({ + moduleSpecifier: specifier, + namedImports: [name] + }); + } +} + +export { addNamedImport }; \ No newline at end of file diff --git a/packages/skeleton-cli/src/utility/get-default-export-object.ts b/packages/skeleton-cli/src/utility/ts-morph/get-default-export-object.ts similarity index 100% rename from packages/skeleton-cli/src/utility/get-default-export-object.ts rename to packages/skeleton-cli/src/utility/ts-morph/get-default-export-object.ts diff --git a/packages/skeleton-cli/src/utility/create-source-file.ts b/packages/skeleton-cli/src/utility/ts-morph/parse-source-file.ts similarity index 69% rename from packages/skeleton-cli/src/utility/create-source-file.ts rename to packages/skeleton-cli/src/utility/ts-morph/parse-source-file.ts index b5ef0b330..785518cd8 100644 --- a/packages/skeleton-cli/src/utility/create-source-file.ts +++ b/packages/skeleton-cli/src/utility/ts-morph/parse-source-file.ts @@ -1,10 +1,10 @@ import { Project } from 'ts-morph'; -function createSourceFile(code: string) { +function parseSourceFile(code: string) { const project = new Project({ useInMemoryFileSystem: true }); return project.createSourceFile('virtual.ts', code); } -export { createSourceFile }; +export { parseSourceFile }; From 6ae2c8fdfcdeb533dbab2bf456edbb2853848a2d Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 13:25:21 +0100 Subject: [PATCH 23/26] Removed import handling from svelte, broken currently --- .../transformers/transform-module.ts | 4 +- .../transformers/transform-svelte.ts | 154 ++++-------------- .../transformers/transform-tailwind-config.ts | 6 +- .../src/utility/ts-morph/add-named-import.ts | 32 ++-- ...sses-in-identifiers => classes-in-literal} | 0 ...sses-in-identifiers => classes-in-literal} | 0 6 files changed, 57 insertions(+), 139 deletions(-) rename packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/{classes-in-identifiers => classes-in-literal} (100%) rename packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/{classes-in-identifiers => classes-in-literal} (100%) 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 9643244f3..2f5ad7b09 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 @@ -2,8 +2,8 @@ import { transformClasses } from './transform-classes.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; import { REMOVED_COMPONENTS } from '../utility/removed-components'; import { Node } from 'ts-morph'; -import {addNamedImport} from "../../../../../utility/ts-morph/add-named-import"; -import {parseSourceFile} from "../../../../../utility/ts-morph/parse-source-file"; +import { addNamedImport } from '../../../../../utility/ts-morph/add-named-import'; +import { parseSourceFile } from '../../../../../utility/ts-morph/parse-source-file'; function transformModule(code: string) { const file = parseSourceFile(code); 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 71f562f11..e0278cce8 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,135 +1,53 @@ import { type AST, parse } from 'svelte/compiler'; import type { Node } from 'estree'; -import { walk } from 'zimmerframe'; +import { type Visitors, walk } from 'zimmerframe'; import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; -import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; -import { REMOVED_COMPONENTS } from '../utility/removed-components'; function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; } +function transformClassLocations(s: MagicString): Visitors { + return { + Literal(node, ctx) { + const parent = ctx.path.at(-1); + const parentIsImportDeclaration = parent && parent.type === 'ImportDeclaration'; + if (typeof node.value === 'string' && !parentIsImportDeclaration && hasRange(node)) { + // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes + s.update(node.start + 1, node.end - 1, transformClasses(node.value).code); + } + ctx.next(); + }, + Text(node, ctx) { + s.update(node.start, node.end, transformClasses(node.data).code); + ctx.next(); + }, + ClassDirective(node, ctx) { + if (!(node.expression.type === 'Identifier' && !('loc' in node.expression) && node.name === node.expression.name) && hasRange(node)) { + const adjustedStart = node.start + 'class:'.length; + s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); + } + ctx.next(); + } + } satisfies Visitors; +} + +function transformImports(s: MagicString) { + return { + // TODO + } satisfies Visitors; +} + function transformSvelte(code: string) { const s = new MagicString(code); const root = parse(code, { modern: true }); - const asts = [root.instance, root.module, root.fragment].filter((node) => !!node); - for (const ast of asts) { - walk( - ast as Node | AST.SvelteNode, - {}, - { - ImportDeclaration(node, ctx) { - if (node.source.type === 'Literal' && node.source.value === '@skeletonlabs/skeleton' && hasRange(node.source)) { - // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes - s.update(node.source.start + 1, node.source.end - 1, '@skeletonlabs/skeleton-svelte'); - } - ctx.next(); - }, - Identifier(node, ctx) { - if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { - s.update(node.start, node.end, COMPONENT_MAPPINGS[node.name]); - } - ctx.next(); - }, - Component(node, ctx) { - if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { - // Adjusts for the opening tag (`<`) - const adjustedStart = node.start + 1; - s.update(adjustedStart, adjustedStart + node.name.length, COMPONENT_MAPPINGS[node.name]); - } - ctx.next(); - }, - ImportSpecifier(node, ctx) { - if (node.imported.type === 'Identifier') { - if (node.imported.name in COMPONENT_MAPPINGS && hasRange(node.imported)) { - s.update(node.imported.start, node.imported.end, COMPONENT_MAPPINGS[node.imported.name]); - } - if (REMOVED_COMPONENTS.includes(node.imported.name) && hasRange(node.imported) && hasRange(node)) { - const parent = ctx.path.at(-1); - if (parent && parent.type === 'ImportDeclaration' && hasRange(parent)) { - const hasDefaultImport = parent.specifiers.some((s) => s.type === 'ImportDefaultSpecifier'); - if (parent.specifiers.length === 1) { - s.remove(parent.start, parent.end); - } else if (parent.specifiers.length === 2 && hasDefaultImport) { - // If we're removing the last named import and there's a default import, - // keep the default import but remove the named import block entirely - const defaultSpecifier = parent.specifiers.find((s) => s.type === 'ImportDefaultSpecifier'); - const importStart = parent.start; - const importEnd = parent.end; - if (defaultSpecifier && hasRange(defaultSpecifier)) { - s.overwrite(importStart, importEnd, `import ${defaultSpecifier.local.name} from "${parent.source.value}";`); - } - } else { - const specifierIndex = parent.specifiers.findIndex((s) => s === node); - // Handle the removal of import specifiers while preserving commas - if (specifierIndex === (hasDefaultImport ? 1 : 0)) { - // First named specifier (after default import if present) - const nextSpecifier = parent.specifiers[specifierIndex + 1]; - if (hasRange(nextSpecifier)) { - s.remove(node.start, nextSpecifier.start); - } - } else if (specifierIndex === parent.specifiers.length - 1) { - // Last specifier - const previousSpecifier = parent.specifiers[specifierIndex - 1]; - if (hasRange(previousSpecifier)) { - s.remove(previousSpecifier.end, node.end); - } - } else { - // Middle specifier - const previousSpecifier = parent.specifiers[specifierIndex - 1]; - const nextSpecifier = parent.specifiers[specifierIndex + 1]; - if (hasRange(previousSpecifier) && hasRange(nextSpecifier)) { - s.overwrite( - previousSpecifier.end, - nextSpecifier.start, - ', ' // Ensure consistent formatting - ); - } - } - // Check if we've removed all named imports and need to clean up the empty brackets - const remainingNamedImports = parent.specifiers.filter((s) => s.type !== 'ImportDefaultSpecifier').length - 1; // -1 for the one we're removing - if (remainingNamedImports === 0 && hasDefaultImport && hasRange(parent.source)) { - // Find the start of the named imports block (after the default import) - const defaultSpecifier = parent.specifiers.find((s) => s.type === 'ImportDefaultSpecifier'); - if (defaultSpecifier && hasRange(defaultSpecifier)) { - // Remove everything from after the default import name to before the 'from' - const fromKeyword = parent.source.start - 6; // 6 = length of ' from ' - s.remove(defaultSpecifier.end, fromKeyword); - } - } - } - } - } - } - ctx.next(); - }, - Literal(node, ctx) { - const parent = ctx.path.at(-1); - if (typeof node.value === 'string' && !(parent && parent.type === 'ImportDeclaration') && hasRange(node)) { - // Add 1 to the start and subtract 1 from the end to exclude (and thus preserve) the quotes - s.update(node.start + 1, node.end - 1, transformClasses(node.value).code); - } - ctx.next(); - }, - Text(node, ctx) { - s.update(node.start, node.end, transformClasses(node.data).code); - ctx.next(); - }, - ClassDirective(node, ctx) { - if ( - !(node.expression.type === 'Identifier' && !('loc' in node.expression) && node.name === node.expression.name) && - hasRange(node) - ) { - const adjustedStart = node.start + 'class:'.length; - s.update(adjustedStart, adjustedStart + node.name.length, transformClasses(node.name).code); - } - ctx.next(); - } - } - ); + for (const ast of [root.instance, root.module, root.fragment].filter((node) => !!node)) { + for (const visitors of [transformImports(s), transformClassLocations(s)]) { + walk(ast as Node | AST.SvelteNode, {}, visitors); + } } return { code: s.toString() 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 33c645db6..a3999bee1 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,9 +1,9 @@ import { CallExpression, Node, ObjectLiteralExpression, SourceFile } from 'ts-morph'; import { THEME_MAPPINGS } from '../utility/theme-mappings'; import { FALLBACK_THEME } from '../utility/constants'; -import {addNamedImport} from "../../../../../utility/ts-morph/add-named-import"; -import {getDefaultExportObject} from "../../../../../utility/ts-morph/get-default-export-object"; -import {parseSourceFile} from "../../../../../utility/ts-morph/parse-source-file"; +import { addNamedImport } from '../../../../../utility/ts-morph/add-named-import'; +import { getDefaultExportObject } from '../../../../../utility/ts-morph/get-default-export-object'; +import { parseSourceFile } from '../../../../../utility/ts-morph/parse-source-file'; function isJoinCallExpression(node: Node): node is CallExpression { if (!Node.isCallExpression(node)) { diff --git a/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts b/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts index 9fda180a9..887577366 100644 --- a/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts +++ b/packages/skeleton-cli/src/utility/ts-morph/add-named-import.ts @@ -1,20 +1,20 @@ -import { SourceFile } from "ts-morph"; +import { SourceFile } from 'ts-morph'; function addNamedImport(file: SourceFile, specifier: string, name: string) { - const existingImportDeclaration = file.getImportDeclaration((importDeclaration) => { - const moduleSpecifier = importDeclaration.getModuleSpecifier().getLiteralText(); - return moduleSpecifier === specifier; - }); - if (existingImportDeclaration) { - if (!existingImportDeclaration.getNamedImports().some((namedImport) => namedImport.getName() === name)) { - existingImportDeclaration.addNamedImport(name); - } - } else { - file.addImportDeclaration({ - moduleSpecifier: specifier, - namedImports: [name] - }); - } + const existingImportDeclaration = file.getImportDeclaration((importDeclaration) => { + const moduleSpecifier = importDeclaration.getModuleSpecifier().getLiteralText(); + return moduleSpecifier === specifier; + }); + if (existingImportDeclaration) { + if (!existingImportDeclaration.getNamedImports().some((namedImport) => namedImport.getName() === name)) { + existingImportDeclaration.addNamedImport(name); + } + } else { + file.addImportDeclaration({ + moduleSpecifier: specifier, + namedImports: [name] + }); + } } -export { addNamedImport }; \ No newline at end of file +export { addNamedImport }; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-literal similarity index 100% rename from packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-identifiers rename to packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/classes-in-literal diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-literal similarity index 100% rename from packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-identifiers rename to packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/classes-in-literal From a11c2d8841481fb7c3a2b5d7375faae7fa208ed4 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 14:03:12 +0100 Subject: [PATCH 24/26] Renaming components, double import needs to be fixed --- .../transformers/transform-svelte.ts | 24 +++++++++++++++++++ .../src/utility/svelte/rename-component.ts | 20 ++++++++++++++++ .../fixtures/svelte/rename-component-import | 2 +- .../results/svelte/rename-component-import | 2 +- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 packages/skeleton-cli/src/utility/svelte/rename-component.ts 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 e0278cce8..381a1777d 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 @@ -3,6 +3,8 @@ import type { Node } from 'estree'; import { type Visitors, walk } from 'zimmerframe'; import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; +import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; +import { renameComponent } from '../../../../../utility/svelte/rename-component'; function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; @@ -35,6 +37,27 @@ function transformClassLocations(s: MagicString): Visitors; } @@ -46,6 +69,7 @@ function transformSvelte(code: string) { }); for (const ast of [root.instance, root.module, root.fragment].filter((node) => !!node)) { for (const visitors of [transformImports(s), transformClassLocations(s)]) { + // @ts-expect-error: FIXME walk(ast as Node | AST.SvelteNode, {}, visitors); } } diff --git a/packages/skeleton-cli/src/utility/svelte/rename-component.ts b/packages/skeleton-cli/src/utility/svelte/rename-component.ts new file mode 100644 index 000000000..52a738f5c --- /dev/null +++ b/packages/skeleton-cli/src/utility/svelte/rename-component.ts @@ -0,0 +1,20 @@ +import MagicString from 'magic-string'; +import type { AST } from 'svelte/compiler'; +import { COMPONENT_MAPPINGS } from '../../commands/migrate/migrations/skeleton-3/utility/component-mappings'; + +function renameComponent(s: MagicString, node: AST.Component) { + const adjustedStart = node.start + 1; + s.update(adjustedStart, adjustedStart + node.name.length, COMPONENT_MAPPINGS[node.name]); + const componentString = s.original.slice(node.start, node.end); + const indexOfNonSelfClosingTag = componentString.lastIndexOf(' node.end) { + return; + } + s.update( + node.start + indexOfNonSelfClosingTag + 2, + node.start + indexOfNonSelfClosingTag + 2 + node.name.length, + COMPONENT_MAPPINGS[node.name] + ); +} + +export { renameComponent }; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import index 288c29ca1..e0c0e3a31 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import @@ -13,7 +13,7 @@ SlideToggle; - + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import index 8fb9b8767..3bf01766c 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import @@ -13,7 +13,7 @@ Switch; - + From f2b20c06acbf3529c9e6c6717298116604d6ac65 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 14:12:10 +0100 Subject: [PATCH 25/26] Improve component test cases to contain both self closing and "normal" closing components --- .../fixtures/svelte/remove-component-import | 9 ++++++++- .../svelte/remove-component-import-keep-default | 10 +++++++++- .../svelte/remove-component-import-keep-named-imports | 11 ++++++++++- .../fixtures/svelte/rename-component-import | 10 ++++++++++ .../skeleton-3/results/svelte/remove-component-import | 9 ++++++++- .../svelte/remove-component-import-keep-default | 10 +++++++++- .../svelte/remove-component-import-keep-named-imports | 11 ++++++++++- .../skeleton-3/results/svelte/rename-component-import | 10 ++++++++++ 8 files changed, 74 insertions(+), 6 deletions(-) diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import index 9694d1a80..c1eeaf49a 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import @@ -3,9 +3,16 @@ + + + + + -
\ No newline at end of file + +
+
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default index d2de522a0..389e10871 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-default @@ -3,10 +3,18 @@ + + + + + + - \ No newline at end of file + +
+
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports index cf445be12..f9323fec8 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/remove-component-import-keep-named-imports @@ -3,11 +3,20 @@ + + + + + + + - \ No newline at end of file +
+ + \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import index e0c0e3a31..e9351bd27 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import @@ -13,13 +13,23 @@ SlideToggle; + + + + + + + + + + diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import index a444a317d..a20465a46 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import @@ -3,9 +3,16 @@ + + + + + - \ No newline at end of file + +
+
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default index 2ef6ed9d3..fa5ba909e 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-default @@ -3,10 +3,18 @@ + + + + + + - \ No newline at end of file + +
+
\ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports index de41d1e32..aa2cd11ad 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/remove-component-import-keep-named-imports @@ -3,11 +3,20 @@ + + + + + + + - \ No newline at end of file +
+ + \ No newline at end of file diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import index 3bf01766c..959d69133 100644 --- a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import +++ b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import @@ -13,13 +13,23 @@ Switch; + + + + + + + + + + From c701549e93d09a8547a496b344e547874bb29c48 Mon Sep 17 00:00:00 2001 From: Hugos68 Date: Wed, 15 Jan 2025 17:47:28 +0100 Subject: [PATCH 26/26] cleanup --- .../transformers/transform-svelte.ts | 22 ++++++++++++++----- .../src/utility/svelte/has-range.ts | 8 +++++++ .../src/utility/svelte/rename-component.ts | 11 +++------- .../utility/svelte/rename-import-specifier.ts | 13 +++++++++++ ...ort => rename-component-import-and-usages} | 0 ...ort => rename-component-import-and-usages} | 0 6 files changed, 40 insertions(+), 14 deletions(-) create mode 100644 packages/skeleton-cli/src/utility/svelte/has-range.ts create mode 100644 packages/skeleton-cli/src/utility/svelte/rename-import-specifier.ts rename packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/{rename-component-import => rename-component-import-and-usages} (100%) rename packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/{rename-component-import => rename-component-import-and-usages} (100%) 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 381a1777d..5899b5d77 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 @@ -5,10 +5,8 @@ import MagicString from 'magic-string'; import { transformClasses } from './transform-classes.js'; import { COMPONENT_MAPPINGS } from '../utility/component-mappings'; import { renameComponent } from '../../../../../utility/svelte/rename-component'; - -function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { - return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; -} +import { hasRange } from '../../../../../utility/svelte/has-range'; +import { renameImportSpecifier } from '../../../../../utility/svelte/rename-import-specifier'; function transformClassLocations(s: MagicString): Visitors { return { @@ -46,6 +44,19 @@ function transformImports(s: MagicString) { } ctx.next(); }, + ImportSpecifier(node, ctx) { + const parent = ctx.path.at(-1); + if ( + parent && + parent.type === 'ImportDeclaration' && + node.imported.type === 'Identifier' && + node.imported.name in COMPONENT_MAPPINGS && + hasRange(node) + ) { + renameImportSpecifier(s, node, parent, COMPONENT_MAPPINGS[node.imported.name]); + } + ctx.next(); + }, Identifier(node, ctx) { if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { s.update(node.start, node.end, COMPONENT_MAPPINGS[node.name]); @@ -54,11 +65,10 @@ function transformImports(s: MagicString) { }, Component(node, ctx) { if (node.name in COMPONENT_MAPPINGS && hasRange(node)) { - renameComponent(s, node); + renameComponent(s, node, COMPONENT_MAPPINGS[node.name]); } ctx.next(); } - // TODO } satisfies Visitors; } diff --git a/packages/skeleton-cli/src/utility/svelte/has-range.ts b/packages/skeleton-cli/src/utility/svelte/has-range.ts new file mode 100644 index 000000000..d3ac77392 --- /dev/null +++ b/packages/skeleton-cli/src/utility/svelte/has-range.ts @@ -0,0 +1,8 @@ +import type { Node } from 'estree'; +import type { AST } from 'svelte/compiler'; + +function hasRange(node: Node | AST.SvelteNode): node is (Node | AST.SvelteNode) & { start: number; end: number } { + return 'start' in node && 'end' in node && typeof node.start === 'number' && typeof node.end === 'number'; +} + +export { hasRange }; diff --git a/packages/skeleton-cli/src/utility/svelte/rename-component.ts b/packages/skeleton-cli/src/utility/svelte/rename-component.ts index 52a738f5c..f07d9de3b 100644 --- a/packages/skeleton-cli/src/utility/svelte/rename-component.ts +++ b/packages/skeleton-cli/src/utility/svelte/rename-component.ts @@ -1,20 +1,15 @@ import MagicString from 'magic-string'; import type { AST } from 'svelte/compiler'; -import { COMPONENT_MAPPINGS } from '../../commands/migrate/migrations/skeleton-3/utility/component-mappings'; -function renameComponent(s: MagicString, node: AST.Component) { +function renameComponent(s: MagicString, node: AST.Component, name: string) { const adjustedStart = node.start + 1; - s.update(adjustedStart, adjustedStart + node.name.length, COMPONENT_MAPPINGS[node.name]); + s.update(adjustedStart, adjustedStart + node.name.length, name); const componentString = s.original.slice(node.start, node.end); const indexOfNonSelfClosingTag = componentString.lastIndexOf(' node.end) { return; } - s.update( - node.start + indexOfNonSelfClosingTag + 2, - node.start + indexOfNonSelfClosingTag + 2 + node.name.length, - COMPONENT_MAPPINGS[node.name] - ); + s.update(node.start + indexOfNonSelfClosingTag + 2, node.start + indexOfNonSelfClosingTag + 2 + node.name.length, name); } export { renameComponent }; diff --git a/packages/skeleton-cli/src/utility/svelte/rename-import-specifier.ts b/packages/skeleton-cli/src/utility/svelte/rename-import-specifier.ts new file mode 100644 index 000000000..04c77cc4e --- /dev/null +++ b/packages/skeleton-cli/src/utility/svelte/rename-import-specifier.ts @@ -0,0 +1,13 @@ +import MagicString from 'magic-string'; +import type { ImportDeclaration, ImportSpecifier } from 'estree'; +import { hasRange } from './has-range'; + +function renameImportSpecifier(s: MagicString, node: ImportSpecifier, parent: ImportDeclaration, name: string) { + if (!(node.imported.type === 'Identifier' && hasRange(node.imported))) { + return; + } + // TODO: Only update when target name isn't already imported + s.update(node.imported.start, node.imported.end, name); +} + +export { renameImportSpecifier }; diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import-and-usages similarity index 100% rename from packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import rename to packages/skeleton-cli/test/migrate/skeleton-3/fixtures/svelte/rename-component-import-and-usages diff --git a/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import b/packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import-and-usages similarity index 100% rename from packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import rename to packages/skeleton-cli/test/migrate/skeleton-3/results/svelte/rename-component-import-and-usages