@tishlang/vite-plugin-tish 2.38.0 → 2.43.8
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/index.js +88 -19
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Dev compiles request a source map (`tish compile-module --source-map`) so Vite's error overlay
|
|
6
6
|
// and the browser debugger resolve back to the original `.tish`.
|
|
7
|
+
//
|
|
8
|
+
// Platform/surface cascade (RN-style `Button.macos.tish` / `.web.tish` / …) is owned by the `tish`
|
|
9
|
+
// CLI (`tish resolve-id`); this plugin must not reimplement those rules.
|
|
7
10
|
|
|
8
11
|
import { execFileSync } from "node:child_process";
|
|
9
12
|
import { existsSync } from "node:fs";
|
|
@@ -17,14 +20,70 @@ const TISH_EXT = ".tish";
|
|
|
17
20
|
* @param {string} [opts.projectRoot] Root for resolving bare specifiers / node_modules (default: Vite root).
|
|
18
21
|
* @param {"hmr"|"full-reload"} [opts.mode] `hmr` (default) hot-swaps modules; `full-reload` reloads the
|
|
19
22
|
* page on any `.tish` change (the documented fallback for `--target bytecode` apps).
|
|
23
|
+
* @param {string} [opts.platform] Platform token for resolve cascade (`macos`, `ios`, `web`, …).
|
|
24
|
+
* @param {string} [opts.surface] Surface token (`native`, `webview`, `web`). Defaults from
|
|
25
|
+
* `TISH_PLATFORM` / `TISH_SURFACE` when unset.
|
|
20
26
|
*/
|
|
21
27
|
export default function tishPlugin(opts = {}) {
|
|
22
28
|
const tishPath = opts.tishPath ?? process.env.TISH_PATH ?? "tish";
|
|
23
29
|
const mode = opts.mode ?? "hmr";
|
|
30
|
+
const platform = opts.platform ?? process.env.TISH_PLATFORM;
|
|
31
|
+
const surface = opts.surface ?? process.env.TISH_SURFACE;
|
|
24
32
|
let projectRoot = opts.projectRoot;
|
|
33
|
+
/** @type {boolean|null} */
|
|
34
|
+
let supportsPlatformFlags = null;
|
|
35
|
+
|
|
36
|
+
function envForChild() {
|
|
37
|
+
const env = { ...process.env };
|
|
38
|
+
if (platform) env.TISH_PLATFORM = platform;
|
|
39
|
+
if (surface) env.TISH_SURFACE = surface;
|
|
40
|
+
return env;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function detectPlatformFlags() {
|
|
44
|
+
if (supportsPlatformFlags !== null) return supportsPlatformFlags;
|
|
45
|
+
try {
|
|
46
|
+
const help = execFileSync(tishPath, ["compile-module", "--help"], {
|
|
47
|
+
encoding: "utf8",
|
|
48
|
+
env: envForChild(),
|
|
49
|
+
});
|
|
50
|
+
supportsPlatformFlags =
|
|
51
|
+
help.includes("--platform") && help.includes("--surface");
|
|
52
|
+
} catch {
|
|
53
|
+
supportsPlatformFlags = false;
|
|
54
|
+
}
|
|
55
|
+
return supportsPlatformFlags;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function platformArgs() {
|
|
59
|
+
if (!detectPlatformFlags()) return [];
|
|
60
|
+
const args = [];
|
|
61
|
+
if (platform) args.push("--platform", platform);
|
|
62
|
+
if (surface) args.push("--surface", surface);
|
|
63
|
+
return args;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function runTish(args, maxBuffer = 1024 * 1024) {
|
|
67
|
+
return execFileSync(tishPath, args, {
|
|
68
|
+
encoding: "utf8",
|
|
69
|
+
maxBuffer,
|
|
70
|
+
env: envForChild(),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Resolve relative imports through `tish resolve-id` (same cascade as compile). */
|
|
75
|
+
function resolveTishId(source, importer) {
|
|
76
|
+
if (!detectPlatformFlags()) return null;
|
|
77
|
+
const args = ["resolve-id", source, ...platformArgs()];
|
|
78
|
+
if (importer) args.push("--importer", importer.split("?")[0]);
|
|
79
|
+
try {
|
|
80
|
+
const out = runTish(args).trim();
|
|
81
|
+
return out || null;
|
|
82
|
+
} catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
25
86
|
|
|
26
|
-
// Compile a single `.tish` file to one ES module. In `hmr` mode we request a source map and parse
|
|
27
|
-
// the `{ js, map }` envelope; otherwise we take raw JS on stdout.
|
|
28
87
|
function compileModule(file) {
|
|
29
88
|
const args = [
|
|
30
89
|
"compile-module",
|
|
@@ -34,18 +93,29 @@ export default function tishPlugin(opts = {}) {
|
|
|
34
93
|
"--format",
|
|
35
94
|
"esm",
|
|
36
95
|
"--vite-dev",
|
|
96
|
+
...platformArgs(),
|
|
37
97
|
];
|
|
38
98
|
args.push(mode === "hmr" ? "--source-map" : "--no-source-map");
|
|
39
99
|
if (projectRoot) args.push("--project-root", projectRoot);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return { code:
|
|
100
|
+
try {
|
|
101
|
+
const stdout = runTish(args, 64 * 1024 * 1024);
|
|
102
|
+
if (mode === "hmr") {
|
|
103
|
+
const { js, map } = JSON.parse(stdout);
|
|
104
|
+
return { code: js, map };
|
|
105
|
+
}
|
|
106
|
+
return { code: stdout, map: null };
|
|
107
|
+
} catch (err) {
|
|
108
|
+
const msg = String(err?.stderr || err?.message || err);
|
|
109
|
+
// Older tish CLIs reject --platform; retry once without flags (env still set).
|
|
110
|
+
if (
|
|
111
|
+
supportsPlatformFlags !== false &&
|
|
112
|
+
/unexpected argument '--platform'|unexpected argument '--surface'/.test(msg)
|
|
113
|
+
) {
|
|
114
|
+
supportsPlatformFlags = false;
|
|
115
|
+
return compileModule(file);
|
|
116
|
+
}
|
|
117
|
+
throw err;
|
|
47
118
|
}
|
|
48
|
-
return { code: stdout, map: null };
|
|
49
119
|
}
|
|
50
120
|
|
|
51
121
|
return {
|
|
@@ -56,15 +126,17 @@ export default function tishPlugin(opts = {}) {
|
|
|
56
126
|
if (!projectRoot) projectRoot = config.root;
|
|
57
127
|
},
|
|
58
128
|
|
|
59
|
-
// Bring `.tish` imports into Vite's module graph: resolve relative `.tish` specifiers to absolute
|
|
60
|
-
// file paths so Vite addresses each module and can invalidate it individually. Root-relative URLs
|
|
61
|
-
// (`/src/x.tish`) and bare specifiers are left to Vite's resolver, which maps them to real files.
|
|
62
129
|
resolveId(source, importer) {
|
|
63
|
-
|
|
130
|
+
// Relative imports: always try platform cascade (with or without `.tish`).
|
|
64
131
|
if (source.startsWith(".") && importer) {
|
|
65
|
-
|
|
132
|
+
const resolved = resolveTishId(source, importer);
|
|
133
|
+
if (resolved) return resolved;
|
|
134
|
+
if (source.endsWith(TISH_EXT)) {
|
|
135
|
+
return path.resolve(path.dirname(importer.split("?")[0]), source);
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
66
138
|
}
|
|
67
|
-
if (path.isAbsolute(source) && existsSync(source)) {
|
|
139
|
+
if (source.endsWith(TISH_EXT) && path.isAbsolute(source) && existsSync(source)) {
|
|
68
140
|
return source;
|
|
69
141
|
}
|
|
70
142
|
return null;
|
|
@@ -75,8 +147,6 @@ export default function tishPlugin(opts = {}) {
|
|
|
75
147
|
if (!file.endsWith(TISH_EXT)) return null;
|
|
76
148
|
const { code, map } = compileModule(file);
|
|
77
149
|
if (mode !== "hmr") return { code, map };
|
|
78
|
-
// Self-accepting boundary: editing this module re-runs it without reloading the page. Frameworks
|
|
79
|
-
// (e.g. Lattish) can register their own `import.meta.hot.accept` handlers on top.
|
|
80
150
|
const withBoundary = `${code}\nif (import.meta.hot) { import.meta.hot.accept(); }\n`;
|
|
81
151
|
return { code: withBoundary, map };
|
|
82
152
|
},
|
|
@@ -88,7 +158,6 @@ export default function tishPlugin(opts = {}) {
|
|
|
88
158
|
server.ws.send({ type: "full-reload" });
|
|
89
159
|
return [];
|
|
90
160
|
}
|
|
91
|
-
// Hand Vite the changed module node(s) so it performs per-module HMR rather than a full reload.
|
|
92
161
|
const mods = server.moduleGraph.getModulesByFile(file);
|
|
93
162
|
return mods ? [...mods] : undefined;
|
|
94
163
|
},
|