@ripast/vue 0.3.0 → 0.5.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/dist/index.d.mts CHANGED
@@ -24,7 +24,7 @@ interface ListComponentsOptions {
24
24
  /** Emit warnings to this sink (default: process.stderr). Pass () => {} to silence. */
25
25
  warn?: (msg: string) => void;
26
26
  }
27
- declare function listComponents(cwd: string, opts?: ListComponentsOptions): VueComponent[];
27
+ export declare function listComponents(cwd: string, opts?: ListComponentsOptions): VueComponent[];
28
28
  interface PropSig {
29
29
  name: string;
30
30
  type?: string;
@@ -40,8 +40,8 @@ interface ParsedComponentShape {
40
40
  setup: boolean;
41
41
  propsResolution: PropsResolution;
42
42
  }
43
- declare function parseComponent(absPath: string): ParsedComponentShape;
44
- declare function parseComponentSource(absPath: string, source: string): ParsedComponentShape;
43
+ export declare function parseComponent(absPath: string): ParsedComponentShape;
44
+ export declare function parseComponentSource(absPath: string, source: string): ParsedComponentShape;
45
45
  type UsageForm = 'tag-pascal' | 'tag-kebab' | 'resolveComponent' | 'dynamic-is-literal' | 'dynamic-is-binding';
46
46
  interface ComponentUsage {
47
47
  name: string;
@@ -57,7 +57,7 @@ interface FindUsagesOptions {
57
57
  cwd?: string;
58
58
  glob?: string | string[];
59
59
  }
60
- declare function findComponentUsages(names: string[], opts?: FindUsagesOptions): ComponentUsage[];
61
- declare function findComponentUsage(name: string, opts?: FindUsagesOptions): ComponentUsage[];
60
+ export declare function findComponentUsages(names: string[], opts?: FindUsagesOptions): ComponentUsage[];
61
+ export declare function findComponentUsage(name: string, opts?: FindUsagesOptions): ComponentUsage[];
62
62
  declare const adapter: FrameworkAdapter;
63
- export { type ComponentKind, type ComponentUsage, type ListComponentsOptions, type ParsedComponentShape, type PropSig, type UsageForm, type VueComponent, adapter as default, findComponentUsage, findComponentUsages, listComponents, parseComponent, parseComponentSource };
63
+ export { type ComponentKind, type ComponentUsage, type ListComponentsOptions, type ParsedComponentShape, type PropSig, type UsageForm, type VueComponent, adapter as default };
package/dist/index.mjs CHANGED
@@ -3,14 +3,13 @@ import { basename, dirname, join, relative, resolve } from "node:path";
3
3
  import { extractTemplateExpressions, hyphenateVueName, isInsideAutoImportScope, parseSourceFile, parseVueTemplateAst, posToLineCol, rewriteTemplateReferences, rgFiles, rgFilesMany, scan } from "@ripast/core/adapter";
4
4
  import { URI } from "vscode-uri";
5
5
  import process from "node:process";
6
+ import ts from "@typescript/typescript6";
6
7
  import { FileType, createLanguage, createLanguageService, createUriMap } from "@volar/language-service";
7
8
  import { createLanguageServiceHost, resolveFileLanguageId } from "@volar/typescript";
8
9
  import { createParsedCommandLine, createVueLanguagePlugin, getAllExtensions } from "@vue/language-core";
9
10
  import { createVueLanguageServicePlugins } from "@vue/language-service";
10
- import ts from "typescript";
11
11
  import { create } from "volar-service-typescript";
12
12
  import { TextDocument } from "vscode-languageserver-textdocument";
13
- import { spawnSync } from "node:child_process";
14
13
  function stringifyArg(arg) {
15
14
  if (arg instanceof Error) return arg.message;
16
15
  if (typeof arg === "string") return arg;
@@ -149,7 +148,8 @@ function createVueServiceInternal(tsconfigPath, cwd) {
149
148
  },
150
149
  ...createLanguageServiceHost(ts, ts.sys, language, fileToUri, projectHost)
151
150
  } };
152
- const service = createLanguageService(language, [...create(ts), ...createVueLanguageServicePlugins(ts)], env, project);
151
+ const plugins = [...create(ts), ...createVueLanguageServicePlugins(ts)];
152
+ const service = createLanguageService(language, plugins, env, project);
153
153
  return {
154
154
  service,
155
155
  fileToUri,
@@ -201,27 +201,17 @@ function hasVueFilesContaining(cwd, pattern) {
201
201
  return listVueFilesContaining(cwd, pattern).length > 0;
202
202
  }
203
203
  function listVueFiles(cwd) {
204
- return rgVueFiles(cwd, ["--files"]);
204
+ return rgFiles("", {
205
+ cwd,
206
+ glob: "*.vue",
207
+ listAll: true
208
+ });
205
209
  }
206
210
  function listVueFilesContaining(cwd, pattern) {
207
- return rgVueFiles(cwd, [
208
- "--files-with-matches",
209
- "--fixed-strings",
210
- pattern
211
- ]);
212
- }
213
- function rgVueFiles(cwd, args) {
214
- return spawnSync("rg", [
215
- ...args,
216
- "--hidden",
217
- "--no-messages",
218
- "-g",
219
- "*.vue",
220
- "."
221
- ], {
211
+ return rgFiles(pattern, {
222
212
  cwd,
223
- encoding: "utf8"
224
- }).stdout.split("\n").filter(Boolean).map((path) => resolve(cwd, path));
213
+ glob: "*.vue"
214
+ });
225
215
  }
226
216
  async function applyVueRename(tsconfigPath, cwd, from, to, sites) {
227
217
  const vue = createVueService(tsconfigPath, cwd);
@@ -300,7 +290,7 @@ async function vueRegressions(tsconfigPath, cwd, pendingChanges) {
300
290
  const baselinePairs = await withFilteredConsoleWarn(() => Promise.all(vueFiles.map(async (file) => [file, await collectDiagKeys(vue, file)])));
301
291
  const baseline = new Map(baselinePairs);
302
292
  for (const c of pendingChanges) vue.setSnapshot(c.path, c.after);
303
- const checkSet = [...new Set([...vueFiles, ...pendingChanges.filter((c) => c.path.endsWith(".vue")).map((c) => c.path)])];
293
+ const checkSet = [.../* @__PURE__ */ new Set([...vueFiles, ...pendingChanges.filter((c) => c.path.endsWith(".vue")).map((c) => c.path)])];
304
294
  const postPairs = await withFilteredConsoleWarn(() => Promise.all(checkSet.map(async (file) => [file, await getDiags(vue, file)])));
305
295
  const out = [];
306
296
  for (const [file, post] of postPairs) {
@@ -734,7 +724,8 @@ function collectFromSfc(abs, source, cwd, alias, out) {
734
724
  if (node.type !== NODE_ELEMENT$1) return;
735
725
  const canonical = alias.byTag.get(node.tag);
736
726
  if (canonical) {
737
- const { line, col } = posToLineCol(source, node.loc.start.offset + 1);
727
+ const offset = node.loc.start.offset + 1;
728
+ const { line, col } = posToLineCol(source, offset);
738
729
  out.push({
739
730
  name: canonical,
740
731
  file: abs,
@@ -821,7 +812,8 @@ function collectFromScript(abs, source, cwd, alias, out) {
821
812
  const arg = node.arguments?.[0];
822
813
  if (arg?.type !== "Literal" || typeof arg.value !== "string") return;
823
814
  if (!alias.byString.has(arg.value)) return;
824
- const { line, col } = posToLineCol(source, (arg.start ?? 0) + scriptOffset);
815
+ const offset = (arg.start ?? 0) + scriptOffset;
816
+ const { line, col } = posToLineCol(source, offset);
825
817
  out.push({
826
818
  name: arg.value,
827
819
  file: abs,
@@ -1010,7 +1002,7 @@ function stripModuleExt(path) {
1010
1002
  }
1011
1003
  const MANIFEST_PATH = ".nuxt/components.d.ts";
1012
1004
  const MANIFEST_ENTRY_RE = /^\s*(?:export\s+const\s+)?([A-Z]\w*)\s*:\s*(?:LazyComponent<\s*)?typeof\s+import\(\s*["']([^"']+)["']\s*\)\s*\[\s*["']default["']\s*\]/gm;
1013
- const COMPONENT_DIR_NAMES = new Set(["components"]);
1005
+ const COMPONENT_DIR_NAMES = /* @__PURE__ */ new Set(["components"]);
1014
1006
  const DEFAULT_VUE_GLOB = ["*.vue"];
1015
1007
  function listComponents(cwd, opts = {}) {
1016
1008
  const source = opts.source ?? "auto";
@@ -1392,7 +1384,7 @@ const doctor = {
1392
1384
  return out;
1393
1385
  }
1394
1386
  };
1395
- const VUE_BUILTINS = new Set([
1387
+ const VUE_BUILTINS = /* @__PURE__ */ new Set([
1396
1388
  "Transition",
1397
1389
  "TransitionGroup",
1398
1390
  "KeepAlive",
@@ -1403,7 +1395,7 @@ const VUE_BUILTINS = new Set([
1403
1395
  "Template",
1404
1396
  "ClientOnly"
1405
1397
  ]);
1406
- const NUXT_BUILTINS = new Set([
1398
+ const NUXT_BUILTINS = /* @__PURE__ */ new Set([
1407
1399
  "NuxtPage",
1408
1400
  "NuxtLink",
1409
1401
  "NuxtLayout",
@@ -1432,26 +1424,59 @@ const NUXT_BUILTINS = new Set([
1432
1424
  ]);
1433
1425
  const PASCAL = /^[A-Z][A-Z0-9a-z]*$/;
1434
1426
  const NODE_ELEMENT = 1;
1435
- function extractTemplateBlock(source) {
1436
- const openStart = source.indexOf("<template");
1437
- if (openStart === -1) return void 0;
1438
- const contentStart = source.indexOf(">", openStart);
1439
- if (contentStart === -1) return void 0;
1440
- const start = contentStart + 1;
1441
- const end = source.indexOf("</template>", start);
1442
- if (end === -1) return void 0;
1443
- return {
1444
- content: source.slice(start, end),
1445
- start
1446
- };
1427
+ function listAppRoots(cwd) {
1428
+ const roots = [];
1429
+ const parent = join(cwd, "apps");
1430
+ if (!existsSync(parent)) return roots;
1431
+ for (const name of readdirSync(parent)) {
1432
+ const abs = join(parent, name);
1433
+ try {
1434
+ if (statSync(abs).isDirectory() && existsSync(join(abs, ".nuxt", "components.d.ts"))) roots.push(abs);
1435
+ } catch {}
1436
+ }
1437
+ return roots;
1447
1438
  }
1448
- function findPhantomComponents(cwd) {
1449
- const files = rgFilesMany(["*.vue"], { cwd });
1450
- const known = new Set([...VUE_BUILTINS, ...NUXT_BUILTINS]);
1451
- for (const c of listComponents(cwd, { source: "auto" })) {
1439
+ function scopeForFile(abs, roots, cwd) {
1440
+ let best = cwd;
1441
+ let bestLen = -1;
1442
+ for (const root of roots) if ((abs === root || abs.startsWith(`${root}/`)) && root.length > bestLen) {
1443
+ best = root;
1444
+ bestLen = root.length;
1445
+ }
1446
+ return best;
1447
+ }
1448
+ function buildKnownSet(root) {
1449
+ const known = /* @__PURE__ */ new Set([...VUE_BUILTINS, ...NUXT_BUILTINS]);
1450
+ for (const c of listComponents(root, {
1451
+ source: "auto",
1452
+ warn: () => {}
1453
+ })) {
1454
+ known.add(c.name);
1455
+ for (const alias of c.aliases ?? []) known.add(alias);
1456
+ }
1457
+ return known;
1458
+ }
1459
+ function buildUnionKnownSet(roots, cwd) {
1460
+ const known = /* @__PURE__ */ new Set([...VUE_BUILTINS, ...NUXT_BUILTINS]);
1461
+ const sources = roots.length ? roots : [cwd];
1462
+ for (const root of sources) for (const c of listComponents(root, {
1463
+ source: "auto",
1464
+ warn: () => {}
1465
+ })) {
1452
1466
  known.add(c.name);
1453
1467
  for (const alias of c.aliases ?? []) known.add(alias);
1454
1468
  }
1469
+ return known;
1470
+ }
1471
+ function findPhantomComponents(cwd) {
1472
+ const files = rgFiles("", {
1473
+ cwd,
1474
+ glob: ["*.vue"],
1475
+ listAll: true
1476
+ });
1477
+ const appRoots = listAppRoots(cwd);
1478
+ const knownByRoot = /* @__PURE__ */ new Map();
1479
+ if (appRoots.length) knownByRoot.set(cwd, buildUnionKnownSet(appRoots, cwd));
1455
1480
  const out = [];
1456
1481
  for (const abs of files) {
1457
1482
  let source;
@@ -1460,11 +1485,14 @@ function findPhantomComponents(cwd) {
1460
1485
  } catch {
1461
1486
  continue;
1462
1487
  }
1463
- const template = extractTemplateBlock(source);
1464
- if (!template) continue;
1465
- const templateStart = template.start;
1466
- const ast = parseVueTemplateAst(template.content);
1488
+ const ast = parseVueTemplateAst(source);
1467
1489
  if (!ast) continue;
1490
+ const root = scopeForFile(abs, appRoots, cwd);
1491
+ let known = knownByRoot.get(root);
1492
+ if (!known) {
1493
+ known = buildKnownSet(root);
1494
+ knownByRoot.set(root, known);
1495
+ }
1468
1496
  const localImports = collectLocalImports(source);
1469
1497
  const seen = /* @__PURE__ */ new Set();
1470
1498
  walkTpl(ast, (node) => {
@@ -1477,7 +1505,7 @@ function findPhantomComponents(cwd) {
1477
1505
  const key = `${abs}::${tag}::${node.loc?.start?.offset ?? 0}`;
1478
1506
  if (seen.has(key)) return;
1479
1507
  seen.add(key);
1480
- const offset = templateStart + (node.loc?.start?.offset ?? 0);
1508
+ const offset = node.loc?.start?.offset ?? 0;
1481
1509
  const { line, col } = posToLineCol(source, offset);
1482
1510
  out.push({
1483
1511
  check: "phantom-component",
@@ -1486,7 +1514,8 @@ function findPhantomComponents(cwd) {
1486
1514
  message: `<${tag}> is not a known component (auto-import scope, local import, or built-in)`,
1487
1515
  detail: {
1488
1516
  name: tag,
1489
- col
1517
+ col,
1518
+ scope: relative(cwd, root) || "."
1490
1519
  }
1491
1520
  });
1492
1521
  });
@@ -1627,7 +1656,8 @@ function findStaleNuxtConfigRefs(cwd) {
1627
1656
  if (importsMatch) for (const lit of importsMatch[1].matchAll(/['"`]([^'"`]+)['"`]/g)) {
1628
1657
  const value = lit[1];
1629
1658
  if (!value.startsWith(".") && !value.startsWith("/")) continue;
1630
- if (existsSync(resolve(root, value.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, "")))) continue;
1659
+ const dirPath = resolve(root, value.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, ""));
1660
+ if (existsSync(dirPath)) continue;
1631
1661
  out.push({
1632
1662
  check: "stale-nuxt-config-ref",
1633
1663
  file: rel,
@@ -1642,7 +1672,8 @@ function findStaleNuxtConfigRefs(cwd) {
1642
1672
  for (const m of source.matchAll(COMPONENT_PATH_RE)) {
1643
1673
  const value = m[1];
1644
1674
  if (!value.startsWith(".") && !value.startsWith("/")) continue;
1645
- if (existsSync(resolve(root, value.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, "")))) continue;
1675
+ const dirPath = resolve(root, value.replace(/\/\*\*.*$/, "").replace(/\/\*.*$/, ""));
1676
+ if (existsSync(dirPath)) continue;
1646
1677
  out.push({
1647
1678
  check: "stale-nuxt-config-ref",
1648
1679
  file: rel,
@@ -1835,7 +1866,7 @@ function rewriteResolveComponentSites(cwd, oldName, newName, changes, oldAbs, ne
1835
1866
  return out;
1836
1867
  }
1837
1868
  function addExplicitComponentImports(cwd, oldName, newName, newAbs, changes, oldAbs) {
1838
- const tokens = new Set([
1869
+ const tokens = /* @__PURE__ */ new Set([
1839
1870
  oldName,
1840
1871
  newName,
1841
1872
  hyphenateVueName(oldName),
@@ -1874,7 +1905,7 @@ function escapeRe(s) {
1874
1905
  function rewriteIsAttributeSites(cwd, oldName, newName, changes, oldAbs, newAbs, warnings) {
1875
1906
  const oldKebab = hyphenateVueName(oldName);
1876
1907
  const newKebab = hyphenateVueName(newName);
1877
- const candidates = new Set([...rgFiles(oldName, {
1908
+ const candidates = /* @__PURE__ */ new Set([...rgFiles(oldName, {
1878
1909
  cwd,
1879
1910
  glob: "*.vue"
1880
1911
  }), ...rgFiles(oldKebab, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ripast/vue",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.5.0",
5
5
  "description": "Vue (and Nuxt) framework adapter for ripast. Provides Volar/Vue Language Service-backed rename, move, and template rewriting for .vue SFCs.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",
@@ -28,34 +28,34 @@
28
28
  ],
29
29
  "exports": {
30
30
  ".": {
31
- "types": "./dist/index.d.ts",
31
+ "types": "./dist/index.d.mts",
32
32
  "import": "./dist/index.mjs"
33
33
  }
34
34
  },
35
35
  "main": "./dist/index.mjs",
36
- "types": "./dist/index.d.ts",
36
+ "types": "./dist/index.d.mts",
37
37
  "files": [
38
38
  "dist"
39
39
  ],
40
40
  "engines": {
41
- "node": ">=20.11"
41
+ "node": ">=22.13"
42
42
  },
43
43
  "peerDependencies": {
44
- "typescript": ">=5.4",
45
- "@ripast/core": "0.3.0"
44
+ "@ripast/core": "0.5.0"
46
45
  },
47
46
  "dependencies": {
47
+ "@typescript/typescript6": "^6.0.2",
48
48
  "@volar/language-service": "^2.4.28",
49
49
  "@volar/typescript": "^2.4.28",
50
- "@vue/language-core": "^3.2.8",
51
- "@vue/language-service": "^3.2.8",
50
+ "@vue/language-core": "^3.3.12",
51
+ "@vue/language-service": "^3.3.12",
52
52
  "volar-service-typescript": "^0.0.71",
53
- "vscode-languageserver-protocol": "3.17.5",
54
- "vscode-languageserver-textdocument": "^1.0.12",
55
- "vscode-uri": "^3.1.0"
53
+ "vscode-languageserver-protocol": "3.18.4",
54
+ "vscode-languageserver-textdocument": "^1.0.15",
55
+ "vscode-uri": "^3.2.0"
56
56
  },
57
57
  "devDependencies": {
58
- "@ripast/core": "0.3.0"
58
+ "@ripast/core": "0.5.0"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "obuild",