diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..a4e7cd5
Binary files /dev/null and b/.DS_Store differ
diff --git a/examples/.DS_Store b/examples/.DS_Store
new file mode 100644
index 0000000..4a39421
Binary files /dev/null and b/examples/.DS_Store differ
diff --git a/examples/rollup/rollup.config.js b/examples/rollup/rollup.config.js
index 7ba7ef4..f1f85ee 100644
--- a/examples/rollup/rollup.config.js
+++ b/examples/rollup/rollup.config.js
@@ -26,6 +26,7 @@ export default {
format: "esm",
},
plugins: [
+ VueSource({}),
vue({
exposeFilename: true,
}),
@@ -46,7 +47,6 @@ export default {
svg({
base64: true,
}),
- VueSource({}),
liveServer({
port: 3000,
wait: 1000,
diff --git a/examples/vite/src/App.vue b/examples/vite/src/App.vue
index dc5a801..6f2ebb1 100644
--- a/examples/vite/src/App.vue
+++ b/examples/vite/src/App.vue
@@ -1,4 +1,4 @@
-
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 0000000..db74382
Binary files /dev/null and b/src/.DS_Store differ
diff --git a/src/core/constants.ts b/src/core/constants.ts
index 7445e99..db59882 100644
--- a/src/core/constants.ts
+++ b/src/core/constants.ts
@@ -8,3 +8,5 @@ export const ElementTypes = {
ELEMENT: 0,
COMPONENT: 1,
};
+
+export const TagTypes = [ElementTypes.ELEMENT, ElementTypes.COMPONENT];
diff --git a/src/core/index.ts b/src/core/index.ts
index 23bf330..c33917c 100644
--- a/src/core/index.ts
+++ b/src/core/index.ts
@@ -1,51 +1,32 @@
-import { relative } from "path";
import type { UnpluginFactory } from "unplugin";
import { createUnplugin } from "unplugin";
-import { parse, transform } from "@vue/compiler-dom";
-import MagicString from "magic-string";
import type { Options } from "../types";
-import { ElementTypes, NodeTypes, TRACE_ID } from "./constants";
+import { parse_ID } from "./parse_ID";
+import { transform_SFC } from "./transform_SFC";
+// import { transform_JSX } from "./transform_JSX";
-const filterRE = /.(vue|jsx|tsx)$/;
-const TagTypes = [ElementTypes.ELEMENT, ElementTypes.COMPONENT];
+const includeRE = /.((vue\?vue)|(vue|jsx|tsx)$)/;
export const unpluginFactory: UnpluginFactory = (options = {}) => {
- const { rootDir = process.cwd() } = options;
-
if (process.env.NODE_ENV !== "development") {
return {
name: "unplugin-vue-source",
};
}
+ const { rootDir = process.cwd() } = options;
+
return {
name: "unplugin-vue-source",
enforce: "pre",
transformInclude(id) {
- return filterRE.test(id);
+ return includeRE.test(id);
},
- transform(raw, id) {
- const relativePath = `/${relative(rootDir, id)}`;
-
- const s = new MagicString(raw);
- transform(parse(raw), {
- nodeTransforms: [
- (node) => {
- if (
- node.type === NodeTypes.ELEMENT &&
- TagTypes.includes(node.tagType as any)
- ) {
- const { line, column, offset } = node.loc.start;
- const startIndex = offset + node.tag.length + 1;
- s.prependLeft(
- startIndex,
- ` ${TRACE_ID}="${relativePath}:${line}:${column}"`
- );
- }
- },
- ],
- });
- return s.toString();
+ transform(code, id) {
+ const { filename, query } = parse_ID(id, rootDir);
+ if (!query.type || query.type === "template") {
+ return transform_SFC(filename, code);
+ }
},
};
};
diff --git a/src/core/parse_ID.ts b/src/core/parse_ID.ts
new file mode 100644
index 0000000..9cf71ef
--- /dev/null
+++ b/src/core/parse_ID.ts
@@ -0,0 +1,29 @@
+import { extname } from "path";
+
+export interface VueQuery {
+ vue?: boolean;
+ src?: string;
+ type?: "script" | "template" | "style" | "custom";
+ lang?: string;
+}
+
+export function parse_ID(
+ id: string,
+ rootDir: string
+): {
+ filename: string;
+ ext: string;
+ query: VueQuery;
+} {
+ const [filename, rawQuery] = id.split(`?`, 2);
+ const query = Object.fromEntries(new URLSearchParams(rawQuery)) as VueQuery;
+ if (query.vue != null) {
+ query.vue = true;
+ }
+
+ return {
+ filename: filename.replace(rootDir, ""),
+ ext: extname(filename).slice(1),
+ query,
+ };
+}
diff --git a/src/core/transform_JSX.ts b/src/core/transform_JSX.ts
new file mode 100644
index 0000000..353a6aa
--- /dev/null
+++ b/src/core/transform_JSX.ts
@@ -0,0 +1,3 @@
+export function transform_JSX(filename: string, code: string, tsx: boolean) {
+ return undefined;
+}
diff --git a/src/core/transform_SFC.ts b/src/core/transform_SFC.ts
new file mode 100644
index 0000000..deba233
--- /dev/null
+++ b/src/core/transform_SFC.ts
@@ -0,0 +1,28 @@
+import { parse, transform } from "@vue/compiler-dom";
+import MagicString from "magic-string";
+import { NodeTypes, TRACE_ID, TagTypes } from "./constants";
+
+export function transform_SFC(filename: string, code: string) {
+ const s = new MagicString(code);
+
+ const ast = parse(code);
+ transform(ast, {
+ nodeTransforms: [
+ (node) => {
+ if (
+ node.type === NodeTypes.ELEMENT &&
+ TagTypes.includes(node.tagType as any)
+ ) {
+ const { line, column, offset } = node.loc.start;
+ const startIndex = offset + node.tag.length + 1;
+ s.prependLeft(
+ startIndex,
+ ` ${TRACE_ID}="${filename}:${line}:${column}"`
+ );
+ }
+ },
+ ],
+ });
+
+ return s.toString();
+}