@eventra_dev/eventra-cli 0.1.16 → 0.1.18

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.
@@ -38,17 +38,18 @@ async function check({ fix = false }) {
38
38
  const known = new Set(config.events ?? []);
39
39
  const newEvents = [...found].filter(e => !known.has(e));
40
40
  const removed = [...known].filter(e => !found.has(e));
41
+ // FIX MODE
41
42
  if (fix) {
42
- const merged = new Set(config.events ?? []);
43
- newEvents.forEach(e => {
44
- merged.add(e);
45
- console.log(chalk_1.default.green(`+ ${e}`));
46
- });
47
- config.events = [...merged].sort();
43
+ const next = new Set();
44
+ found.forEach(e => next.add(e));
45
+ newEvents.forEach(e => console.log(chalk_1.default.green(`+ ${e}`)));
46
+ removed.forEach(e => console.log(chalk_1.default.red(`- ${e}`)));
47
+ config.events = [...next].sort();
48
48
  await (0, config_1.saveConfig)(config);
49
- console.log(chalk_1.default.green("\nFixed"));
49
+ console.log(chalk_1.default.green(`\nSynced (${config.events.length} events)`));
50
50
  return;
51
51
  }
52
+ // CHECK MODE
52
53
  if (newEvents.length || removed.length) {
53
54
  if (newEvents.length) {
54
55
  console.log(chalk_1.default.red("\nNew events:"));
@@ -12,13 +12,7 @@ const path_1 = __importDefault(require("path"));
12
12
  const config_1 = require("../utils/config");
13
13
  const engine_1 = require("../engine/engine");
14
14
  const processFile_1 = require("../utils/processFile");
15
- const toVirtual = async (file) => {
16
- const abs = path_1.default.resolve(file);
17
- const raw = await promises_1.default.readFile(abs, "utf-8");
18
- return (0, processFile_1.processFile)(abs, raw);
19
- };
20
15
  async function watch() {
21
- process.env.EVENTRA_WATCH = "1";
22
16
  const config = await (0, config_1.loadConfig)();
23
17
  if (!config)
24
18
  return;
@@ -34,7 +28,6 @@ async function watch() {
34
28
  const abs = path_1.default.resolve(file);
35
29
  const raw = await promises_1.default.readFile(abs, "utf-8");
36
30
  const { content, virtualFile } = (0, processFile_1.processFile)(abs, raw);
37
- engine["ts"].updateFile(virtualFile, content);
38
31
  fileCache.push({ file: virtualFile, content });
39
32
  }
40
33
  catch {
@@ -59,7 +52,8 @@ async function watch() {
59
52
  queued.clear();
60
53
  for (const file of batch) {
61
54
  try {
62
- const { content, virtualFile } = await toVirtual(file);
55
+ const raw = await promises_1.default.readFile(file, "utf-8");
56
+ const { content, virtualFile } = (0, processFile_1.processFile)(file, raw);
63
57
  engine.updateFile(virtualFile, content, config);
64
58
  }
65
59
  catch {
@@ -87,6 +87,7 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
87
87
  const isAutoWrapper = resolvedFn && (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn) !== null;
88
88
  const isTracking = isKnownWrapper ||
89
89
  TRACKING_NAMES.has(name) ||
90
+ name.startsWith("$") || // NUXT FIX
90
91
  (isAutoWrapper &&
91
92
  resolvedFn &&
92
93
  !(0, boundary_1.isExternalFile)(resolvedFn.getSourceFile().fileName));
@@ -97,7 +98,6 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
97
98
  if (!isKnownWrapper && isAutoWrapper && !TRACKING_NAMES.has(name)) {
98
99
  detectedFunctionWrappers.add(name);
99
100
  }
100
- // paramMap (chain support)
101
101
  const paramMap = new Map(inheritedParamMap ?? []);
102
102
  if (resolvedFn && typescript_1.default.isFunctionLike(resolvedFn)) {
103
103
  resolvedFn.parameters.forEach((param, i) => {
@@ -110,6 +110,7 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
110
110
  });
111
111
  }
112
112
  let handled = false;
113
+ // MAIN RESOLVE
113
114
  if (resolvedFn) {
114
115
  const idx = (0, functionAnalyzer_1.findTrackParamIndex)(resolvedFn);
115
116
  if (idx !== null && node.arguments[idx]) {
@@ -121,6 +122,7 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
121
122
  handled = true;
122
123
  }
123
124
  }
125
+ // FALLBACK
124
126
  if (!handled) {
125
127
  for (const arg of node.arguments) {
126
128
  const res = (0, resolver_1.resolveNodeValue)(arg, checker, paramMap);
@@ -130,7 +132,7 @@ function scanSource(source, checker, config, visited = new Set(), depth = 0, inh
130
132
  });
131
133
  }
132
134
  }
133
- // cross-file with paramMap
135
+ // CROSS FILE
134
136
  if (resolvedFn) {
135
137
  const sf = resolvedFn.getSourceFile();
136
138
  if (!visited.has(sf.fileName)) {
@@ -1,13 +1,33 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.parseAstro = parseAstro;
4
- function parseAstro(content) {
5
- const frontmatter = content.match(/---([\s\S]*?)---/);
6
- const scripts = [
7
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
8
- ];
9
- return [
10
- frontmatter?.[1] ?? "",
11
- ...scripts.map(s => s[1])
12
- ].join("\n");
7
+ const path_1 = __importDefault(require("path"));
8
+ function parseAstro(content, file) {
9
+ const parts = [];
10
+ // frontmatter
11
+ const frontmatter = content.match(/^---([\s\S]*?)---/);
12
+ if (frontmatter?.[1]) {
13
+ parts.push(frontmatter[1]);
14
+ }
15
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
16
+ for (const m of scripts) {
17
+ const attrs = m[1];
18
+ const body = m[2];
19
+ if (attrs.includes("src")) {
20
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
21
+ if (!src)
22
+ continue;
23
+ const resolved = src.startsWith("/")
24
+ ? path_1.default.resolve(process.cwd(), src.slice(1))
25
+ : path_1.default.resolve(path_1.default.dirname(file), src);
26
+ parts.push(`import "${resolved}"`);
27
+ }
28
+ else {
29
+ parts.push(body);
30
+ }
31
+ }
32
+ return parts.join("\n");
13
33
  }
@@ -1,13 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.detectParser = detectParser;
4
+ const vue_1 = require("./vue");
5
+ const svelte_1 = require("./svelte");
6
+ const astro_1 = require("./astro");
7
+ const fallback = (content) => content;
4
8
  function detectParser(file) {
5
- file = file.toLowerCase();
6
- if (file.endsWith(".vue"))
7
- return "vue";
8
- if (file.endsWith(".svelte"))
9
- return "svelte";
10
- if (file.endsWith(".astro"))
11
- return "astro";
12
- return "ts";
9
+ const f = file.toLowerCase();
10
+ if (f.endsWith(".vue"))
11
+ return vue_1.parseVue;
12
+ if (f.endsWith(".svelte"))
13
+ return svelte_1.parseSvelte;
14
+ if (f.endsWith(".astro"))
15
+ return astro_1.parseAstro;
16
+ return fallback;
13
17
  }
@@ -1,9 +1,31 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.parseSvelte = parseSvelte;
4
- function parseSvelte(content) {
5
- const scriptMatches = [
6
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
7
- ];
8
- return scriptMatches.map(m => m[1]).join("\n");
7
+ const path_1 = __importDefault(require("path"));
8
+ function parseSvelte(content, file) {
9
+ const parts = [];
10
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
11
+ for (const m of scripts) {
12
+ const attrs = m[1];
13
+ const body = m[2];
14
+ if (attrs.includes("src")) {
15
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
16
+ if (!src)
17
+ continue;
18
+ const resolved = src.startsWith("/")
19
+ ? path_1.default.resolve(process.cwd(), src.slice(1))
20
+ : path_1.default.resolve(path_1.default.dirname(file), src);
21
+ parts.push(`import "${resolved}"`);
22
+ continue;
23
+ }
24
+ parts.push(body);
25
+ }
26
+ // handlers
27
+ for (const h of content.matchAll(/on:\w+=\{([^}]+)\}/g)) {
28
+ parts.push(`${h[1]}();`);
29
+ }
30
+ return parts.join("\n");
9
31
  }
@@ -1,31 +1,41 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.parseVue = parseVue;
4
- function parseVue(content) {
5
- const scriptMatches = [
6
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
7
- ];
8
- const script = scriptMatches.map(m => m[1]).join("\n");
9
- // template
10
- const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
7
+ const path_1 = __importDefault(require("path"));
8
+ function parseVue(content, file) {
9
+ const parts = [];
10
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
11
+ for (const m of scripts) {
12
+ const attrs = m[1];
13
+ const body = m[2];
14
+ // src
15
+ if (attrs.includes("src")) {
16
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
17
+ if (!src)
18
+ continue;
19
+ const resolved = src.startsWith("/")
20
+ ? path_1.default.resolve(process.cwd(), src.slice(1))
21
+ : path_1.default.resolve(path_1.default.dirname(file), src);
22
+ parts.push(`import "${resolved}"`);
23
+ continue;
24
+ }
25
+ // script setup
26
+ parts.push(body);
27
+ }
28
+ // TEMPLATE
29
+ const templateMatch = content.match(/<template[^>]*>([\s\S]*?)<\/template>/);
11
30
  let template = templateMatch?.[1] ?? "";
12
31
  template = template.replace(/<!--[\s\S]*?-->/g, "");
13
- // Vue → JSX
14
- template = template
15
- .replace(/\bclass=/g, "className=")
16
- .replace(/\bfor=/g, "htmlFor=")
17
- .replace(/@(\w+)=/g, (_, e) => {
18
- const name = e.charAt(0).toUpperCase() + e.slice(1);
19
- return `on${name}=`;
20
- })
21
- .replace(/v-if="[^"]+"/g, "")
22
- .replace(/v-for="[^"]+"/g, "");
23
- const jsx = `
24
- const __VUE_JSX__ = (
25
- <>
26
- ${template}
27
- </>
28
- );
29
- `;
30
- return script + "\n" + jsx;
32
+ // @click
33
+ for (const m of template.matchAll(/@[\w-]+="([^"]+)"/g)) {
34
+ parts.push(`${m[1]}();`);
35
+ }
36
+ // v-on
37
+ for (const m of template.matchAll(/v-on:[\w-]+="([^"]+)"/g)) {
38
+ parts.push(`${m[1]}();`);
39
+ }
40
+ return parts.join("\n");
31
41
  }
@@ -1,22 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.processFile = processFile;
7
+ const path_1 = __importDefault(require("path"));
4
8
  const router_1 = require("./parsers/router");
5
- const vue_1 = require("./parsers/vue");
6
- const svelte_1 = require("./parsers/svelte");
7
- const astro_1 = require("./parsers/astro");
8
9
  function processFile(file, content) {
9
- const parser = (0, router_1.detectParser)(file);
10
- if (parser === "vue")
11
- content = (0, vue_1.parseVue)(content);
12
- if (parser === "svelte")
13
- content = (0, svelte_1.parseSvelte)(content);
14
- if (parser === "astro")
15
- content = (0, astro_1.parseAstro)(content);
16
- const virtualFile = file.endsWith(".vue") ||
10
+ const abs = path_1.default.resolve(file);
11
+ const parser = (0, router_1.detectParser)(abs);
12
+ content = parser(content, abs);
13
+ const isVirtual = file.endsWith(".vue") ||
17
14
  file.endsWith(".svelte") ||
18
- file.endsWith(".astro")
19
- ? file + ".tsx"
20
- : file;
15
+ file.endsWith(".astro");
16
+ const virtualFile = isVirtual ? abs + ".tsx" : abs;
21
17
  return { content, virtualFile };
22
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventra_dev/eventra-cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Eventra CLI",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -25,7 +25,6 @@ export async function check({ fix = false }: { fix?: boolean }) {
25
25
  for (const file of files) {
26
26
  try {
27
27
  const raw = await fs.readFile(file, "utf-8");
28
-
29
28
  const { content, virtualFile } = processFile(file, raw);
30
29
 
31
30
  engine.scanFile(virtualFile, content, config);
@@ -45,31 +44,45 @@ export async function check({ fix = false }: { fix?: boolean }) {
45
44
  const newEvents = [...found].filter(e => !known.has(e));
46
45
  const removed = [...known].filter(e => !found.has(e));
47
46
 
47
+ // FIX MODE
48
48
  if (fix) {
49
- const merged = new Set(config.events ?? []);
49
+ const next = new Set<string>();
50
+
51
+ found.forEach(e => next.add(e));
50
52
 
51
- newEvents.forEach(e => {
52
- merged.add(e);
53
- console.log(chalk.green(`+ ${e}`));
54
- });
53
+ newEvents.forEach(e =>
54
+ console.log(chalk.green(`+ ${e}`))
55
+ );
55
56
 
56
- config.events = [...merged].sort();
57
+ removed.forEach(e =>
58
+ console.log(chalk.red(`- ${e}`))
59
+ );
60
+
61
+ config.events = [...next].sort();
57
62
 
58
63
  await saveConfig(config);
59
64
 
60
- console.log(chalk.green("\nFixed"));
65
+ console.log(
66
+ chalk.green(`\nSynced (${config.events.length} events)`)
67
+ );
68
+
61
69
  return;
62
70
  }
63
71
 
72
+ // CHECK MODE
64
73
  if (newEvents.length || removed.length) {
65
74
  if (newEvents.length) {
66
75
  console.log(chalk.red("\nNew events:"));
67
- newEvents.forEach(e => console.log(chalk.red(`+ ${e}`)));
76
+ newEvents.forEach(e =>
77
+ console.log(chalk.red(`+ ${e}`))
78
+ );
68
79
  }
69
80
 
70
81
  if (removed.length) {
71
82
  console.log(chalk.yellow("\nRemoved events:"));
72
- removed.forEach(e => console.log(chalk.yellow(`- ${e}`)));
83
+ removed.forEach(e =>
84
+ console.log(chalk.yellow(`- ${e}`))
85
+ );
73
86
  }
74
87
 
75
88
  process.exit(1);
@@ -8,15 +8,7 @@ import { loadConfig, saveConfig } from "../utils/config";
8
8
  import { EventraEngine } from "../engine/engine";
9
9
  import { processFile } from "../utils/processFile";
10
10
 
11
- const toVirtual = async (file: string) => {
12
- const abs = path.resolve(file);
13
- const raw = await fs.readFile(abs, "utf-8");
14
- return processFile(abs, raw);
15
- };
16
-
17
11
  export async function watch() {
18
- process.env.EVENTRA_WATCH = "1";
19
-
20
12
  const config = await loadConfig();
21
13
  if (!config) return;
22
14
 
@@ -36,7 +28,6 @@ export async function watch() {
36
28
  const abs = path.resolve(file);
37
29
  const raw = await fs.readFile(abs, "utf-8");
38
30
  const { content, virtualFile } = processFile(abs, raw);
39
- engine["ts"].updateFile(virtualFile, content);
40
31
  fileCache.push({ file: virtualFile, content });
41
32
  } catch {
42
33
  console.log(chalk.gray(`skip: ${file}`));
@@ -68,7 +59,8 @@ export async function watch() {
68
59
 
69
60
  for (const file of batch) {
70
61
  try {
71
- const { content, virtualFile } = await toVirtual(file);
62
+ const raw = await fs.readFile(file, "utf-8");
63
+ const { content, virtualFile } = processFile(file, raw);
72
64
 
73
65
  engine.updateFile(virtualFile, content, config);
74
66
 
@@ -126,6 +126,7 @@ export function scanSource(
126
126
  const isTracking =
127
127
  isKnownWrapper ||
128
128
  TRACKING_NAMES.has(name) ||
129
+ name.startsWith("$") || // NUXT FIX
129
130
  (isAutoWrapper &&
130
131
  resolvedFn &&
131
132
  !isExternalFile(resolvedFn.getSourceFile().fileName));
@@ -139,7 +140,6 @@ export function scanSource(
139
140
  detectedFunctionWrappers.add(name);
140
141
  }
141
142
 
142
- // paramMap (chain support)
143
143
  const paramMap = new Map(inheritedParamMap ?? []);
144
144
 
145
145
  if (resolvedFn && ts.isFunctionLike(resolvedFn)) {
@@ -155,6 +155,7 @@ export function scanSource(
155
155
 
156
156
  let handled = false;
157
157
 
158
+ // MAIN RESOLVE
158
159
  if (resolvedFn) {
159
160
  const idx = findTrackParamIndex(resolvedFn);
160
161
 
@@ -173,6 +174,7 @@ export function scanSource(
173
174
  }
174
175
  }
175
176
 
177
+ // FALLBACK
176
178
  if (!handled) {
177
179
  for (const arg of node.arguments) {
178
180
  const res = resolveNodeValue(arg, checker, paramMap);
@@ -183,7 +185,7 @@ export function scanSource(
183
185
  }
184
186
  }
185
187
 
186
- // cross-file with paramMap
188
+ // CROSS FILE
187
189
  if (resolvedFn) {
188
190
  const sf = resolvedFn.getSourceFile();
189
191
 
package/src/types.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export type ScanMode = "strict" | "hybrid" | "discovery";
2
2
 
3
+ export type Parser = (content: string, file: string) => string;
4
+
3
5
  export type ComponentWrapper = {
4
6
  name: string;
5
7
  prop: string;
@@ -23,8 +25,3 @@ export type EventraConfig = {
23
25
  exclude: string[];
24
26
  };
25
27
  };
26
-
27
- export type ResolveResult = {
28
- values: string[];
29
- dynamic: boolean;
30
- };
@@ -1,12 +1,33 @@
1
- export function parseAstro(content: string) {
2
- const frontmatter = content.match(/---([\s\S]*?)---/);
1
+ import path from "path";
3
2
 
4
- const scripts = [
5
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
6
- ];
3
+ export function parseAstro(content: string, file: string) {
4
+ const parts: string[] = [];
7
5
 
8
- return [
9
- frontmatter?.[1] ?? "",
10
- ...scripts.map(s => s[1])
11
- ].join("\n");
6
+ // frontmatter
7
+ const frontmatter = content.match(/^---([\s\S]*?)---/);
8
+ if (frontmatter?.[1]) {
9
+ parts.push(frontmatter[1]);
10
+ }
11
+
12
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
13
+
14
+ for (const m of scripts) {
15
+ const attrs = m[1];
16
+ const body = m[2];
17
+
18
+ if (attrs.includes("src")) {
19
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
20
+ if (!src) continue;
21
+
22
+ const resolved = src.startsWith("/")
23
+ ? path.resolve(process.cwd(), src.slice(1))
24
+ : path.resolve(path.dirname(file), src);
25
+
26
+ parts.push(`import "${resolved}"`);
27
+ } else {
28
+ parts.push(body);
29
+ }
30
+ }
31
+
32
+ return parts.join("\n");
12
33
  }
@@ -1,9 +1,16 @@
1
- export function detectParser(file: string) {
2
- file = file.toLowerCase();
1
+ import { Parser } from "../../types";
2
+ import { parseVue } from "./vue";
3
+ import { parseSvelte } from "./svelte";
4
+ import { parseAstro } from "./astro";
3
5
 
4
- if (file.endsWith(".vue")) return "vue";
5
- if (file.endsWith(".svelte")) return "svelte";
6
- if (file.endsWith(".astro")) return "astro";
6
+ const fallback: Parser = (content) => content;
7
7
 
8
- return "ts";
8
+ export function detectParser(file: string): Parser {
9
+ const f = file.toLowerCase();
10
+
11
+ if (f.endsWith(".vue")) return parseVue;
12
+ if (f.endsWith(".svelte")) return parseSvelte;
13
+ if (f.endsWith(".astro")) return parseAstro;
14
+
15
+ return fallback;
9
16
  }
@@ -1,7 +1,33 @@
1
- export function parseSvelte(content: string) {
2
- const scriptMatches = [
3
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
4
- ];
1
+ import path from "path";
5
2
 
6
- return scriptMatches.map(m => m[1]).join("\n");
3
+ export function parseSvelte(content: string, file: string) {
4
+ const parts: string[] = [];
5
+
6
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
7
+
8
+ for (const m of scripts) {
9
+ const attrs = m[1];
10
+ const body = m[2];
11
+
12
+ if (attrs.includes("src")) {
13
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
14
+ if (!src) continue;
15
+
16
+ const resolved = src.startsWith("/")
17
+ ? path.resolve(process.cwd(), src.slice(1))
18
+ : path.resolve(path.dirname(file), src);
19
+
20
+ parts.push(`import "${resolved}"`);
21
+ continue;
22
+ }
23
+
24
+ parts.push(body);
25
+ }
26
+
27
+ // handlers
28
+ for (const h of content.matchAll(/on:\w+=\{([^}]+)\}/g)) {
29
+ parts.push(`${h[1]}();`);
30
+ }
31
+
32
+ return parts.join("\n");
7
33
  }
@@ -1,34 +1,46 @@
1
- export function parseVue(content: string) {
2
- const scriptMatches = [
3
- ...content.matchAll(/<script[^>]*>([\s\S]*?)<\/script>/g)
4
- ];
1
+ import path from "path";
5
2
 
6
- const script = scriptMatches.map(m => m[1]).join("\n");
3
+ export function parseVue(content: string, file: string) {
4
+ const parts: string[] = [];
7
5
 
8
- // template
9
- const templateMatch = content.match(/<template>([\s\S]*?)<\/template>/);
6
+ const scripts = content.matchAll(/<script([^>]*)>([\s\S]*?)<\/script>/g);
7
+
8
+ for (const m of scripts) {
9
+ const attrs = m[1];
10
+ const body = m[2];
11
+
12
+ // src
13
+ if (attrs.includes("src")) {
14
+ const src = attrs.match(/src=["'](.+?)["']/)?.[1];
15
+ if (!src) continue;
16
+
17
+ const resolved = src.startsWith("/")
18
+ ? path.resolve(process.cwd(), src.slice(1))
19
+ : path.resolve(path.dirname(file), src);
20
+
21
+ parts.push(`import "${resolved}"`);
22
+ continue;
23
+ }
24
+
25
+ // script setup
26
+ parts.push(body);
27
+ }
28
+
29
+ // TEMPLATE
30
+ const templateMatch = content.match(/<template[^>]*>([\s\S]*?)<\/template>/);
10
31
  let template = templateMatch?.[1] ?? "";
11
32
 
12
33
  template = template.replace(/<!--[\s\S]*?-->/g, "");
13
34
 
14
- // Vue → JSX
15
- template = template
16
- .replace(/\bclass=/g, "className=")
17
- .replace(/\bfor=/g, "htmlFor=")
18
- .replace(/@(\w+)=/g, (_, e) => {
19
- const name = e.charAt(0).toUpperCase() + e.slice(1);
20
- return `on${name}=`;
21
- })
22
- .replace(/v-if="[^"]+"/g, "")
23
- .replace(/v-for="[^"]+"/g, "");
24
-
25
- const jsx = `
26
- const __VUE_JSX__ = (
27
- <>
28
- ${template}
29
- </>
30
- );
31
- `;
32
-
33
- return script + "\n" + jsx;
35
+ // @click
36
+ for (const m of template.matchAll(/@[\w-]+="([^"]+)"/g)) {
37
+ parts.push(`${m[1]}();`);
38
+ }
39
+
40
+ // v-on
41
+ for (const m of template.matchAll(/v-on:[\w-]+="([^"]+)"/g)) {
42
+ parts.push(`${m[1]}();`);
43
+ }
44
+
45
+ return parts.join("\n");
34
46
  }
@@ -1,21 +1,18 @@
1
+ import path from "path";
1
2
  import { detectParser } from "./parsers/router";
2
- import { parseVue } from "./parsers/vue";
3
- import { parseSvelte } from "./parsers/svelte";
4
- import { parseAstro } from "./parsers/astro";
5
3
 
6
4
  export function processFile(file: string, content: string) {
7
- const parser = detectParser(file);
5
+ const abs = path.resolve(file);
8
6
 
9
- if (parser === "vue") content = parseVue(content);
10
- if (parser === "svelte") content = parseSvelte(content);
11
- if (parser === "astro") content = parseAstro(content);
7
+ const parser = detectParser(abs);
8
+ content = parser(content, abs);
12
9
 
13
- const virtualFile =
10
+ const isVirtual =
14
11
  file.endsWith(".vue") ||
15
12
  file.endsWith(".svelte") ||
16
- file.endsWith(".astro")
17
- ? file + ".tsx"
18
- : file;
13
+ file.endsWith(".astro");
14
+
15
+ const virtualFile = isVirtual ? abs + ".tsx" : abs;
19
16
 
20
17
  return { content, virtualFile };
21
18
  }