Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: CLI Improvements 3 #3107

Merged
merged 27 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
059d3d2
Removed unused imports after transformation
Hugos68 Jan 13, 2025
4c69093
Merge branch 'skeletonlabs:next' into next
Hugos68 Jan 13, 2025
6e202f5
Feature: class: attributes will also be transformed when they're not …
Hugos68 Jan 13, 2025
dc6ba34
Bugfix: transformations on the package.json now preserve the original…
Hugos68 Jan 13, 2025
844ef63
fix changeset
Hugos68 Jan 13, 2025
023081d
Feature: `app.html` is now transformed.
Hugos68 Jan 14, 2025
7e29a8c
Transform classes is now compliant with other transformers
Hugos68 Jan 14, 2025
e0950e8
Feature: `<packagemanager> install` is now ran at the end of the migr…
Hugos68 Jan 14, 2025
5991867
Fixed bug where class: directives that were referencing regular ident…
Hugos68 Jan 14, 2025
8f4ed9c
Replaced `estree-walker` with `zimmerframe` due to more readable code.
Hugos68 Jan 14, 2025
cef4705
Add additional test cases for all preset themes for the app tests.
Hugos68 Jan 14, 2025
0321557
Tailwind transforms are much more correct now.
Hugos68 Jan 14, 2025
8b4aa60
Tailwind transforms are much more correct now, as well as being teste…
Hugos68 Jan 14, 2025
eb739aa
format
Hugos68 Jan 14, 2025
4976bdc
cleanup, added component mappings
Hugos68 Jan 14, 2025
3b3baeb
Feature: Rename all components imports and usages.
Hugos68 Jan 14, 2025
86969ce
Feature: Removed components have their imports removed.
Hugos68 Jan 14, 2025
f91af07
Moving to fixtures, much easier to add test cases, although less dynamic
Hugos68 Jan 15, 2025
0e3d28f
Fix tab?
Hugos68 Jan 15, 2025
70604cc
Add tests
Hugos68 Jan 15, 2025
734ec0d
Move testing to fixtures
Hugos68 Jan 15, 2025
6a5c22f
cleanup
Hugos68 Jan 15, 2025
63c1db7
Stuff
Hugos68 Jan 15, 2025
6ae2c8f
Removed import handling from svelte, broken currently
Hugos68 Jan 15, 2025
a11c2d8
Renaming components, double import needs to be fixed
Hugos68 Jan 15, 2025
f2b20c0
Improve component test cases to contain both self closing and "normal…
Hugos68 Jan 15, 2025
c701549
cleanup
Hugos68 Jan 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/afraid-geckos-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: The `class:` directive will also be transformed when they're not also an identifier.
5 changes: 5 additions & 0 deletions .changeset/big-radios-pretend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Bugfix: transformations on the package.json now preserve the original indentation.
5 changes: 5 additions & 0 deletions .changeset/chilly-news-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: `app.html` is now transformed.
5 changes: 5 additions & 0 deletions .changeset/early-suns-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: Better error handling is now in place.
5 changes: 5 additions & 0 deletions .changeset/itchy-knives-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: `<packagemanager> install` is now ran at the end of the migration.
5 changes: 5 additions & 0 deletions .changeset/modern-pianos-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: Rename all components imports and usages.
5 changes: 5 additions & 0 deletions .changeset/wicked-maps-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@skeletonlabs/skeleton-cli': patch
---

Feature: Removed components have their imports removed.
11 changes: 7 additions & 4 deletions packages/skeleton-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
"bin": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist",
"!**/*.test.*"
"dist"
],
"scripts": {
"package": "unbuild",
Expand All @@ -27,6 +26,8 @@
"test:watch": "vitest watch"
},
"devDependencies": {
"@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",
Expand All @@ -39,13 +40,15 @@
"@clack/prompts": "^0.7.0",
"colorette": "^2.0.20",
"commander": "^13.0.0",
"estree-walker": "^3.0.3",
"detect-indent": "^7.0.1",
"esrap": "^1.4.3",
"fast-glob": "^3.3.1",
"latest-version": "^9.0.0",
"magic-string": "^0.30.17",
"package-manager-detector": "^0.2.8",
"semver": "^7.6.3",
"svelte": "^5.17.3",
"ts-morph": "^25.0.0"
"ts-morph": "^25.0.0",
"zimmerframe": "^1.1.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ 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 { 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';
import { FALLBACK_THEME } from './utility/constants';
import getLatestVersion from 'latest-version';

export default async function (options: MigrateOptions) {
const cwd = options.cwd ?? process.cwd();
Expand All @@ -19,8 +24,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}".`);
}
Expand All @@ -29,42 +38,109 @@ 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 })),
initialValues: availableSourceFolders
});

if (isCancel(sourceFolders)) {
cli.error('Migration cancelled.');
cli.error('Migration cancelled by user.');
return;
}

const packageSpinner = spinner();
packageSpinner.start(`Migrating ${pkg.matcher}...`);
await transformPackage(pkg.paths[0]);
packageSpinner.stop(`Successfully migrated ${pkg.matcher}`);
try {
const pkgCode = await readFile(pkg.paths[0], 'utf-8');
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) {
if (e instanceof Error) {
packageSpinner.stop(`Failed to migrate ${pkg.matcher}: ${e.message}`);
}
packageSpinner.stop(`Failed to migrate ${pkg.matcher}`);
}

const tailwindConfigSpinner = spinner();
tailwindConfigSpinner.start(`Migrating ${tailwindConfig.matcher}...`);
await transformTailwindConfig(tailwindConfig.paths[0]);
tailwindConfigSpinner.stop(`Successfully migrated ${tailwindConfig.matcher}`);
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);
theme = transformedTailwind.meta.themes.preset.at(0) ?? 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}...`);
try {
const appCode = await readFile(app.paths[0], 'utf-8');
const transformedApp = transformApp(appCode, theme ?? FALLBACK_THEME);
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') {
await transformSvelte(sourceFile);
} else {
await transformModule(sourceFile);
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');
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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 AST.SvelteNode,
{},
{
RegularElement(node, ctx) {
if (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 + '<body'.length, ` ${newDataThemeAttribute}`);
}
}
ctx.next();
}
}
);
return {
code: s.toString()
};
}

export { transformApp };
Original file line number Diff line number Diff line change
Expand Up @@ -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 };

This file was deleted.

Loading
Loading