tw-migrate 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/native.js CHANGED
@@ -1,12 +1,12 @@
1
- import { createRequire } from 'node:module';
1
+ import { createRequire } from "node:module";
2
2
 
3
3
  const require = createRequire(import.meta.url);
4
4
  const targets = {
5
- 'darwin-arm64': 'darwin-arm64',
6
- 'darwin-x64': 'darwin-x64',
7
- 'linux-arm64': 'linux-arm64-gnu',
8
- 'linux-x64': 'linux-x64-gnu',
9
- 'win32-x64': 'win32-x64-msvc',
5
+ "darwin-arm64": "darwin-arm64",
6
+ "darwin-x64": "darwin-x64",
7
+ "linux-arm64": "linux-arm64-gnu",
8
+ "linux-x64": "linux-x64-gnu",
9
+ "win32-x64": "win32-x64-msvc",
10
10
  };
11
11
  const target = targets[`${process.platform}-${process.arch}`];
12
12
 
@@ -21,14 +21,21 @@ for (const load of [
21
21
  binding = load();
22
22
  break;
23
23
  } catch (error) {
24
- if (error.code !== 'MODULE_NOT_FOUND') throw error;
24
+ if (error.code !== "MODULE_NOT_FOUND") throw error;
25
25
  }
26
26
  }
27
27
 
28
28
  if (!binding) {
29
- throw new Error(`No tw-migrate native addon was found for ${target}. Reinstall the package or build it locally.`);
29
+ throw new Error(
30
+ `No tw-migrate native addon was found for ${target}. Reinstall the package or build it locally.`,
31
+ );
30
32
  }
31
33
 
32
- export const decodeSourceMap = binding.decodeSourceMap;
33
- export const planBatchMigration = binding.planBatchMigration;
34
- export const validateCss = binding.validateCss;
34
+ export const {
35
+ decodeSourceMap,
36
+ planBatchMigration,
37
+ staticImportBindings,
38
+ staticImports,
39
+ staticStringExpression,
40
+ validateCss,
41
+ } = binding;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tw-migrate",
3
- "version": "0.1.0",
4
- "description": "Preview and migrate React CSS to Tailwind utilities",
3
+ "version": "0.2.0",
4
+ "description": "Preview and migrate React, Vue, and HTML CSS to Tailwind utilities",
5
5
  "keywords": [
6
6
  "codemod",
7
7
  "css",
@@ -10,7 +10,8 @@
10
10
  "napi-rs",
11
11
  "react",
12
12
  "tailwind",
13
- "tailwindcss"
13
+ "tailwindcss",
14
+ "vue"
14
15
  ],
15
16
  "homepage": "https://github.com/jong-kyung/tw-migrate#readme",
16
17
  "bugs": {
@@ -31,8 +32,8 @@
31
32
  "index.js",
32
33
  "index.d.ts",
33
34
  "native.js",
34
- "rfcs",
35
- "style-compiler.js"
35
+ "style-compiler.js",
36
+ "vue.js"
36
37
  ],
37
38
  "type": "module",
38
39
  "main": "index.js",
@@ -41,7 +42,7 @@
41
42
  "build": "napi build --manifest-path crates/tw_migrate/Cargo.toml --package-json-path package.json --output-dir . --platform --release --no-js --dts binding.d.ts",
42
43
  "build:debug": "napi build --manifest-path crates/tw_migrate/Cargo.toml --package-json-path package.json --output-dir . --platform --no-js --dts binding.d.ts",
43
44
  "artifacts": "napi artifacts --output-dir . --npm-dir npm",
44
- "test": "cargo test && pnpm build:debug && node --test",
45
+ "test": "cargo test && pnpm build:debug && vp test",
45
46
  "test:ecosystem": "node ecosystem-ci/run.ts",
46
47
  "test:rust": "cargo test",
47
48
  "typecheck": "tsc --noEmit",
@@ -64,14 +65,15 @@
64
65
  "verdaccio": "6.8.0",
65
66
  "vite": "catalog:",
66
67
  "vite-plus": "catalog:",
67
- "vitest": "catalog:"
68
+ "vitest": "catalog:",
69
+ "vue": "3.5.40"
68
70
  },
