@lithent/lithent-template-vite 0.1.1 → 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/README.md +7 -3
- package/dist/index.mjs +86 -121
- package/dist/index.mjs.map +1 -1
- package/dist/plugin.d.cts +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/tests/plugin.test.d.cts +1 -0
- package/dist/tests/plugin.test.d.ts +1 -0
- package/package.json +7 -8
- package/src/plugin.ts +29 -31
package/README.md
CHANGED
|
@@ -16,12 +16,14 @@ conditional and iterative markup while compiling straight to `h()` calls.
|
|
|
16
16
|
- **Document pipeline** – scans entire source files, replaces Lithent markup
|
|
17
17
|
with generated `h()` calls, and forwards source maps downstream.
|
|
18
18
|
- **Custom extensions** – default support for `.ljsx` and `.ltsx`, with full
|
|
19
|
-
control over additional extensions and associated
|
|
19
|
+
control over additional extensions and associated script loaders.
|
|
20
20
|
- **HTML entry transform** – `<script type="module" src="*.ltsx">` tags are
|
|
21
21
|
automatically rewritten to inline imports so the browser receives valid JS.
|
|
22
22
|
- **Tooling-friendly** – exposes warnings, preserves source maps in production,
|
|
23
23
|
and keeps untouched code intact.
|
|
24
24
|
|
|
25
|
+
Requires Vite 8. Script transforms use Oxc; opt-in JSON/CSS loaders retain an explicit esbuild fallback.
|
|
26
|
+
|
|
25
27
|
## Installation
|
|
26
28
|
|
|
27
29
|
```bash
|
|
@@ -47,7 +49,9 @@ If you prefer a static HTML entry in development, the safest option is to inline
|
|
|
47
49
|
the import yourself so the browser receives JavaScript immediately:
|
|
48
50
|
|
|
49
51
|
```html
|
|
50
|
-
<script type="module">
|
|
52
|
+
<script type="module">
|
|
53
|
+
import '/src/dev/main.ltsx';
|
|
54
|
+
</script>
|
|
51
55
|
```
|
|
52
56
|
|
|
53
57
|
This pattern works in both dev and build modes and avoids relying on HTML entry
|
|
@@ -70,7 +74,7 @@ lithentTemplateVite({
|
|
|
70
74
|
- `extensions` (string[]) – list of file extensions to treat as Lithent
|
|
71
75
|
templates. Values are normalised (leading `.` is optional). Defaults to
|
|
72
76
|
`['.ljsx', '.ltsx']`.
|
|
73
|
-
- `extensionLoaders` (Record<string, LoaderValue>) – override the
|
|
77
|
+
- `extensionLoaders` (Record<string, LoaderValue>) – override the source loader
|
|
74
78
|
used for a given extension (`'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'css'`).
|
|
75
79
|
When omitted, the loader is inferred from the extension suffix (e.g. `.ltsx`
|
|
76
80
|
→ `'ts'`).
|
package/dist/index.mjs
CHANGED
|
@@ -1,122 +1,87 @@
|
|
|
1
|
-
import { readFile as
|
|
2
|
-
import
|
|
3
|
-
import { normalizePath as
|
|
4
|
-
import { transformDocument as
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
async load(t) {
|
|
85
|
-
const n = O(t, r);
|
|
86
|
-
if (!n)
|
|
87
|
-
return null;
|
|
88
|
-
const a = x(n, r);
|
|
89
|
-
if (!a)
|
|
90
|
-
return null;
|
|
91
|
-
this.addWatchFile(n);
|
|
92
|
-
const c = await v(n, "utf-8"), l = P(c, {
|
|
93
|
-
source: n,
|
|
94
|
-
generateSourceMap: (i == null ? void 0 : i.command) === "build"
|
|
95
|
-
}), o = this.warn ? this.warn.bind(this) : console.warn;
|
|
96
|
-
if (l.errors.length > 0)
|
|
97
|
-
for (const { error: u } of l.errors) {
|
|
98
|
-
const W = u.line || u.column ? ` (line ${u.line}, column ${u.column})` : "";
|
|
99
|
-
o(
|
|
100
|
-
`[@lithent/lithent-template-vite] Failed to compile template in ${n}${W}: ${u.message}`
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
const d = s[a] ?? y(a), f = l.transformed ? l.code : c, b = await A(
|
|
104
|
-
f,
|
|
105
|
-
n,
|
|
106
|
-
{
|
|
107
|
-
loader: d,
|
|
108
|
-
sourcemap: (i == null ? void 0 : i.command) === "build",
|
|
109
|
-
sourcefile: n
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
return {
|
|
113
|
-
code: b.code,
|
|
114
|
-
map: b.map ?? null
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}];
|
|
1
|
+
import { readFile as e } from "node:fs/promises";
|
|
2
|
+
import t from "node:path";
|
|
3
|
+
import { normalizePath as n, transformWithEsbuild as r, transformWithOxc as i } from "vite";
|
|
4
|
+
import { transformDocument as a } from "@lithent/lithent-template-parser";
|
|
5
|
+
// src/plugin.ts
|
|
6
|
+
var o = [".ljsx", ".ltsx"], s = (e) => e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), c = (e) => e.startsWith(".") ? e : `.${e}`, l = (e) => {
|
|
7
|
+
let t = (e && e.length > 0 ? e : Array.from(o)).map(c);
|
|
8
|
+
return Array.from(new Set(t));
|
|
9
|
+
}, u = (e) => e.endsWith("tsx") || e.endsWith("ts") ? "ts" : (e.endsWith("jsx"), "js"), d = (e, t) => e ? Array.isArray(e) ? e : [e] : t, f = (e, t) => e.some((e) => e.test(t)), p = (e, t) => {
|
|
10
|
+
let [r, i] = e.split("?", 2);
|
|
11
|
+
if (i) {
|
|
12
|
+
let e = new URLSearchParams(i).get(g);
|
|
13
|
+
if (e) return n(e);
|
|
14
|
+
}
|
|
15
|
+
return r && m(r, t) ? n(r) : null;
|
|
16
|
+
}, m = (e, t) => t.find((t) => e.endsWith(t)) ?? null, h = (e, t) => {
|
|
17
|
+
let n = new Set(e ?? []);
|
|
18
|
+
for (let e of t) n.add(e);
|
|
19
|
+
return Array.from(n);
|
|
20
|
+
}, g = "lithent:original";
|
|
21
|
+
function _(o = {}) {
|
|
22
|
+
let c = l(o.extensions), _ = c.reduce((e, t) => {
|
|
23
|
+
var n;
|
|
24
|
+
return e[t] = ((n = o.extensionLoaders) == null ? void 0 : n[t]) ?? u(t), e;
|
|
25
|
+
}, {}), v = Object.fromEntries(Object.entries(_).map(([e, t]) => [e, t === "ts" ? "tsx" : t === "js" ? "jsx" : t])), y = c.map((e) => RegExp(`${s(e)}$`)), b = d(o.include, y), x, S = (e) => `${e}?${new URLSearchParams({ [g]: e }).toString()}`;
|
|
26
|
+
return [{
|
|
27
|
+
name: "lithent:template-vite",
|
|
28
|
+
enforce: "pre",
|
|
29
|
+
config(e) {
|
|
30
|
+
var t, n, r, i;
|
|
31
|
+
return {
|
|
32
|
+
resolve: { extensions: h((t = e.resolve) == null ? void 0 : t.extensions, c) },
|
|
33
|
+
optimizeDeps: {
|
|
34
|
+
extensions: h((n = e.optimizeDeps) == null ? void 0 : n.extensions, c),
|
|
35
|
+
rolldownOptions: {
|
|
36
|
+
...(r = e.optimizeDeps) == null ? void 0 : r.rolldownOptions,
|
|
37
|
+
moduleTypes: {
|
|
38
|
+
...(i = e.optimizeDeps) == null || (i = i.rolldownOptions) == null ? void 0 : i.moduleTypes,
|
|
39
|
+
...v
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
configResolved(e) {
|
|
46
|
+
x = e;
|
|
47
|
+
},
|
|
48
|
+
async resolveId(e, r, i) {
|
|
49
|
+
if (!m(e, c)) return null;
|
|
50
|
+
let a = (x == null ? void 0 : x.root) ?? process.cwd(), o;
|
|
51
|
+
if (typeof this.resolve == "function") {
|
|
52
|
+
let t = await this.resolve(e, r, {
|
|
53
|
+
skipSelf: !0,
|
|
54
|
+
...i
|
|
55
|
+
});
|
|
56
|
+
t != null && t.id && (o = t.id);
|
|
57
|
+
}
|
|
58
|
+
return o || (o = t.isAbsolute(e) ? e : e.startsWith("/") ? t.join(a, e.slice(1)) : r && (e.startsWith("./") || e.startsWith("../")) ? t.resolve(t.dirname(r), e) : t.resolve(a, e)), o = n(o), f(b, o) ? S(o) : null;
|
|
59
|
+
},
|
|
60
|
+
async load(t) {
|
|
61
|
+
let n = p(t, c);
|
|
62
|
+
if (!n) return null;
|
|
63
|
+
let o = m(n, c);
|
|
64
|
+
if (!o) return null;
|
|
65
|
+
this.addWatchFile(n);
|
|
66
|
+
let s = await e(n, "utf-8"), l = a(s, {
|
|
67
|
+
source: n,
|
|
68
|
+
generateSourceMap: (x == null ? void 0 : x.command) === "build"
|
|
69
|
+
}), d = this.warn ? this.warn.bind(this) : console.warn;
|
|
70
|
+
if (l.errors.length > 0) for (let { error: e } of l.errors) d(`[@lithent/lithent-template-vite] Failed to compile template in ${n}${e.line || e.column ? ` (line ${e.line}, column ${e.column})` : ""}: ${e.message}`);
|
|
71
|
+
let f = _[o] ?? u(o), h = l.transformed ? l.code : s, g = f === "json" || f === "css" ? await r(h, n, {
|
|
72
|
+
loader: f,
|
|
73
|
+
sourcemap: (x == null ? void 0 : x.command) === "build"
|
|
74
|
+
}) : await i(h, n, {
|
|
75
|
+
lang: f,
|
|
76
|
+
sourcemap: (x == null ? void 0 : x.command) === "build"
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
code: g.code,
|
|
80
|
+
map: g.map ?? null
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}];
|
|
118
84
|
}
|
|
119
|
-
export {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
//# sourceMappingURL=index.mjs.map
|
|
85
|
+
export { _ as default };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Plugin, PluginOption, ResolvedConfig, UserConfig } from 'vite';\nimport { normalizePath, transformWithEsbuild } from 'vite';\nimport { transformDocument } from '@lithent/lithent-template-parser';\n\ntype LoaderValue = 'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'css';\ntype LoaderMap = Record<string, LoaderValue>;\n\nexport interface LithentTemplateViteOptions {\n include?: RegExp | RegExp[];\n extensions?: string[];\n extensionLoaders?: Record<string, LoaderValue>;\n}\n\nconst DEFAULT_EXTENSIONS = ['.ljsx', '.ltsx'] as const;\n\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst normalizeExtension = (ext: string): string =>\n ext.startsWith('.') ? ext : `.${ext}`;\n\nconst resolveExtensions = (extensions?: string[]): string[] => {\n const base =\n extensions && extensions.length > 0\n ? extensions\n : Array.from(DEFAULT_EXTENSIONS);\n const normalized = base.map(normalizeExtension);\n return Array.from(new Set(normalized));\n};\n\nconst inferLoader = (ext: string): LoaderValue => {\n if (ext.endsWith('tsx') || ext.endsWith('ts')) {\n return 'ts';\n }\n if (ext.endsWith('jsx')) {\n return 'js';\n }\n return 'js';\n};\n\nconst toRegExpArray = (\n value: RegExp | RegExp[] | undefined,\n fallback: RegExp[]\n): RegExp[] => {\n if (!value) {\n return fallback;\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst shouldProcess = (patterns: RegExp[], filePath: string): boolean => {\n return patterns.some(pattern => pattern.test(filePath));\n};\n\nconst extractOriginalPath = (\n id: string,\n extensions: string[]\n): string | null => {\n const [filepath, query] = id.split('?', 2);\n if (query) {\n const params = new URLSearchParams(query);\n const original = params.get(VIRTUAL_QUERY);\n if (original) {\n return normalizePath(original);\n }\n }\n if (filepath && matchExtension(filepath, extensions)) {\n return normalizePath(filepath);\n }\n return null;\n};\n\nconst matchExtension = (\n filePath: string,\n extensions: string[]\n): string | null => {\n return extensions.find(ext => filePath.endsWith(ext)) ?? null;\n};\n\nconst mergeExtensions = (\n original: string[] | undefined,\n additions: readonly string[]\n): string[] => {\n const set = new Set(original ?? []);\n for (const ext of additions) {\n set.add(ext);\n }\n return Array.from(set);\n};\n\nconst mergeLoaderMap = (\n original: LoaderMap | undefined,\n additions: LoaderMap\n): LoaderMap => {\n return {\n ...(original ?? {}),\n ...additions,\n };\n};\n\nconst VIRTUAL_QUERY = 'lithent:original';\n\nexport function lithentTemplateVite(\n options: LithentTemplateViteOptions = {}\n): PluginOption {\n const extensions = resolveExtensions(options.extensions);\n const extensionLoaders: LoaderMap = extensions.reduce((acc, ext) => {\n const loader = options.extensionLoaders?.[ext] ?? inferLoader(ext);\n acc[ext] = loader;\n return acc;\n }, {} as LoaderMap);\n const defaultInclude = extensions.map(\n ext => new RegExp(`${escapeRegExp(ext)}$`)\n );\n const includePatterns = toRegExpArray(options.include, defaultInclude);\n let config: ResolvedConfig | undefined;\n\n const createVirtualId = (originalPath: string): string => {\n const query = new URLSearchParams({\n [VIRTUAL_QUERY]: originalPath,\n });\n return `${originalPath}?${query.toString()}`;\n };\n\n const templatePlugin: Plugin = {\n name: 'lithent:template-vite',\n enforce: 'pre',\n config(userConfig: UserConfig) {\n return {\n resolve: {\n extensions: mergeExtensions(\n userConfig.resolve?.extensions,\n extensions\n ),\n },\n optimizeDeps: {\n extensions: mergeExtensions(\n userConfig.optimizeDeps?.extensions,\n extensions\n ),\n esbuildOptions: {\n ...(userConfig.optimizeDeps?.esbuildOptions ?? {}),\n loader: mergeLoaderMap(\n typeof userConfig.optimizeDeps?.esbuildOptions?.loader ===\n 'object'\n ? (userConfig.optimizeDeps?.esbuildOptions?.loader as LoaderMap)\n : undefined,\n extensionLoaders\n ),\n },\n },\n };\n },\n configResolved(resolved) {\n config = resolved;\n },\n async resolveId(source, importer, options) {\n const ext = matchExtension(source, extensions);\n if (!ext) {\n return null;\n }\n\n const rootDir = config?.root ?? process.cwd();\n let resolvedPath: string | undefined;\n\n if (typeof this.resolve === 'function') {\n const resolved = await this.resolve(source, importer, {\n skipSelf: true,\n ...options,\n });\n if (resolved?.id) {\n resolvedPath = resolved.id;\n }\n }\n\n if (!resolvedPath) {\n if (path.isAbsolute(source)) {\n resolvedPath = source;\n } else if (source.startsWith('/')) {\n resolvedPath = path.join(rootDir, source.slice(1));\n } else if (\n importer &&\n (source.startsWith('./') || source.startsWith('../'))\n ) {\n resolvedPath = path.resolve(path.dirname(importer), source);\n } else {\n resolvedPath = path.resolve(rootDir, source);\n }\n }\n\n resolvedPath = normalizePath(resolvedPath);\n\n if (!shouldProcess(includePatterns, resolvedPath)) {\n return null;\n }\n\n return createVirtualId(resolvedPath);\n },\n async load(id) {\n const originalPath = extractOriginalPath(id, extensions);\n if (!originalPath) {\n return null;\n }\n\n const ext = matchExtension(originalPath, extensions);\n if (!ext) {\n return null;\n }\n\n this.addWatchFile(originalPath);\n\n const raw = await readFile(originalPath, 'utf-8');\n const result = transformDocument(raw, {\n source: originalPath,\n generateSourceMap: config?.command === 'build',\n });\n\n const warn = this.warn ? this.warn.bind(this) : console.warn;\n if (result.errors.length > 0) {\n for (const { error } of result.errors) {\n const location =\n error.line || error.column\n ? ` (line ${error.line}, column ${error.column})`\n : '';\n warn(\n `[@lithent/lithent-template-vite] Failed to compile template in ${originalPath}${location}: ${error.message}`\n );\n }\n }\n\n const loader = extensionLoaders[ext] ?? inferLoader(ext);\n const transformedCode = result.transformed ? result.code : raw;\n const esbuildResult = await transformWithEsbuild(\n transformedCode,\n originalPath,\n {\n loader,\n sourcemap: config?.command === 'build',\n sourcefile: originalPath,\n }\n );\n\n return {\n code: esbuildResult.code,\n map: esbuildResult.map ?? null,\n };\n },\n };\n\n return [templatePlugin];\n}\n\nexport default lithentTemplateVite;\n"],"names":["DEFAULT_EXTENSIONS","escapeRegExp","value","normalizeExtension","ext","resolveExtensions","extensions","normalized","inferLoader","toRegExpArray","fallback","shouldProcess","patterns","filePath","pattern","extractOriginalPath","id","filepath","query","original","VIRTUAL_QUERY","normalizePath","matchExtension","mergeExtensions","additions","set","mergeLoaderMap","lithentTemplateVite","options","extensionLoaders","acc","loader","_a","defaultInclude","includePatterns","config","createVirtualId","originalPath","userConfig","_b","_c","_e","_d","_g","_f","resolved","source","importer","rootDir","resolvedPath","path","raw","readFile","result","transformDocument","warn","error","location","transformedCode","esbuildResult","transformWithEsbuild"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["path","DEFAULT_EXTENSIONS","escapeRegExp","value","normalizeExtension","ext","resolveExtensions","normalized","extensions","inferLoader","toRegExpArray","fallback","shouldProcess","patterns","pattern","filePath","extractOriginalPath","filepath","query","id","original","VIRTUAL_QUERY","normalizePath","matchExtension","mergeExtensions","set","additions","lithentTemplateVite","options","extensionLoaders","_options$extensionLoa","acc","scanLoaders","loader","defaultInclude","includePatterns","config","createVirtualId","originalPath","_userConfig$resolve","_userConfig$optimizeD","_userConfig$optimizeD2","_userConfig$optimizeD3","userConfig","resolved","source","rootDir","resolvedPath","importer","raw","readFile","result","transformDocument","warn","error","transformedCode","resultCode","transformWithEsbuild","transformWithOxc"],"sources":["../src/plugin.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Plugin, PluginOption, ResolvedConfig, UserConfig } from 'vite';\nimport { normalizePath, transformWithEsbuild, transformWithOxc } from 'vite';\nimport { transformDocument } from '@lithent/lithent-template-parser';\n\ntype LoaderValue = 'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'css';\ntype LoaderMap = Record<string, LoaderValue>;\n\nexport interface LithentTemplateViteOptions {\n include?: RegExp | RegExp[];\n extensions?: string[];\n extensionLoaders?: Record<string, LoaderValue>;\n}\n\nconst DEFAULT_EXTENSIONS = ['.ljsx', '.ltsx'] as const;\n\nconst escapeRegExp = (value: string): string =>\n value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\nconst normalizeExtension = (ext: string): string =>\n ext.startsWith('.') ? ext : `.${ext}`;\n\nconst resolveExtensions = (extensions?: string[]): string[] => {\n const base =\n extensions && extensions.length > 0\n ? extensions\n : Array.from(DEFAULT_EXTENSIONS);\n const normalized = base.map(normalizeExtension);\n return Array.from(new Set(normalized));\n};\n\nconst inferLoader = (ext: string): LoaderValue => {\n if (ext.endsWith('tsx') || ext.endsWith('ts')) {\n return 'ts';\n }\n if (ext.endsWith('jsx')) {\n return 'js';\n }\n return 'js';\n};\n\nconst toRegExpArray = (\n value: RegExp | RegExp[] | undefined,\n fallback: RegExp[]\n): RegExp[] => {\n if (!value) {\n return fallback;\n }\n return Array.isArray(value) ? value : [value];\n};\n\nconst shouldProcess = (patterns: RegExp[], filePath: string): boolean => {\n return patterns.some(pattern => pattern.test(filePath));\n};\n\nconst extractOriginalPath = (\n id: string,\n extensions: string[]\n): string | null => {\n const [filepath, query] = id.split('?', 2);\n if (query) {\n const params = new URLSearchParams(query);\n const original = params.get(VIRTUAL_QUERY);\n if (original) {\n return normalizePath(original);\n }\n }\n if (filepath && matchExtension(filepath, extensions)) {\n return normalizePath(filepath);\n }\n return null;\n};\n\nconst matchExtension = (\n filePath: string,\n extensions: string[]\n): string | null => {\n return extensions.find(ext => filePath.endsWith(ext)) ?? null;\n};\n\nconst mergeExtensions = (\n original: string[] | undefined,\n additions: readonly string[]\n): string[] => {\n const set = new Set(original ?? []);\n for (const ext of additions) {\n set.add(ext);\n }\n return Array.from(set);\n};\n\nconst VIRTUAL_QUERY = 'lithent:original';\n\nexport function lithentTemplateVite(\n options: LithentTemplateViteOptions = {}\n): PluginOption {\n const extensions = resolveExtensions(options.extensions);\n const extensionLoaders: LoaderMap = extensions.reduce((acc, ext) => {\n const loader = options.extensionLoaders?.[ext] ?? inferLoader(ext);\n acc[ext] = loader;\n return acc;\n }, {} as LoaderMap);\n // The optimizer scans raw templates before our load hook compiles markup.\n // Its parser must accept JSX even when the compiled document uses plain TS.\n const scanLoaders: LoaderMap = Object.fromEntries(\n Object.entries(extensionLoaders).map(([ext, loader]) => [\n ext,\n loader === 'ts' ? 'tsx' : loader === 'js' ? 'jsx' : loader,\n ])\n );\n const defaultInclude = extensions.map(\n ext => new RegExp(`${escapeRegExp(ext)}$`)\n );\n const includePatterns = toRegExpArray(options.include, defaultInclude);\n let config: ResolvedConfig | undefined;\n\n const createVirtualId = (originalPath: string): string => {\n const query = new URLSearchParams({\n [VIRTUAL_QUERY]: originalPath,\n });\n return `${originalPath}?${query.toString()}`;\n };\n\n const templatePlugin: Plugin = {\n name: 'lithent:template-vite',\n enforce: 'pre',\n config(userConfig: UserConfig) {\n return {\n resolve: {\n extensions: mergeExtensions(\n userConfig.resolve?.extensions,\n extensions\n ),\n },\n optimizeDeps: {\n extensions: mergeExtensions(\n userConfig.optimizeDeps?.extensions,\n extensions\n ),\n rolldownOptions: {\n ...userConfig.optimizeDeps?.rolldownOptions,\n moduleTypes: {\n ...userConfig.optimizeDeps?.rolldownOptions?.moduleTypes,\n ...scanLoaders,\n },\n },\n },\n };\n },\n configResolved(resolved) {\n config = resolved;\n },\n async resolveId(source, importer, options) {\n const ext = matchExtension(source, extensions);\n if (!ext) {\n return null;\n }\n\n const rootDir = config?.root ?? process.cwd();\n let resolvedPath: string | undefined;\n\n if (typeof this.resolve === 'function') {\n const resolved = await this.resolve(source, importer, {\n skipSelf: true,\n ...options,\n });\n if (resolved?.id) {\n resolvedPath = resolved.id;\n }\n }\n\n if (!resolvedPath) {\n if (path.isAbsolute(source)) {\n resolvedPath = source;\n } else if (source.startsWith('/')) {\n resolvedPath = path.join(rootDir, source.slice(1));\n } else if (\n importer &&\n (source.startsWith('./') || source.startsWith('../'))\n ) {\n resolvedPath = path.resolve(path.dirname(importer), source);\n } else {\n resolvedPath = path.resolve(rootDir, source);\n }\n }\n\n resolvedPath = normalizePath(resolvedPath);\n\n if (!shouldProcess(includePatterns, resolvedPath)) {\n return null;\n }\n\n return createVirtualId(resolvedPath);\n },\n async load(id) {\n const originalPath = extractOriginalPath(id, extensions);\n if (!originalPath) {\n return null;\n }\n\n const ext = matchExtension(originalPath, extensions);\n if (!ext) {\n return null;\n }\n\n this.addWatchFile(originalPath);\n\n const raw = await readFile(originalPath, 'utf-8');\n const result = transformDocument(raw, {\n source: originalPath,\n generateSourceMap: config?.command === 'build',\n });\n\n const warn = this.warn ? this.warn.bind(this) : console.warn;\n if (result.errors.length > 0) {\n for (const { error } of result.errors) {\n const location =\n error.line || error.column\n ? ` (line ${error.line}, column ${error.column})`\n : '';\n warn(\n `[@lithent/lithent-template-vite] Failed to compile template in ${originalPath}${location}: ${error.message}`\n );\n }\n }\n\n const loader = extensionLoaders[ext] ?? inferLoader(ext);\n const transformedCode = result.transformed ? result.code : raw;\n // Oxc handles the script loaders. Preserve the existing opt-in JSON/CSS\n // loaders through esbuild, which is an explicit plugin dependency.\n const resultCode =\n loader === 'json' || loader === 'css'\n ? await transformWithEsbuild(transformedCode, originalPath, {\n loader,\n sourcemap: config?.command === 'build',\n })\n : await transformWithOxc(transformedCode, originalPath, {\n lang: loader,\n sourcemap: config?.command === 'build',\n });\n\n return {\n code: resultCode.code,\n map: resultCode.map ?? null,\n };\n },\n };\n\n return [templatePlugin];\n}\n\nexport default lithentTemplateVite;\n"],"mappings":"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"}
|
package/dist/plugin.d.cts
CHANGED
package/dist/plugin.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@lithent/lithent-template-vite",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
5
5
|
"description": "Vite plugin that compiles Lithent’s JSX-like template syntax into h() calls.",
|
|
6
6
|
"main": "./dist/index.mjs",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -9,14 +9,16 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.mjs"
|
|
12
|
+
"import": "./dist/index.mjs",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"dependencies": {
|
|
16
|
-
"@lithent/lithent-template-parser": "0.1.
|
|
17
|
+
"@lithent/lithent-template-parser": "0.1.3",
|
|
18
|
+
"esbuild": "^0.28.2"
|
|
17
19
|
},
|
|
18
20
|
"devDependencies": {
|
|
19
|
-
"lithent": "1.25.
|
|
21
|
+
"lithent": "1.25.7"
|
|
20
22
|
},
|
|
21
23
|
"keywords": [
|
|
22
24
|
"lithent",
|
|
@@ -31,15 +33,12 @@
|
|
|
31
33
|
"url": "https://github.com/superlucky84/lithent.git"
|
|
32
34
|
},
|
|
33
35
|
"peerDependencies": {
|
|
34
|
-
"vite": "^
|
|
36
|
+
"vite": "^8.0.0"
|
|
35
37
|
},
|
|
36
38
|
"files": [
|
|
37
39
|
"dist",
|
|
38
40
|
"src"
|
|
39
41
|
],
|
|
40
|
-
"volta": {
|
|
41
|
-
"node": "20.3.0"
|
|
42
|
-
},
|
|
43
42
|
"scripts": {
|
|
44
43
|
"dev": "vite --config vite.config.plugin.ts",
|
|
45
44
|
"dev:lib": "vite",
|
package/src/plugin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import type { Plugin, PluginOption, ResolvedConfig, UserConfig } from 'vite';
|
|
4
|
-
import { normalizePath, transformWithEsbuild } from 'vite';
|
|
4
|
+
import { normalizePath, transformWithEsbuild, transformWithOxc } from 'vite';
|
|
5
5
|
import { transformDocument } from '@lithent/lithent-template-parser';
|
|
6
6
|
|
|
7
7
|
type LoaderValue = 'js' | 'jsx' | 'ts' | 'tsx' | 'json' | 'css';
|
|
@@ -90,16 +90,6 @@ const mergeExtensions = (
|
|
|
90
90
|
return Array.from(set);
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
const mergeLoaderMap = (
|
|
94
|
-
original: LoaderMap | undefined,
|
|
95
|
-
additions: LoaderMap
|
|
96
|
-
): LoaderMap => {
|
|
97
|
-
return {
|
|
98
|
-
...(original ?? {}),
|
|
99
|
-
...additions,
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
|
|
103
93
|
const VIRTUAL_QUERY = 'lithent:original';
|
|
104
94
|
|
|
105
95
|
export function lithentTemplateVite(
|
|
@@ -111,6 +101,14 @@ export function lithentTemplateVite(
|
|
|
111
101
|
acc[ext] = loader;
|
|
112
102
|
return acc;
|
|
113
103
|
}, {} as LoaderMap);
|
|
104
|
+
// The optimizer scans raw templates before our load hook compiles markup.
|
|
105
|
+
// Its parser must accept JSX even when the compiled document uses plain TS.
|
|
106
|
+
const scanLoaders: LoaderMap = Object.fromEntries(
|
|
107
|
+
Object.entries(extensionLoaders).map(([ext, loader]) => [
|
|
108
|
+
ext,
|
|
109
|
+
loader === 'ts' ? 'tsx' : loader === 'js' ? 'jsx' : loader,
|
|
110
|
+
])
|
|
111
|
+
);
|
|
114
112
|
const defaultInclude = extensions.map(
|
|
115
113
|
ext => new RegExp(`${escapeRegExp(ext)}$`)
|
|
116
114
|
);
|
|
@@ -140,15 +138,12 @@ export function lithentTemplateVite(
|
|
|
140
138
|
userConfig.optimizeDeps?.extensions,
|
|
141
139
|
extensions
|
|
142
140
|
),
|
|
143
|
-
|
|
144
|
-
...
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
: undefined,
|
|
150
|
-
extensionLoaders
|
|
151
|
-
),
|
|
141
|
+
rolldownOptions: {
|
|
142
|
+
...userConfig.optimizeDeps?.rolldownOptions,
|
|
143
|
+
moduleTypes: {
|
|
144
|
+
...userConfig.optimizeDeps?.rolldownOptions?.moduleTypes,
|
|
145
|
+
...scanLoaders,
|
|
146
|
+
},
|
|
152
147
|
},
|
|
153
148
|
},
|
|
154
149
|
};
|
|
@@ -232,19 +227,22 @@ export function lithentTemplateVite(
|
|
|
232
227
|
|
|
233
228
|
const loader = extensionLoaders[ext] ?? inferLoader(ext);
|
|
234
229
|
const transformedCode = result.transformed ? result.code : raw;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
230
|
+
// Oxc handles the script loaders. Preserve the existing opt-in JSON/CSS
|
|
231
|
+
// loaders through esbuild, which is an explicit plugin dependency.
|
|
232
|
+
const resultCode =
|
|
233
|
+
loader === 'json' || loader === 'css'
|
|
234
|
+
? await transformWithEsbuild(transformedCode, originalPath, {
|
|
235
|
+
loader,
|
|
236
|
+
sourcemap: config?.command === 'build',
|
|
237
|
+
})
|
|
238
|
+
: await transformWithOxc(transformedCode, originalPath, {
|
|
239
|
+
lang: loader,
|
|
240
|
+
sourcemap: config?.command === 'build',
|
|
241
|
+
});
|
|
244
242
|
|
|
245
243
|
return {
|
|
246
|
-
code:
|
|
247
|
-
map:
|
|
244
|
+
code: resultCode.code,
|
|
245
|
+
map: resultCode.map ?? null,
|
|
248
246
|
};
|
|
249
247
|
},
|
|
250
248
|
};
|