@component-compass/parser-vue 0.1.0 → 0.1.1

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.
@@ -0,0 +1,41 @@
1
+ import type { ResolveLazyManifest } from "@component-compass/plugin-core";
2
+ import type { FileBuilder } from "@component-compass/reference-graph";
3
+ import type { VueParseWrapper } from "./parse-sfc.js";
4
+ /**
5
+ * Options threaded into the parse5-based Vue SFC emitter. Mirrors the legacy
6
+ * `walkVueTemplate` surface but consumes the reference-graph FileBuilder
7
+ * instead of producing `Occurrence[]` directly. Tasks 2.4 → 2.12 progressively
8
+ * fill in script-import emission, template walking, owner attribution, and
9
+ * prop extraction.
10
+ */
11
+ export type EmitVueTemplateOpts = {
12
+ file: string;
13
+ source: string;
14
+ wrapper: VueParseWrapper;
15
+ fileBuilder: FileBuilder;
16
+ captureValues: boolean;
17
+ /**
18
+ * Optional lazy-manifest priming hook. Vue SFCs commonly side-effect-import
19
+ * a WC's register entrypoint (`import "@pkg/components/button"`) so its
20
+ * template tag references (`<pie-button>`) can be resolved later. Calling
21
+ * `resolveLazyManifest` for each side-effect source primes the engine's
22
+ * tagIndex / CEM lookup pipeline. Optional — when undefined the priming
23
+ * loop is skipped (acceptable for synthetic test fixtures).
24
+ */
25
+ resolveLazyManifest?: ResolveLazyManifest;
26
+ /**
27
+ * Optional pre-resolved SFC component symbol. When omitted, emit-template
28
+ * falls back to the filename stem (e.g. `button` for `button.vue`). The CLI
29
+ * passes the symbol resolved by `detectVueComponents` (which inspects
30
+ * `defineOptions` and falls back to a PascalCase filename) so the SFC's
31
+ * seed id and the engine's owner ComponentId hash to the same value. A
32
+ * mismatch here causes the SFC seed to be pruned as an unreachable local.
33
+ */
34
+ sfcSymbol?: string;
35
+ };
36
+ /**
37
+ * parse5-based emitter for Vue SFC templates. REPLACES the legacy
38
+ * `walkVueTemplate` pathway once Task 2.13 wires it into scan.ts. Until then
39
+ * the two coexist — the emitter is only driven by its unit tests.
40
+ */
41
+ export declare function emitVueTemplate(opts: EmitVueTemplateOpts): void;
@@ -0,0 +1,178 @@
1
+ import { basename, extname } from "node:path";
2
+ import { parseFragment } from "parse5";
3
+ import { isElement, hasChildren } from "@component-compass/ast-utils";
4
+ import { MODULE_SCOPE } from "@component-compass/reference-graph";
5
+ import { partsFromWrapper } from "./parse-sfc.js";
6
+ import { readAttrs } from "./read-attrs.js";
7
+ import { extractScriptImports } from "./script-imports.js";
8
+ /**
9
+ * Vue tag-form enumeration. A script-bound import resolves both via its
10
+ * lowercased exact form (`Card` → `card`) and its PascalCase→kebab form
11
+ * (`VBtn` → `v-btn`). Pre-computed once per import; ported from src/index.ts.
12
+ */
13
+ function vueTagForms(importName) {
14
+ const lowercased = importName.toLowerCase();
15
+ const kebab = importName
16
+ .replace(/([A-Za-z0-9])([A-Z])/g, "$1-$2")
17
+ .toLowerCase();
18
+ return Array.from(new Set([lowercased, kebab]));
19
+ }
20
+ /**
21
+ * parse5-based emitter for Vue SFC templates. REPLACES the legacy
22
+ * `walkVueTemplate` pathway once Task 2.13 wires it into scan.ts. Until then
23
+ * the two coexist — the emitter is only driven by its unit tests.
24
+ */
25
+ export function emitVueTemplate(opts) {
26
+ const parts = partsFromWrapper(opts.wrapper);
27
+ // SFC's default export is the component itself. Stamp it as a JSX-returning
28
+ // BindingDecl + a default ExportRecord so the engine can resolve template
29
+ // usages back to this SFC as their owner (Task 2.9). Prefer the caller's
30
+ // pre-resolved symbol (which uses defineOptions / PascalCase filename for
31
+ // hash parity with `detectVueComponents`); fall back to the raw filename
32
+ // stem only when the caller didn't supply one (synthetic test fixtures).
33
+ const sfcSymbol = opts.sfcSymbol ?? basename(opts.file, extname(opts.file));
34
+ opts.fileBuilder.addDeclaration({
35
+ symbol: sfcSymbol,
36
+ value: { kind: "Function", returns: [{ kind: "JSX" }] },
37
+ loc: { line: 1, column: 1 },
38
+ isExported: true,
39
+ });
40
+ opts.fileBuilder.addExport({ kind: "default", local: sfcSymbol });
41
+ // Script imports flow through to `fileBuilder.addImport` regardless of
42
+ // whether the template emits anything — downstream engine passes look up
43
+ // imports by local name to resolve template tag references.
44
+ let importSpecs = [];
45
+ let sideEffectSources = [];
46
+ if (parts.scriptSource && opts.wrapper.scriptProgram) {
47
+ const scriptResult = extractScriptImports({
48
+ file: opts.file,
49
+ program: opts.wrapper.scriptProgram,
50
+ });
51
+ importSpecs = scriptResult.importSpecs;
52
+ sideEffectSources = scriptResult.sideEffectSources;
53
+ for (const spec of importSpecs) {
54
+ opts.fileBuilder.addImport({
55
+ specifier: spec.source,
56
+ imported: spec.imported,
57
+ local: spec.local,
58
+ // Per-import loc not tracked yet — script-imports.ts only records
59
+ // local + imported + source. Stamping a placeholder until either the
60
+ // extractor surfaces real positions or downstream consumers prove a
61
+ // need for them.
62
+ loc: { line: 1, column: 1 },
63
+ });
64
+ }
65
+ }
66
+ // Side-effect imports (`import "pkg"`) carry no binding but signal that the
67
+ // SFC depends on the package's runtime; prime the lazy resolver so template
68
+ // tag references (`<pie-button>`) can find the leaf's CEM later. Mirrors
69
+ // the legacy walkVueTemplate priming step from src/index.ts.
70
+ if (opts.resolveLazyManifest) {
71
+ for (const source of sideEffectSources) {
72
+ opts.resolveLazyManifest(opts.file, source, "");
73
+ }
74
+ }
75
+ if (!parts.templateSource)
76
+ return;
77
+ // SFC owner Reference. Every template-emitted usage attributes back to the
78
+ // SFC's own BindingDecl (declared above). Module-scope, no member chain.
79
+ // `originFile` is required by `resolveOwnerChain` to look up the owner's
80
+ // declaration — without it the engine emits the occurrence with no
81
+ // ownerComponentId and the SFC seed gets filtered as an unreachable local.
82
+ const sfcOwnerRef = {
83
+ symbol: sfcSymbol,
84
+ scope: MODULE_SCOPE,
85
+ memberChain: [],
86
+ loc: { line: 1, column: 1 },
87
+ originFile: opts.file,
88
+ };
89
+ // parse5 line numbers are 1-based against the template content itself.
90
+ // SFC templates start mid-file, so add the line count of everything before
91
+ // `templateOffset` (minus the trailing 1 the count gives for the line the
92
+ // template opens on) so emitted locs read against the full SFC.
93
+ const lineOffset = opts.source.slice(0, parts.templateOffset ?? 0).split("\n").length - 1;
94
+ // Map of template tag form → ImportSpec. Vue addresses script-bound
95
+ // components either by the lowercased import name (`Card` → `card`) or by
96
+ // the PascalCase→kebab conversion (`VBtn` → `v-btn`). Pre-compute both forms
97
+ // here so the recursive walk can do a single Map lookup per element, and
98
+ // store the full spec so owner attribution can stamp specifier + import on
99
+ // the viaOverride.
100
+ const scriptBindings = new Map();
101
+ for (const spec of importSpecs) {
102
+ for (const form of vueTagForms(spec.local)) {
103
+ scriptBindings.set(form, spec);
104
+ }
105
+ }
106
+ const doc = parseFragment(parts.templateSource, { sourceCodeLocationInfo: true });
107
+ function visit(node) {
108
+ let pushed = false;
109
+ if (isElement(node)) {
110
+ const rawTag = node.tagName;
111
+ const scriptSpec = scriptBindings.get(rawTag);
112
+ if (scriptSpec) {
113
+ const loc = node.sourceCodeLocation;
114
+ const line = (loc?.startLine ?? 1) + lineOffset;
115
+ const column = loc?.startCol ?? 1;
116
+ // events not yet wired — see #57 (consumer-side event-listener tracking)
117
+ const { props } = readAttrs(node, opts.captureValues);
118
+ opts.fileBuilder.addJsxUsage({
119
+ ref: {
120
+ symbol: scriptSpec.local,
121
+ scope: MODULE_SCOPE,
122
+ memberChain: [],
123
+ loc: { line, column },
124
+ },
125
+ loc: { line, column },
126
+ props,
127
+ });
128
+ // Owner is always the enclosing SFC; viaOverride carries the
129
+ // script-import specifier + name so downstream consumers can present
130
+ // the usage as a vue-template occurrence with the import provenance
131
+ // intact.
132
+ opts.fileBuilder.setOwner(sfcOwnerRef, {
133
+ kind: "vue-template",
134
+ specifier: scriptSpec.source,
135
+ import: scriptSpec.imported,
136
+ });
137
+ pushed = true;
138
+ }
139
+ else if (rawTag.includes("-")) {
140
+ // Hyphenated tag with no script binding. Vue's auto-import / runtime
141
+ // global-component convention (e.g. `<pie-button>`, Vuetify's `<v-list>`
142
+ // when registered globally). Engine maps these to custom-element or
143
+ // vue-component identity by tag-name lookup in the tagIndex.
144
+ const loc = node.sourceCodeLocation;
145
+ const line = (loc?.startLine ?? 1) + lineOffset;
146
+ const column = loc?.startCol ?? 1;
147
+ // events not yet wired — see #57 (consumer-side event-listener tracking)
148
+ const { props } = readAttrs(node, opts.captureValues);
149
+ opts.fileBuilder.addTagUsage({
150
+ tagName: rawTag,
151
+ loc: { line, column },
152
+ props,
153
+ });
154
+ // Owner is the enclosing SFC; no viaOverride — engine defaults the
155
+ // occurrence's `via` to `{ kind: "html-tag" }` for TagUsage.
156
+ opts.fileBuilder.setTagOwner(sfcOwnerRef);
157
+ pushed = true;
158
+ }
159
+ // Plain HTML (`<div>`, `<span>`) and unknown PascalCase tags fall
160
+ // through without emission — they're neither tracked components nor
161
+ // hyphenated custom elements.
162
+ }
163
+ // Tracked elements push themselves as the lexical parent for their
164
+ // children; non-tracked elements (plain HTML, untracked tags) skip the
165
+ // push so descendants attribute to the next tracked ancestor
166
+ // (parent-transparency rule).
167
+ if (pushed)
168
+ opts.fileBuilder.pushUsageScope();
169
+ if (isElement(node) || hasChildren(node)) {
170
+ for (const child of node.childNodes)
171
+ visit(child);
172
+ }
173
+ if (pushed)
174
+ opts.fileBuilder.popUsageScope();
175
+ }
176
+ visit(doc);
177
+ }
178
+ //# sourceMappingURL=emit-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit-template.js","sourceRoot":"","sources":["../src/emit-template.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import type { ParserPlugin } from "@component-compass/plugin-core";
2
- export declare const vuePlugin: ParserPlugin;
1
+ export { emitVueTemplate } from "./emit-template.js";
2
+ export type { EmitVueTemplateOpts } from "./emit-template.js";
package/dist/index.js CHANGED
@@ -1,164 +1,2 @@
1
- import { basename, extname } from "node:path";
2
- import { serialiseComponentId } from "@component-compass/plugin-core";
3
- import { asWrapperId } from "@component-compass/plugin-core";
4
- import { posixPath } from "@component-compass/ast-utils";
5
- import { partsFromWrapper } from "./parse-sfc.js";
6
- import { walkVueTemplate } from "./walk-template.js";
7
- import { resolveSfcOwner } from "./owner.js";
8
- import { extractScriptImports } from "./script-imports.js";
9
- function wrapperIdFromName(name) {
10
- const kebab = name.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
11
- return asWrapperId(`wrap-${kebab.replaceAll(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "")}`);
12
- }
13
- function vueTagForms(importName) {
14
- const lowercased = importName.toLowerCase();
15
- // Vue convention: PascalCase like `VBtn` becomes kebab `v-btn`. Insert a hyphen
16
- // before any uppercase letter that is preceded by a letter/digit (handles both
17
- // `aB`→`a-b` and the leading-uppercase case `VB`→`v-b`).
18
- const kebab = importName
19
- .replace(/([A-Za-z0-9])([A-Z])/g, "$1-$2")
20
- .toLowerCase();
21
- return Array.from(new Set([lowercased, kebab]));
22
- }
23
- export const vuePlugin = {
24
- name: "vue",
25
- extensions: [".vue"],
26
- parse(file, source, ctx) {
27
- // Single-pass scan invariant (#48): scan.ts owns the SFC parse and threads
28
- // the wrapper (descriptor + optional scriptAst) through ctx.ast. Defensive
29
- // throw — should only fire under direct plugin invocation that bypasses
30
- // scan.ts. Named `parsedWrapper` to disambiguate from the WrapperDef the
31
- // SFC emits.
32
- const parsedWrapper = ctx.ast;
33
- if (parsedWrapper === undefined) {
34
- throw new Error("parser-vue: ctx.ast must be provided (single-pass scan, #48)");
35
- }
36
- const parts = partsFromWrapper(parsedWrapper);
37
- let imports = [];
38
- let importSpecs = [];
39
- let sideEffectSources = [];
40
- const warnings = [];
41
- if (parts.scriptSource) {
42
- // scriptProgram is optional on the wrapper because an SFC with no script
43
- // block has no script AST to thread. When `parts.scriptSource` is
44
- // truthy, scan.ts must have produced a scriptProgram — anything else is
45
- // direct plugin misuse.
46
- if (parsedWrapper.scriptProgram === undefined) {
47
- throw new Error("parser-vue: wrapper.scriptProgram must be provided when the SFC has a script block (single-pass scan, #48)");
48
- }
49
- const scriptResult = extractScriptImports({
50
- file,
51
- program: parsedWrapper.scriptProgram,
52
- });
53
- imports = scriptResult.imports;
54
- importSpecs = scriptResult.importSpecs;
55
- sideEffectSources = scriptResult.sideEffectSources;
56
- warnings.push(...scriptResult.warnings);
57
- }
58
- // Side-effect imports (`import "pkg"`) carry no binding but signal that
59
- // the SFC depends on the package's runtime; prime the lazy resolver so
60
- // template tag references (`<x-button>`) find the leaf's CEM.
61
- for (const source of sideEffectSources) {
62
- ctx.resolveLazyManifest(file, source, "");
63
- }
64
- if (!parts.templateSource) {
65
- return { occurrences: [], wrappers: [], imports, warnings };
66
- }
67
- // Build map of template tag (lowercased + kebab forms) → vue-direct binding,
68
- // for direct Vue DS imports that resolve to a vue-component manifest entry.
69
- const templateBindings = new Map();
70
- // Track imports that did NOT match a manifest entry for opportunistic classification.
71
- const unmappedBindings = new Map();
72
- for (const spec of importSpecs) {
73
- const hit = ctx.resolveLazyManifest(file, spec.source, spec.imported);
74
- if (hit?.matched?.kind === "vue-component") {
75
- const binding = {
76
- kind: "vue-direct",
77
- package: hit.leafPackage,
78
- export: hit.matched.export,
79
- specifier: spec.source,
80
- importName: spec.imported,
81
- modulePath: hit.modulePath,
82
- };
83
- for (const form of vueTagForms(spec.local)) {
84
- templateBindings.set(form, binding);
85
- }
86
- }
87
- else if (hit) {
88
- // Resolver landed on a leaf (could be CE / RC / no match) — track as
89
- // opaque vue-unmapped with leafPackage so the template walker emits a
90
- // vue-component occurrence attributed to that leaf.
91
- const unmapped = {
92
- kind: "vue-unmapped",
93
- importedName: spec.imported,
94
- specifier: spec.source,
95
- leafPackage: hit.leafPackage,
96
- modulePath: hit.modulePath,
97
- };
98
- for (const form of vueTagForms(spec.local)) {
99
- unmappedBindings.set(form, unmapped);
100
- }
101
- }
102
- else {
103
- // Specifier did not resolve — fall back to local-component detection
104
- // in walk-template via classifyImportOrigin.
105
- const unmapped = {
106
- kind: "vue-unmapped",
107
- importedName: spec.imported,
108
- specifier: spec.source,
109
- leafPackage: null,
110
- modulePath: null,
111
- };
112
- for (const form of vueTagForms(spec.local)) {
113
- unmappedBindings.set(form, unmapped);
114
- }
115
- }
116
- }
117
- const lineOffset = source.slice(0, parts.templateOffset ?? 0).split("\n").length - 1;
118
- const ownerId = resolveSfcOwner(file, ctx.localIndex, ctx.repoRoot);
119
- const occurrences = walkVueTemplate({
120
- file,
121
- template: parts.templateSource,
122
- lineOffset,
123
- lookupByTag: ctx.lookupByTag,
124
- localIndex: ctx.localIndex,
125
- templateBindings,
126
- unmappedBindings,
127
- ...(ctx.cemIndex !== undefined ? { cemIndex: ctx.cemIndex } : {}),
128
- captureValues: ctx.config.captureValues,
129
- repoRoot: ctx.repoRoot,
130
- resolveImport: ctx.resolveImport,
131
- resolveLocalExport: ctx.resolveLocalExport,
132
- ...(ctx.knownPackageNames !== undefined ? { knownPackageNames: ctx.knownPackageNames } : {}),
133
- ...(ctx.collector !== undefined ? { collector: ctx.collector } : {}),
134
- ...(ownerId !== undefined ? { ownerId } : {}),
135
- });
136
- if (occurrences.length === 0) {
137
- return { occurrences: [], wrappers: [], imports, warnings };
138
- }
139
- const componentName = basename(file, extname(file));
140
- const seen = new Set();
141
- const componentDeps = [];
142
- for (const o of occurrences) {
143
- const key = serialiseComponentId(o.componentId);
144
- if (seen.has(key))
145
- continue;
146
- seen.add(key);
147
- componentDeps.push(o.componentId);
148
- }
149
- const wrapper = {
150
- id: wrapperIdFromName(componentName),
151
- name: componentName,
152
- file: posixPath(file),
153
- exportName: "default",
154
- componentDeps,
155
- };
156
- return {
157
- occurrences,
158
- wrappers: [wrapper],
159
- imports,
160
- warnings,
161
- };
162
- },
163
- };
1
+ export { emitVueTemplate } from "./emit-template.js";
164
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3D,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACxE,OAAO,WAAW,CAAC,QAAQ,KAAK,CAAC,UAAU,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,WAAW,CAAC,UAAkB;IACrC,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAC5C,gFAAgF;IAChF,+EAA+E;IAC/E,yDAAyD;IACzD,MAAM,KAAK,GAAG,UAAU;SACrB,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,WAAW,EAAE,CAAC;IACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAiB;IACrC,IAAI,EAAE,KAAK;IACX,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QACrB,2EAA2E;QAC3E,2EAA2E;QAC3E,wEAAwE;QACxE,yEAAyE;QACzE,aAAa;QACb,MAAM,aAAa,GAAG,GAAG,CAAC,GAAkC,CAAC;QAC7D,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,KAAK,GAAG,gBAAgB,CAAC,aAAa,CAAC,CAAC;QAE9C,IAAI,OAAO,GAAiB,EAAE,CAAC;QAC/B,IAAI,WAAW,GAAiB,EAAE,CAAC;QACnC,IAAI,iBAAiB,GAAa,EAAE,CAAC;QACrC,MAAM,QAAQ,GAA4B,EAAE,CAAC;QAC7C,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACvB,yEAAyE;YACzE,kEAAkE;YAClE,wEAAwE;YACxE,wBAAwB;YACxB,IAAI,aAAa,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;gBAC9C,MAAM,IAAI,KAAK,CACb,4GAA4G,CAC7G,CAAC;YACJ,CAAC;YACD,MAAM,YAAY,GAAG,oBAAoB,CAAC;gBACxC,IAAI;gBACJ,OAAO,EAAE,aAAa,CAAC,aAAa;aACrC,CAAC,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;YAC/B,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC;YACvC,iBAAiB,GAAG,YAAY,CAAC,iBAAiB,CAAC;YACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC1C,CAAC;QAED,wEAAwE;QACxE,uEAAuE;QACvE,8DAA8D;QAC9D,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;YACvC,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC1B,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;QAC9D,CAAC;QAED,6EAA6E;QAC7E,4EAA4E;QAC5E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA4B,CAAC;QAC7D,sFAAsF;QACtF,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA8B,CAAC;QAC/D,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtE,IAAI,GAAG,EAAE,OAAO,EAAE,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC3C,MAAM,OAAO,GAAqB;oBAChC,IAAI,EAAE,YAAY;oBAClB,OAAO,EAAE,GAAG,CAAC,WAAW;oBACxB,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM;oBAC1B,SAAS,EAAE,IAAI,CAAC,MAAM;oBACtB,UAAU,EAAE,IAAI,CAAC,QAAQ;oBACzB,UAAU,EAAE,GAAG,CAAC,UAAU;iBAC3B,CAAC;gBACF,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3C,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;iBAAM,IAAI,GAAG,EAAE,CAAC;gBACf,qEAAqE;gBACrE,sEAAsE;gBACtE,oDAAoD;gBACpD,MAAM,QAAQ,GAAuB;oBACnC,IAAI,EAAE,cAAc;oBACpB,YAAY,EAAE,IAAI,CAAC,QAAQ;oBAC3B,SAAS,EAAE,IAAI,CAAC,MAAM;oBACtB,WAAW,EAAE,GAAG,CAAC,WAAW;oBAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;iBAC3B,CAAC;gBACF,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3C,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,qEAAqE;gBACrE,6CAA6C;gBAC7C,MAAM,QAAQ,GAAuB;oBACnC,IAAI,EAAE,cAAc;oBACpB,YAAY,EAAE,IAAI,CAAC,QAAQ;oBAC3B,SAAS,EAAE,IAAI,CAAC,MAAM;oBACtB,WAAW,EAAE,IAAI;oBACjB,UAAU,EAAE,IAAI;iBACjB,CAAC;gBACF,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC3C,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACrF,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,WAAW,GAAG,eAAe,CAAC;YAClC,IAAI;YACJ,QAAQ,EAAE,KAAK,CAAC,cAAc;YAC9B,UAAU;YACV,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,UAAU,EAAE,GAAG,CAAC,UAAU;YAC1B,gBAAgB;YAChB,gBAAgB;YAChB,GAAG,CAAC,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,aAAa;YACvC,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,kBAAkB,EAAE,GAAG,CAAC,kBAAkB;YAC1C,GAAG,CAAC,GAAG,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5F,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9C,CAAC,CAAC;QAEH,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;QAC9D,CAAC;QAED,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,MAAM,aAAa,GAAkB,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAChD,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,SAAS;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACpC,CAAC;QACD,MAAM,OAAO,GAAe;YAC1B,EAAE,EAAE,iBAAiB,CAAC,aAAa,CAAC;YACpC,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC;YACrB,UAAU,EAAE,SAAS;YACrB,aAAa;SACd,CAAC;QAEF,OAAO;YACL,WAAW;YACX,QAAQ,EAAE,CAAC,OAAO,CAAC;YACnB,OAAO;YACP,QAAQ;SACT,CAAC;IACJ,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { DefaultTreeAdapterMap } from "parse5";
2
+ import type { PropUsage } from "@component-compass/plugin-core";
3
+ type Element = DefaultTreeAdapterMap["element"];
4
+ export declare function readAttrs(el: Element, captureValues: boolean): {
5
+ props: PropUsage[];
6
+ events: string[];
7
+ };
8
+ export {};
@@ -0,0 +1,69 @@
1
+ const IDENT_RE = /^[A-Za-z_$][\w$]*$/;
2
+ const QUOTED_STRING_RE = /^(['"])(.*)\1$/s;
3
+ const NUMERIC_RE = /^-?\d+(\.\d+)?$/;
4
+ const BOOLEAN_RE = /^(true|false)$/;
5
+ export function readAttrs(el, captureValues) {
6
+ const props = [];
7
+ const events = [];
8
+ for (const attr of el.attrs) {
9
+ if (/^@|^v-on:/.test(attr.name)) {
10
+ events.push(attr.name.replace(/^@|^v-on:/, ""));
11
+ continue;
12
+ }
13
+ // Bare `v-bind="obj"` (no arg) → spread sentinel, deduped.
14
+ if (attr.name === "v-bind") {
15
+ if (props.some((p) => p.name === "...rest"))
16
+ continue;
17
+ props.push({ name: "...rest", isDynamic: true });
18
+ continue;
19
+ }
20
+ // Other Vue directives that aren't prop bindings → ignore.
21
+ if (/^v-/.test(attr.name) && !/^v-bind:/.test(attr.name))
22
+ continue;
23
+ if (/^[:.]|^v-bind:/.test(attr.name)) {
24
+ const name = attr.name.replace(/^[:.]|^v-bind:/, "");
25
+ const expr = attr.value.trim();
26
+ const usage = classifyBindExpr(name, expr, captureValues);
27
+ props.push(usage);
28
+ continue;
29
+ }
30
+ // Static attribute. parse5 reports value `""` for boolean shorthand.
31
+ const usage = { name: attr.name, isDynamic: false };
32
+ if (captureValues) {
33
+ // Boolean shorthand: <X foo /> → literalValue: true.
34
+ // The HTML parser exposes both `<X foo>` and `<X foo="">` as value `""`.
35
+ // Treat empty value as boolean shorthand for consistency with the
36
+ // three-state model; explicit empty strings on Vue attributes are
37
+ // exceedingly rare in practice.
38
+ usage.literalValue = attr.value === "" ? true : attr.value;
39
+ }
40
+ props.push(usage);
41
+ }
42
+ return { props, events };
43
+ }
44
+ function classifyBindExpr(name, expr, captureValues) {
45
+ const quoted = expr.match(QUOTED_STRING_RE);
46
+ if (quoted) {
47
+ const usage = { name, isDynamic: false };
48
+ if (captureValues)
49
+ usage.literalValue = quoted[2] ?? "";
50
+ return usage;
51
+ }
52
+ if (NUMERIC_RE.test(expr)) {
53
+ const usage = { name, isDynamic: false };
54
+ if (captureValues)
55
+ usage.literalValue = Number(expr);
56
+ return usage;
57
+ }
58
+ if (BOOLEAN_RE.test(expr)) {
59
+ const usage = { name, isDynamic: false };
60
+ if (captureValues)
61
+ usage.literalValue = expr === "true";
62
+ return usage;
63
+ }
64
+ if (IDENT_RE.test(expr)) {
65
+ return { name, isDynamic: true };
66
+ }
67
+ return { name, isDynamic: true };
68
+ }
69
+ //# sourceMappingURL=read-attrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-attrs.js","sourceRoot":"","sources":["../src/read-attrs.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@component-compass/parser-vue",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Consumer-scan parser for Vue Single-File Components. Detects component usages in .vue files.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,8 +27,9 @@
27
27
  "clean": "rm -rf dist .turbo"
28
28
  },
29
29
  "dependencies": {
30
- "@component-compass/ast-utils": "0.1.0",
31
- "@component-compass/plugin-core": "0.1.0",
30
+ "@component-compass/ast-utils": "0.1.1",
31
+ "@component-compass/plugin-core": "0.1.1",
32
+ "@component-compass/reference-graph": "0.1.1",
32
33
  "@oxc-project/types": "0.130.0",
33
34
  "@vue/compiler-sfc": "3.5.33",
34
35
  "oxc-walker": "1.0.0",
package/dist/owner.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { ComponentId, LocalDefinitionIndex } from "@component-compass/plugin-core";
2
- /**
3
- * Resolve the enclosing SFC's Component Identity for owner-stamping.
4
- *
5
- * Every template-emitted Occurrence in a `.vue` file is owned by that SFC's
6
- * vue-component Identity. Looks up the file in the local-index — the single
7
- * source of truth populated by `detect-vue.ts` — so the owner stamp aligns
8
- * with the local-lane Component in `components[]`.
9
- *
10
- * Returns `undefined` if no Local definition exists for the file (e.g.
11
- * `<script>`-only files that don't match `defineComponent` or SFC shape).
12
- * Occurrences then surface as root in the composition rollup.
13
- */
14
- export declare function resolveSfcOwner(file: string, localIndex: LocalDefinitionIndex, repoRoot?: string): ComponentId | undefined;
package/dist/owner.js DELETED
@@ -1,22 +0,0 @@
1
- import { normalizeOwnerPath } from "@component-compass/plugin-core";
2
- /**
3
- * Resolve the enclosing SFC's Component Identity for owner-stamping.
4
- *
5
- * Every template-emitted Occurrence in a `.vue` file is owned by that SFC's
6
- * vue-component Identity. Looks up the file in the local-index — the single
7
- * source of truth populated by `detect-vue.ts` — so the owner stamp aligns
8
- * with the local-lane Component in `components[]`.
9
- *
10
- * Returns `undefined` if no Local definition exists for the file (e.g.
11
- * `<script>`-only files that don't match `defineComponent` or SFC shape).
12
- * Occurrences then surface as root in the composition rollup.
13
- */
14
- export function resolveSfcOwner(file, localIndex, repoRoot) {
15
- const normalizedPath = normalizeOwnerPath(file, repoRoot);
16
- const defs = localIndex.byPath.get(normalizedPath);
17
- const first = defs?.[0];
18
- if (!first)
19
- return undefined;
20
- return first.componentId;
21
- }
22
- //# sourceMappingURL=owner.js.map
package/dist/owner.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"owner.js","sourceRoot":"","sources":["../src/owner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,UAAgC,EAChC,QAAiB;IAEjB,MAAM,cAAc,GAAG,kBAAkB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxB,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,KAAK,CAAC,WAAW,CAAC;AAC3B,CAAC"}
@@ -1,51 +0,0 @@
1
- import type { CemIndex, ComponentId, DiagnosticCollector, LocalDefinitionIndex, LookupByTag, Occurrence, ResolveImport, ResolveLocalExport } from "@component-compass/plugin-core";
2
- export type VueDirectBinding = {
3
- kind: "vue-direct";
4
- package: string;
5
- export: string;
6
- specifier: string;
7
- importName: string;
8
- modulePath: string;
9
- };
10
- export type VueUnmappedBinding = {
11
- kind: "vue-unmapped";
12
- /** The original imported export name (e.g. "Button" or "default"). */
13
- importedName: string;
14
- /** The import specifier (module path). */
15
- specifier: string;
16
- /**
17
- * Non-null when the lazy resolver landed on a leaf package without a
18
- * manifest entry for `importedName` — in that case the template walker
19
- * attributes the opaque external occurrence to this leaf rather than
20
- * re-running origin classification on the user-written aggregator
21
- * specifier. Null when the specifier did not resolve via the lazy
22
- * resolver (relative path, alias, or unresolvable bare import).
23
- */
24
- leafPackage: string | null;
25
- /**
26
- * Package-relative resolved module path from the lazy resolver hit
27
- * (paired with non-null `leafPackage`); null when the resolver returned
28
- * no hit. Threaded onto the external identity by the template-emission
29
- * pass so downstream consumers can disambiguate same-export entries
30
- * served from different package subpaths (#63).
31
- */
32
- modulePath: string | null;
33
- };
34
- export type WalkVueTemplateOpts = {
35
- file: string;
36
- template: string;
37
- lineOffset: number;
38
- lookupByTag: LookupByTag;
39
- localIndex: LocalDefinitionIndex;
40
- templateBindings: Map<string, VueDirectBinding>;
41
- unmappedBindings?: Map<string, VueUnmappedBinding>;
42
- cemIndex?: CemIndex;
43
- captureValues: boolean;
44
- repoRoot?: string;
45
- resolveImport?: ResolveImport;
46
- resolveLocalExport?: ResolveLocalExport;
47
- knownPackageNames?: ReadonlySet<string>;
48
- collector?: DiagnosticCollector;
49
- ownerId?: ComponentId;
50
- };
51
- export declare function walkVueTemplate(opts: WalkVueTemplateOpts): Occurrence[];
@@ -1,330 +0,0 @@
1
- import { parseFragment } from "parse5";
2
- import { asTagName, externalPackageOf } from "@component-compass/plugin-core";
3
- import { posixPath, isElement, hasChildren, classifyImportOrigin } from "@component-compass/ast-utils";
4
- export function walkVueTemplate(opts) {
5
- const { file, template, lineOffset, lookupByTag, localIndex, templateBindings, unmappedBindings, cemIndex, captureValues, repoRoot, resolveImport, resolveLocalExport, knownPackageNames, collector, ownerId, } = opts;
6
- const occurrences = [];
7
- const doc = parseFragment(template, { sourceCodeLocationInfo: true });
8
- // Phase 2: parent stack maintains the lexical chain of tracked elements.
9
- // Vue scoped slots (`v-slot` on a host element) are deliberately treated as
10
- // lexical — `<DataLoader v-slot="d"><Card/></DataLoader>` records `<Card>`'s
11
- // parent as `<DataLoader>` because parse5 sees the slot content as a direct
12
- // child of the host element. No render-prop guard is needed here (unlike the
13
- // React walker), per the Phase 2 spec's parser-vue concerns.
14
- const parentStack = [];
15
- /** Push the occurrence onto the array, stamping parentRef + depth from the
16
- * current parent stack. Returns the new index so the caller can later push
17
- * this element onto the stack as a parent for its children. */
18
- function emit(occurrence) {
19
- const top = parentStack[parentStack.length - 1];
20
- if (top)
21
- occurrence.parentRef = top.idx;
22
- occurrence.depth = parentStack.length;
23
- if (ownerId !== undefined)
24
- occurrence.ownerComponentId = ownerId;
25
- const idx = occurrences.length;
26
- occurrences.push(occurrence);
27
- return idx;
28
- }
29
- function visit(node) {
30
- if (isElement(node)) {
31
- const rawTag = node.tagName;
32
- const indexedWc = lookupByTag(rawTag);
33
- let pushedIdx;
34
- if (indexedWc) {
35
- pushedIdx = emitWcOccurrence(node, indexedWc);
36
- }
37
- else {
38
- const direct = templateBindings.get(rawTag);
39
- if (direct) {
40
- pushedIdx = emitVueDirectOccurrence(node, direct);
41
- }
42
- else if (unmappedBindings && repoRoot && resolveImport) {
43
- const unmapped = unmappedBindings.get(rawTag);
44
- if (unmapped) {
45
- if (unmapped.leafPackage) {
46
- // Resolver knew the leaf — emit external with that package.
47
- pushedIdx = emitOpportunisticVueOccurrence(node, unmapped, unmapped.leafPackage);
48
- }
49
- else {
50
- // Specifier didn't resolve via the lazy resolver — fall back to
51
- // local-component detection via classifyImportOrigin against the
52
- // user-written specifier.
53
- const origin = classifyImportOrigin(unmapped.specifier, {
54
- repoRoot,
55
- fromFile: file,
56
- resolveImport,
57
- ...(knownPackageNames !== undefined ? { knownPackageNames } : {}),
58
- });
59
- if (origin.type === "external") {
60
- // Manifest enrichment is disabled but the specifier resolves to
61
- // node_modules — emit an opaque external occurrence keyed by
62
- // package name. Identity resolution and manifest enrichment are
63
- // separate concerns; the component still appears in components[]
64
- // with manifest: null.
65
- pushedIdx = emitOpportunisticVueOccurrence(node, unmapped, origin.package);
66
- }
67
- else if (origin.type === "local") {
68
- // Direct byPath lookup may miss when origin.filePath is a barrel
69
- // re-exporting the import name from elsewhere (bug 3). Try
70
- // resolveLocalExport to walk the chain, then retry at terminal.
71
- let resolvedFilePath = origin.filePath;
72
- let resolvedExportName = unmapped.importedName;
73
- let localDefs = localIndex.byPath.get(resolvedFilePath);
74
- let matched = localDefs?.find((d) => resolvedExportName === "default"
75
- ? d.isDefault
76
- : d.exportName === resolvedExportName && !d.isDefault);
77
- if (!matched && resolveLocalExport) {
78
- const localExport = resolveLocalExport(origin.filePath, unmapped.importedName);
79
- if (localExport) {
80
- resolvedFilePath = localExport.filePath;
81
- resolvedExportName = localExport.exportName;
82
- localDefs = localIndex.byPath.get(resolvedFilePath);
83
- matched = localDefs?.find((d) => resolvedExportName === "default"
84
- ? d.isDefault
85
- : d.exportName === resolvedExportName && !d.isDefault);
86
- }
87
- }
88
- if (matched && matched.componentId.kind === "vue-component") {
89
- pushedIdx = emitLocalVueOccurrence(node, unmapped, matched.componentId);
90
- }
91
- // Local miss → skip silently.
92
- }
93
- else if (origin.type === "unresolved") {
94
- // Genuinely unresolvable specifier. Emit a diagnostic at the
95
- // template-tag usage site; drop the occurrence. Replaces the
96
- // deleted bare-spec heuristic (source of bug 1).
97
- const loc = node.sourceCodeLocation;
98
- collector?.emit({
99
- code: "unresolved-import",
100
- severity: "warning",
101
- filePath: posixPath(file),
102
- line: (loc?.startLine ?? 1) + lineOffset,
103
- column: loc?.startCol ?? 0,
104
- specifier: unmapped.specifier,
105
- });
106
- }
107
- }
108
- }
109
- else if (rawTag.includes("-")) {
110
- // Hyphenated tag not in index: Vue auto-import convention (e.g. Vuetify).
111
- pushedIdx = emitOpportunisticVueAutoImport(node);
112
- }
113
- }
114
- else if (rawTag.includes("-")) {
115
- // No unmapped bindings provided but tag is hyphenated and not in index.
116
- pushedIdx = emitOpportunisticVueAutoImport(node);
117
- }
118
- }
119
- // Tracked elements push themselves as the lexical parent for their
120
- // children; non-tracked elements (plain HTML, untracked components)
121
- // skip the push so descendants attribute to the next tracked ancestor
122
- // (parent-transparency rule).
123
- if (pushedIdx !== undefined)
124
- parentStack.push({ idx: pushedIdx, node });
125
- for (const child of node.childNodes)
126
- visit(child);
127
- if (pushedIdx !== undefined)
128
- parentStack.pop();
129
- }
130
- else if (hasChildren(node)) {
131
- for (const child of node.childNodes)
132
- visit(child);
133
- }
134
- }
135
- function emitWcOccurrence(node, indexed) {
136
- const tag = asTagName(node.tagName);
137
- const { props, events } = readAttrs(node, captureValues);
138
- const loc = node.sourceCodeLocation;
139
- return emit({
140
- componentId: { kind: "custom-element", tagName: tag, source: { type: "external", package: externalPackageOf(indexed.source) } },
141
- loc: {
142
- file: posixPath(file),
143
- line: (loc?.startLine ?? 1) + lineOffset,
144
- column: loc?.startCol ?? 1,
145
- },
146
- via: { kind: "html-tag" },
147
- props,
148
- events,
149
- });
150
- }
151
- function emitOpportunisticVueOccurrence(node, binding, pkg) {
152
- const { props, events } = readAttrs(node, captureValues);
153
- const loc = node.sourceCodeLocation;
154
- const via = {
155
- kind: "vue-template",
156
- specifier: binding.specifier,
157
- import: binding.importedName,
158
- };
159
- return emit({
160
- componentId: {
161
- kind: "vue-component",
162
- export: binding.importedName,
163
- source: {
164
- type: "external",
165
- package: pkg,
166
- ...(binding.modulePath !== null ? { modulePath: binding.modulePath } : {}),
167
- },
168
- },
169
- loc: {
170
- file: posixPath(file),
171
- line: (loc?.startLine ?? 1) + lineOffset,
172
- column: loc?.startCol ?? 1,
173
- },
174
- via,
175
- props,
176
- events,
177
- });
178
- }
179
- function emitLocalVueOccurrence(node, binding, componentId) {
180
- const { props, events } = readAttrs(node, captureValues);
181
- const loc = node.sourceCodeLocation;
182
- const via = {
183
- kind: "vue-template",
184
- specifier: binding.specifier,
185
- import: binding.importedName,
186
- };
187
- return emit({
188
- componentId,
189
- loc: {
190
- file: posixPath(file),
191
- line: (loc?.startLine ?? 1) + lineOffset,
192
- column: loc?.startCol ?? 1,
193
- },
194
- via,
195
- props,
196
- events,
197
- });
198
- }
199
- function emitOpportunisticVueAutoImport(node) {
200
- const tag = asTagName(node.tagName);
201
- const { props, events } = readAttrs(node, captureValues);
202
- const loc = node.sourceCodeLocation;
203
- // CEM index lookup: attribute to the package if known, otherwise emit
204
- // unattributed but still tracked (packageName: null in the output).
205
- const cemEntry = cemIndex?.byTag.get(tag);
206
- if (!cemEntry) {
207
- collector?.emit({
208
- code: "vue-tag-low-confidence",
209
- severity: "info",
210
- filePath: posixPath(file),
211
- ...(loc?.startLine !== undefined && { line: loc.startLine + lineOffset }),
212
- ...(loc?.startCol !== undefined && { column: loc.startCol }),
213
- tagName: tag,
214
- emittedAs: "custom-element",
215
- });
216
- }
217
- return emit({
218
- componentId: {
219
- kind: "custom-element",
220
- tagName: tag,
221
- source: cemEntry
222
- ? { type: "external", package: cemEntry.packageName }
223
- : { type: "unknown" },
224
- },
225
- loc: {
226
- file: posixPath(file),
227
- line: (loc?.startLine ?? 1) + lineOffset,
228
- column: loc?.startCol ?? 1,
229
- },
230
- via: { kind: "html-tag" },
231
- props,
232
- events,
233
- });
234
- }
235
- function emitVueDirectOccurrence(node, binding) {
236
- const { props, events } = readAttrs(node, captureValues);
237
- const loc = node.sourceCodeLocation;
238
- const via = {
239
- kind: "vue-template",
240
- specifier: binding.specifier,
241
- import: binding.importName,
242
- };
243
- return emit({
244
- componentId: {
245
- kind: "vue-component",
246
- export: binding.export,
247
- source: { type: "external", package: binding.package, modulePath: binding.modulePath },
248
- },
249
- loc: {
250
- file: posixPath(file),
251
- line: (loc?.startLine ?? 1) + lineOffset,
252
- column: loc?.startCol ?? 1,
253
- },
254
- via,
255
- props,
256
- events,
257
- });
258
- }
259
- visit(doc);
260
- return occurrences;
261
- }
262
- const IDENT_RE = /^[A-Za-z_$][\w$]*$/;
263
- const QUOTED_STRING_RE = /^(['"])(.*)\1$/s;
264
- const NUMERIC_RE = /^-?\d+(\.\d+)?$/;
265
- const BOOLEAN_RE = /^(true|false)$/;
266
- function readAttrs(el, captureValues) {
267
- const props = [];
268
- const events = [];
269
- for (const attr of el.attrs) {
270
- if (/^@|^v-on:/.test(attr.name)) {
271
- events.push(attr.name.replace(/^@|^v-on:/, ""));
272
- continue;
273
- }
274
- // Bare `v-bind="obj"` (no arg) → spread sentinel, deduped.
275
- if (attr.name === "v-bind") {
276
- if (props.some((p) => p.name === "...rest"))
277
- continue;
278
- props.push({ name: "...rest", isDynamic: true });
279
- continue;
280
- }
281
- // Other Vue directives that aren't prop bindings → ignore.
282
- if (/^v-/.test(attr.name) && !/^v-bind:/.test(attr.name))
283
- continue;
284
- if (/^[:.]|^v-bind:/.test(attr.name)) {
285
- const name = attr.name.replace(/^[:.]|^v-bind:/, "");
286
- const expr = attr.value.trim();
287
- const usage = classifyBindExpr(name, expr, captureValues);
288
- props.push(usage);
289
- continue;
290
- }
291
- // Static attribute. parse5 reports value `""` for boolean shorthand.
292
- const usage = { name: attr.name, isDynamic: false };
293
- if (captureValues) {
294
- // Boolean shorthand: <X foo /> → literalValue: true.
295
- // The HTML parser exposes both `<X foo>` and `<X foo="">` as value `""`.
296
- // Treat empty value as boolean shorthand for consistency with the
297
- // three-state model; explicit empty strings on Vue attributes are
298
- // exceedingly rare in practice.
299
- usage.literalValue = attr.value === "" ? true : attr.value;
300
- }
301
- props.push(usage);
302
- }
303
- return { props, events };
304
- }
305
- function classifyBindExpr(name, expr, captureValues) {
306
- const quoted = expr.match(QUOTED_STRING_RE);
307
- if (quoted) {
308
- const usage = { name, isDynamic: false };
309
- if (captureValues)
310
- usage.literalValue = quoted[2] ?? "";
311
- return usage;
312
- }
313
- if (NUMERIC_RE.test(expr)) {
314
- const usage = { name, isDynamic: false };
315
- if (captureValues)
316
- usage.literalValue = Number(expr);
317
- return usage;
318
- }
319
- if (BOOLEAN_RE.test(expr)) {
320
- const usage = { name, isDynamic: false };
321
- if (captureValues)
322
- usage.literalValue = expr === "true";
323
- return usage;
324
- }
325
- if (IDENT_RE.test(expr)) {
326
- return { name, isDynamic: true };
327
- }
328
- return { name, isDynamic: true };
329
- }
330
- //# sourceMappingURL=walk-template.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"walk-template.js","sourceRoot":"","sources":["../src/walk-template.ts"],"names":[],"mappings":"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"}