69
71
  "optionalDependencies": {
70
- "tw-migrate-darwin-arm64": "0.1.0",
71
- "tw-migrate-darwin-x64": "0.1.0",
72
- "tw-migrate-linux-arm64-gnu": "0.1.0",
73
- "tw-migrate-linux-x64-gnu": "0.1.0",
74
- "tw-migrate-win32-x64-msvc": "0.1.0"
72
+ "tw-migrate-darwin-arm64": "0.2.0",
73
+ "tw-migrate-darwin-x64": "0.2.0",
74
+ "tw-migrate-linux-arm64-gnu": "0.2.0",
75
+ "tw-migrate-linux-x64-gnu": "0.2.0",
76
+ "tw-migrate-win32-x64-msvc": "0.2.0"
75
77
  },
76
78
  "napi": {
77
79
  "binaryName": "tw-migrate",
package/style-compiler.js CHANGED
@@ -1,22 +1,22 @@
1
- import { realpath } from 'node:fs/promises';
2
- import { createRequire } from 'node:module';
3
- import { basename, dirname, extname, isAbsolute, join, resolve } from 'node:path';
4
- import { fileURLToPath, pathToFileURL } from 'node:url';
1
+ import { realpath } from "node:fs/promises";
2
+ import { createRequire } from "node:module";
3
+ import { basename, dirname, extname, isAbsolute, join, resolve } from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
5
 
6
- import { decodeSourceMap } from './native.js';
6
+ import { decodeSourceMap } from "./native.js";
7
7
 
8
- const SASS_EXTENSIONS = new Set(['.scss', '.sass']);
8
+ const SASS_EXTENSIONS = new Set([".scss", ".sass"]);
9
9
 
10
10
  export function isSassPath(path) {
11
11
  return SASS_EXTENSIONS.has(extname(path));
12
12
  }
13
13
 
14
14
  export function isPreprocessorPath(path) {
15
- return isSassPath(path) || extname(path) === '.less';
15
+ return isSassPath(path) || extname(path) === ".less";
16
16
  }
17
17
 
18
18
  async function loadProjectModule(packageRoot, name, errorMessage) {
19
- const projectRequire = createRequire(join(packageRoot, 'package.json'));
19
+ const projectRequire = createRequire(join(packageRoot, "package.json"));
20
20
  let modulePath;
21
21
  try {
22
22
  modulePath = projectRequire.resolve(name);
@@ -28,34 +28,36 @@ async function loadProjectModule(packageRoot, name, errorMessage) {
28
28
  }
29
29
 
30
30
  export function loadProjectSass(packageRoot) {
31
- return loadProjectModule(packageRoot, 'sass', 'Sass must be installed in the target project.');
31
+ return loadProjectModule(packageRoot, "sass", "Sass must be installed in the target project.");
32
32
  }
33
33
 
34
34
  export function loadProjectLess(packageRoot) {
35
- return loadProjectModule(packageRoot, 'less', 'Less must be installed in the target project.');
35
+ return loadProjectModule(packageRoot, "less", "Less must be installed in the target project.");
36
36
  }
37
37
 
38
- export async function compileSassEntry(sass, entryPath, source) {
38
+ export async function compileSassEntry(sass, entryPath, source, { virtualEntry = false } = {}) {
39
39
  const options = {
40
40
  sourceMap: true,
41
41
  sourceMapIncludeSources: true,
42
42
  };
43
- const result = source === undefined
44
- ? await sass.compileAsync(entryPath, options)
45
- : await sass.compileStringAsync(source, {
46
- ...options,
47
- url: pathToFileURL(entryPath),
48
- syntax: extname(entryPath) === '.sass' ? 'indented' : 'scss',
49
- });
43
+ const result =
44
+ source === undefined
45
+ ? await sass.compileAsync(entryPath, options)
46
+ : await sass.compileStringAsync(source, {
47
+ ...options,
48
+ url: pathToFileURL(entryPath),
49
+ syntax: extname(entryPath) === ".sass" ? "indented" : "scss",
50
+ });
50
51
 
51
52
  if (!result.sourceMap) throw new Error(`Sass did not produce a source map for ${entryPath}`);
52
53
  const loadedPaths = result.loadedUrls
53
- .filter((url) => url.protocol === 'file:')
54
+ .filter((url) => url.protocol === "file:")
54
55
  .map(fileURLToPath);
55
56
  const mappings = sourceMappings(result.sourceMap);
56
57
  const normalizedPaths = await normalizeEntryPaths(
57
58
  [...loadedPaths, ...mappings.map((mapping) => mapping.sourcePath)],
58
59
  entryPath,
60
+ virtualEntry,
59
61
  );
60
62
  return {
61
63
  css: result.css,
@@ -67,16 +69,22 @@ export async function compileSassEntry(sass, entryPath, source) {
67
69
  };
68
70
  }
69
71
 
70
- async function normalizeEntryPaths(paths, entryPath) {
71
- const canonicalEntryPath = await realpath(entryPath);
72
- return new Map(await Promise.all([...new Set(paths)].map(async (path) => {
73
- if (path === entryPath) return [path, path];
74
- try {
75
- return [path, await realpath(path) === canonicalEntryPath ? entryPath : path];
76
- } catch {
77
- return [path, path];
78
- }
79
- })));
72
+ async function normalizeEntryPaths(paths, entryPath, virtualEntry) {
73
+ // A virtual SFC block entry never exists on disk; a real entry that
74
+ // vanished mid-run must keep failing as a source-integrity error.
75
+ const canonicalEntryPath = virtualEntry ? entryPath : await realpath(entryPath);
76
+ return new Map(
77
+ await Promise.all(
78
+ [...new Set(paths)].map(async (path) => {
79
+ if (path === entryPath) return [path, path];
80
+ try {
81
+ return [path, (await realpath(path)) === canonicalEntryPath ? entryPath : path];
82
+ } catch {
83
+ return [path, path];
84
+ }
85
+ }),
86
+ ),
87
+ );
80
88
  }
81
89
 
82
90
  export async function compileLessEntry(less, entryPath, source) {
@@ -85,21 +93,28 @@ export async function compileLessEntry(less, entryPath, source) {
85
93
  sourceMap: {
86
94
  outputSourceFiles: true,
87
95
  sourceMapBasepath: dirname(entryPath),
88
- sourceMapOutputFilename: `${basename(entryPath, '.less')}.css`,
96
+ sourceMapOutputFilename: `${basename(entryPath, ".less")}.css`,
89
97
  },
90
98
  });
91
99
  return {
92
100
  css: result.css,
93
- loadedPaths: result.imports.map((path) => isAbsolute(path) ? path : resolve(dirname(entryPath), path)),
101
+ loadedPaths: result.imports.map((path) =>
102
+ isAbsolute(path) ? path : resolve(dirname(entryPath), path),
103
+ ),
94
104
  sourceMappings: result.map ? sourceMappings(JSON.parse(result.map), dirname(entryPath)) : [],
95
105
  };
96
106
  }
97
107
 
98
108
  export function sourceMappings(sourceMap, sourceBase) {
99
- return JSON.parse(decodeSourceMap(JSON.stringify(sourceMap))).flatMap(({ source, ...mapping }) => {
100
- const sourcePath = sourcePathFromMap(sourceReferenceFromMap(source, sourceMap.sourceRoot), sourceBase);
101
- return sourcePath ? [{ ...mapping, sourcePath }] : [];
102
- });
109
+ return JSON.parse(decodeSourceMap(JSON.stringify(sourceMap))).flatMap(
110
+ ({ source, ...mapping }) => {
111
+ const sourcePath = sourcePathFromMap(
112
+ sourceReferenceFromMap(source, sourceMap.sourceRoot),
113
+ sourceBase,
114
+ );
115
+ return sourcePath ? [{ ...mapping, sourcePath }] : [];
116
+ },
117
+ );
103
118
  }
104
119
 
105
120
  function sourceReferenceFromMap(source, sourceRoot) {
@@ -107,7 +122,7 @@ function sourceReferenceFromMap(source, sourceRoot) {
107
122
  if (isAbsolute(sourceRoot)) return resolve(sourceRoot, source);
108
123
  try {
109
124
  const root = new URL(sourceRoot);
110
- root.pathname = `${root.pathname.replace(/\/+$/, '')}/`;
125
+ root.pathname = `${root.pathname.replace(/\/+$/, "")}/`;
111
126
  return new URL(source, root).href;
112
127
  } catch {
113
128
  return join(sourceRoot, source);
@@ -118,7 +133,7 @@ function sourcePathFromMap(source, sourceBase) {
118
133
  if (isAbsolute(source)) return resolve(source);
119
134
  try {
120
135
  const url = new URL(source);
121
- return url.protocol === 'file:' ? resolve(fileURLToPath(url)) : undefined;
136
+ return url.protocol === "file:" ? resolve(fileURLToPath(url)) : undefined;
122
137
  } catch {
123
138
  return sourceBase ? resolve(sourceBase, source) : undefined;
124
139
  }