@rohal12/twee-ts 1.14.0 → 1.15.2

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.
@@ -1,29 +1,23 @@
1
- import { C as CompileOptions } from '../types-FHZ3rZD6.js';
2
-
3
- /**
4
- * Ready-made Rollup plugin for twee-ts.
5
- * Compiles .tw files and emits HTML as an asset.
6
- */
7
-
8
- interface TweeTsRollupPluginOptions {
9
- /** Source directories/files to compile. */
10
- sources: string[];
11
- /** Story format ID. */
12
- format?: string;
13
- /** Output filename. Default: 'index.html'. */
14
- outputFilename?: string;
15
- /** Additional compile options. */
16
- compileOptions?: Partial<CompileOptions>;
1
+ import { t as CompileOptions } from "../types-BFyb40Zq.js";
2
+ //#region src/plugins/rollup.d.ts
3
+ export interface TweeTsRollupPluginOptions {
4
+ /** Source directories/files to compile. */
5
+ sources: string[];
6
+ /** Story format ID. */
7
+ format?: string;
8
+ /** Output filename. Default: 'index.html'. */
9
+ outputFilename?: string;
10
+ /** Additional compile options. */
11
+ compileOptions?: Partial<CompileOptions>;
17
12
  }
18
- declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
19
- name: string;
20
- generateBundle(this: {
21
- emitFile: (opts: {
22
- type: string;
23
- fileName: string;
24
- source: string;
25
- }) => void;
26
- }): Promise<void>;
13
+ export declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
14
+ name: string;
15
+ generateBundle(this: {
16
+ emitFile: (opts: {
17
+ type: string;
18
+ fileName: string;
19
+ source: string;
20
+ }) => void;
21
+ }): Promise<void>;
27
22
  };
28
-
29
- export { type TweeTsRollupPluginOptions, tweeTsPlugin };
23
+ //#endregion
@@ -1,34 +1,26 @@
1
- import {
2
- compile
3
- } from "../chunk-Z2CNKPVJ.js";
4
-
5
- // src/plugins/rollup.ts
1
+ import { n as compile } from "../compiler-Bfi1w-to.js";
2
+ //#region src/plugins/rollup.ts
6
3
  function tweeTsPlugin(options) {
7
- const outputFilename = options.outputFilename ?? "index.html";
8
- return {
9
- name: "twee-ts",
10
- async generateBundle() {
11
- const result = await compile({
12
- sources: options.sources,
13
- formatId: options.format,
14
- ...options.compileOptions
15
- });
16
- this.emitFile({
17
- type: "asset",
18
- fileName: outputFilename,
19
- source: result.output
20
- });
21
- for (const d of result.diagnostics) {
22
- if (d.level === "warning") {
23
- console.warn(`[twee-ts] ${d.message}`);
24
- } else {
25
- console.error(`[twee-ts] ${d.message}`);
26
- }
27
- }
28
- }
29
- };
4
+ const outputFilename = options.outputFilename ?? "index.html";
5
+ return {
6
+ name: "twee-ts",
7
+ async generateBundle() {
8
+ const result = await compile({
9
+ sources: options.sources,
10
+ formatId: options.format,
11
+ ...options.compileOptions
12
+ });
13
+ this.emitFile({
14
+ type: "asset",
15
+ fileName: outputFilename,
16
+ source: result.output
17
+ });
18
+ for (const d of result.diagnostics) if (d.level === "warning") console.warn(`[twee-ts] ${d.message}`);
19
+ else console.error(`[twee-ts] ${d.message}`);
20
+ }
21
+ };
30
22
  }
31
- export {
32
- tweeTsPlugin
33
- };
23
+ //#endregion
24
+ export { tweeTsPlugin };
25
+
34
26
  //# sourceMappingURL=rollup.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/rollup.ts"],"sourcesContent":["/**\n * Ready-made Rollup plugin for twee-ts.\n * Compiles .tw files and emits HTML as an asset.\n */\nimport type { CompileOptions } from '../types.js';\nimport { compile } from '../compiler.js';\n\nexport interface TweeTsRollupPluginOptions {\n /** Source directories/files to compile. */\n sources: string[];\n /** Story format ID. */\n format?: string;\n /** Output filename. Default: 'index.html'. */\n outputFilename?: string;\n /** Additional compile options. */\n compileOptions?: Partial<CompileOptions>;\n}\n\nexport function tweeTsPlugin(options: TweeTsRollupPluginOptions) {\n const outputFilename = options.outputFilename ?? 'index.html';\n\n return {\n name: 'twee-ts',\n\n async generateBundle(this: { emitFile: (opts: { type: string; fileName: string; source: string }) => void }) {\n const result = await compile({\n sources: options.sources,\n formatId: options.format,\n ...options.compileOptions,\n });\n\n this.emitFile({\n type: 'asset',\n fileName: outputFilename,\n source: result.output,\n });\n\n for (const d of result.diagnostics) {\n if (d.level === 'warning') {\n console.warn(`[twee-ts] ${d.message}`);\n } else {\n console.error(`[twee-ts] ${d.message}`);\n }\n }\n },\n };\n}\n"],"mappings":";;;;;AAkBO,SAAS,aAAa,SAAoC;AAC/D,QAAM,iBAAiB,QAAQ,kBAAkB;AAEjD,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,MAAM,iBAAuG;AAC3G,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,SAAS,QAAQ;AAAA,QACjB,UAAU,QAAQ;AAAA,QAClB,GAAG,QAAQ;AAAA,MACb,CAAC;AAED,WAAK,SAAS;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,QACV,QAAQ,OAAO;AAAA,MACjB,CAAC;AAED,iBAAW,KAAK,OAAO,aAAa;AAClC,YAAI,EAAE,UAAU,WAAW;AACzB,kBAAQ,KAAK,aAAa,EAAE,OAAO,EAAE;AAAA,QACvC,OAAO;AACL,kBAAQ,MAAM,aAAa,EAAE,OAAO,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"file":"rollup.js","names":[],"sources":["../../src/plugins/rollup.ts"],"sourcesContent":["/**\n * Ready-made Rollup plugin for twee-ts.\n * Compiles .tw files and emits HTML as an asset.\n */\nimport type { CompileOptions } from '../types.js';\nimport { compile } from '../compiler.js';\n\nexport interface TweeTsRollupPluginOptions {\n /** Source directories/files to compile. */\n sources: string[];\n /** Story format ID. */\n format?: string;\n /** Output filename. Default: 'index.html'. */\n outputFilename?: string;\n /** Additional compile options. */\n compileOptions?: Partial<CompileOptions>;\n}\n\nexport function tweeTsPlugin(options: TweeTsRollupPluginOptions) {\n const outputFilename = options.outputFilename ?? 'index.html';\n\n return {\n name: 'twee-ts',\n\n async generateBundle(this: { emitFile: (opts: { type: string; fileName: string; source: string }) => void }) {\n const result = await compile({\n sources: options.sources,\n formatId: options.format,\n ...options.compileOptions,\n });\n\n this.emitFile({\n type: 'asset',\n fileName: outputFilename,\n source: result.output,\n });\n\n for (const d of result.diagnostics) {\n if (d.level === 'warning') {\n console.warn(`[twee-ts] ${d.message}`);\n } else {\n console.error(`[twee-ts] ${d.message}`);\n }\n }\n },\n };\n}\n"],"mappings":";;AAkBA,SAAgB,aAAa,SAAoC;CAC/D,MAAM,iBAAiB,QAAQ,kBAAkB;CAEjD,OAAO;EACL,MAAM;EAEN,MAAM,iBAAuG;GAC3G,MAAM,SAAS,MAAM,QAAQ;IAC3B,SAAS,QAAQ;IACjB,UAAU,QAAQ;IAClB,GAAG,QAAQ;GACb,CAAC;GAED,KAAK,SAAS;IACZ,MAAM;IACN,UAAU;IACV,QAAQ,OAAO;GACjB,CAAC;GAED,KAAK,MAAM,KAAK,OAAO,aACrB,IAAI,EAAE,UAAU,WACd,QAAQ,KAAK,aAAa,EAAE,SAAS;QAErC,QAAQ,MAAM,aAAa,EAAE,SAAS;EAG5C;CACF;AACF"}
@@ -1,57 +1,22 @@
1
- import { C as CompileOptions } from '../types-FHZ3rZD6.js';
2
-
3
- /**
4
- * Ready-made Vite plugin for twee-ts.
5
- * Watches .tw files and emits compiled HTML via incremental compilation.
6
- */
7
-
8
- interface TweeTsVitePluginOptions {
9
- /** Source directories/files to compile. */
10
- sources: string[];
11
- /** Story format ID. */
12
- format?: string;
13
- /** Output filename in build output. Default: 'index.html'. */
14
- outputFilename?: string;
15
- /** Additional compile options. */
16
- compileOptions?: Partial<CompileOptions>;
1
+ import { t as CompileOptions } from "../types-BFyb40Zq.js";
2
+ import { Plugin } from "vite";
3
+ //#region src/plugins/vite.d.ts
4
+ export interface TweeTsVitePluginOptions {
5
+ /** Source directories/files to compile, relative to the working directory. */
6
+ sources: string[];
7
+ /** Story format ID. */
8
+ format?: string;
9
+ /** Output filename in build output. Default: 'index.html'. */
10
+ outputFilename?: string;
11
+ /** Additional compile options. `sources` and `formatId` come from the options above. */
12
+ compileOptions?: Partial<CompileOptions>;
13
+ /**
14
+ * A JS or TS file, relative to the working directory. Vite bundles it and
15
+ * everything it imports into one self-contained script that becomes the
16
+ * story's Story JavaScript; CSS it imports becomes the Story Stylesheet.
17
+ * Requires Vite 8.
18
+ */
19
+ entry?: string;
17
20
  }
18
- declare function tweeTsPlugin(options: TweeTsVitePluginOptions): {
19
- name: string;
20
- buildStart(): Promise<void>;
21
- generateBundle(this: {
22
- emitFile: (opts: {
23
- type: string;
24
- fileName: string;
25
- source: string;
26
- }) => void;
27
- }): Promise<void>;
28
- configureServer(server: {
29
- watcher: {
30
- add: (path: string) => void;
31
- };
32
- ws: {
33
- send: (data: {
34
- type: string;
35
- }) => void;
36
- };
37
- middlewares: {
38
- use: (fn: (req: {
39
- url?: string;
40
- }, res: {
41
- end: (data: string) => void;
42
- }, next: () => void) => void) => void;
43
- };
44
- }): Promise<void>;
45
- handleHotUpdate(ctx: {
46
- file: string;
47
- server: {
48
- ws: {
49
- send: (data: {
50
- type: string;
51
- }) => void;
52
- };
53
- };
54
- }): Promise<void>;
55
- };
56
-
57
- export { type TweeTsVitePluginOptions, tweeTsPlugin };
21
+ export declare function tweeTsPlugin(options: TweeTsVitePluginOptions): Plugin;
22
+ //#endregion
@@ -1,70 +1,407 @@
1
- import {
2
- compileIncremental
3
- } from "../chunk-Z2CNKPVJ.js";
4
-
5
- // src/plugins/vite.ts
6
- function isTweeFile(file) {
7
- return file.endsWith(".tw") || file.endsWith(".twee");
8
- }
9
- function getCompileOptions(options) {
10
- return {
11
- sources: options.sources,
12
- formatId: options.format,
13
- ...options.compileOptions
14
- };
15
- }
16
- function logDiagnostics(diagnostics) {
17
- for (const d of diagnostics) {
18
- if (d.level === "warning") {
19
- console.warn(`[twee-ts] ${d.message}`);
20
- } else {
21
- console.error(`[twee-ts] ${d.message}`);
22
- }
23
- }
1
+ import { i as mediaTypeFromFilename, r as compileIncremental, t as TweeTsError } from "../compiler-Bfi1w-to.js";
2
+ import { resolve } from "node:path";
3
+ import { stripVTControlCharacters } from "node:util";
4
+ import { build, version } from "vite";
5
+ //#region src/plugins/paths.ts
6
+ /**
7
+ * Path helpers for the Vite plugin. Vite reports module ids with forward
8
+ * slashes on every platform, while node:path gives backslashes on Windows, so
9
+ * the plugin compares paths in forward-slash form only.
10
+ */
11
+ /** The path with Windows separators turned into forward slashes. */
12
+ function toPosix(path) {
13
+ return path.replace(/\\/g, "/");
24
14
  }
25
- function tweeTsPlugin(options) {
26
- const outputFilename = options.outputFilename ?? "index.html";
27
- const cache = /* @__PURE__ */ new Map();
28
- let compiledHtml = "";
29
- return {
30
- name: "twee-ts",
31
- async buildStart() {
32
- },
33
- async generateBundle() {
34
- const result = await compileIncremental(getCompileOptions(options), cache);
35
- this.emitFile({
36
- type: "asset",
37
- fileName: outputFilename,
38
- source: result.output
39
- });
40
- logDiagnostics(result.diagnostics);
41
- },
42
- async configureServer(server) {
43
- for (const source of options.sources) {
44
- server.watcher.add(source);
45
- }
46
- const result = await compileIncremental(getCompileOptions(options), cache);
47
- compiledHtml = result.output;
48
- logDiagnostics(result.diagnostics);
49
- const servePath = outputFilename === "index.html" ? "/" : `/${outputFilename}`;
50
- server.middlewares.use((req, res, next) => {
51
- if (req.url === servePath || servePath === "/" && req.url === "/index.html") {
52
- res.end(compiledHtml);
53
- return;
54
- }
55
- next();
56
- });
57
- },
58
- async handleHotUpdate(ctx) {
59
- if (!isTweeFile(ctx.file)) return;
60
- const result = await compileIncremental(getCompileOptions(options), cache, /* @__PURE__ */ new Set([ctx.file]));
61
- compiledHtml = result.output;
62
- logDiagnostics(result.diagnostics);
63
- ctx.server.ws.send({ type: "full-reload" });
64
- }
65
- };
66
- }
67
- export {
68
- tweeTsPlugin
15
+ /** Whether `file` is one of `dirs` or inside one of them. All paths in forward-slash form. */
16
+ function isInside(file, dirs) {
17
+ return dirs.some((dir) => file === dir || file.startsWith(dir.endsWith("/") ? dir : `${dir}/`));
18
+ }
19
+ /**
20
+ * Whether `file` is a temporary copy of a Vite config file. Vite writes one next
21
+ * to the config file each time it loads it (when no node_modules folder is
22
+ * above the config, and always under Deno), then deletes it.
23
+ */
24
+ function isViteConfigTemp(file) {
25
+ return /\.timestamp-\d+-[0-9a-f]*\.mjs$/.test(file);
26
+ }
27
+ //#endregion
28
+ //#region src/plugins/vite.ts
29
+ /**
30
+ * Ready-made Vite plugin for twee-ts.
31
+ *
32
+ * Compiles Twee sources into the story HTML. With `entry`, Vite also bundles a
33
+ * script, and the CSS it imports, into the story as its Story JavaScript and
34
+ * Story Stylesheet.
35
+ *
36
+ * In dev the compiled HTML is served at the base URL with Vite's client added.
37
+ * Every change to a source, the head file, a module or a file the entry imports
38
+ * recompiles it and reloads the page, and errors appear in Vite's overlay.
39
+ */
40
+ /** Passage names the bundled entry takes inside the story. */
41
+ const ENTRY_SCRIPT_NAME = "twee-ts-entry.js";
42
+ const ENTRY_STYLE_NAME = "twee-ts-entry.css";
43
+ /**
44
+ * Set on the inline config of the build this plugin starts itself to bundle the
45
+ * entry in dev. The plugin instance that build loads from the user's config file
46
+ * sees it and stands aside.
47
+ */
48
+ const INNER_BUILD_FLAG = "__tweeTsEntryBuild";
49
+ /**
50
+ * A build input that stands in when there is no entry, so Vite does not look
51
+ * for an index.html (whose page would replace the story). Its empty chunk is
52
+ * dropped from the output.
53
+ */
54
+ const EMPTY_INPUT = "virtual:twee-ts-empty-input";
55
+ const RESOLVED_EMPTY_INPUT = "\0" + EMPTY_INPUT;
56
+ const viteMajor = Number.parseInt(version, 10);
57
+ function formatDiagnostic(d) {
58
+ return `${d.file ? `${d.file}${d.line ? `:${d.line}` : ""}: ` : ""}${d.file && d.line ? d.message.replace(/^line \d+: /, "") : d.message}`;
59
+ }
60
+ /** Returns the warnings; throws a LocatedError when the compile reported errors. */
61
+ function splitDiagnostics(result) {
62
+ const errors = result.diagnostics.filter((d) => d.level === "error");
63
+ if (errors.length === 0) return result.diagnostics.filter((d) => d.level === "warning");
64
+ const error = new Error(errors.map(formatDiagnostic).join("\n"));
65
+ const [first] = errors;
66
+ if (first?.file) {
67
+ error.id = first.file;
68
+ error.loc = {
69
+ file: first.file,
70
+ line: first.line ?? 1,
71
+ column: 1
72
+ };
73
+ }
74
+ throw error;
75
+ }
76
+ /** An error thrown by the compiler or bundler, with a TweeTsError's error diagnostics folded into its message. */
77
+ function fatalError(e) {
78
+ if (e instanceof TweeTsError) {
79
+ const errors = e.diagnostics.filter((d) => d.level === "error").map(formatDiagnostic);
80
+ return new Error([...errors, e.message].join("\n"));
81
+ }
82
+ return e instanceof Error ? e : new Error(String(e));
83
+ }
84
+ function buildCompileOptions(options, entry) {
85
+ const inline = [];
86
+ if (entry) {
87
+ inline.push({
88
+ filename: ENTRY_SCRIPT_NAME,
89
+ content: entry.script
90
+ });
91
+ if (entry.style !== "") inline.push({
92
+ filename: ENTRY_STYLE_NAME,
93
+ content: entry.style
94
+ });
95
+ }
96
+ return {
97
+ ...options.compileOptions,
98
+ sources: [...options.sources, ...inline],
99
+ formatId: options.format ?? options.compileOptions?.formatId
100
+ };
101
+ }
102
+ /** Whether the user's config names build inputs of its own. */
103
+ function hasUserInput(userConfig) {
104
+ const build = userConfig.build;
105
+ return build?.["rolldownOptions"]?.input !== void 0 || build?.["rollupOptions"]?.input !== void 0;
106
+ }
107
+ /** Build settings naming one input, under the option name this Vite version reads. */
108
+ function inputOnly(input) {
109
+ return viteMajor >= 8 ? { rolldownOptions: { input } } : { rollupOptions: { input } };
110
+ }
111
+ /**
112
+ * Build settings that turn the entry into one IIFE script and one stylesheet.
113
+ * Fonts and images the entry uses are inlined as data URLs, so the story stays
114
+ * one file; only an import marked `?no-inline` is still emitted separately.
115
+ */
116
+ function entryBuildOptions(entryPath) {
117
+ return {
118
+ cssCodeSplit: false,
119
+ assetsInlineLimit: () => true,
120
+ rolldownOptions: {
121
+ input: entryPath,
122
+ output: {
123
+ format: "iife",
124
+ entryFileNames: ENTRY_SCRIPT_NAME,
125
+ assetFileNames: "[name][extname]"
126
+ }
127
+ }
128
+ };
129
+ }
130
+ /** Removes a trailing source-map comment that points at a file (a data: URL map stays). */
131
+ function dropFileSourceMapComment(code) {
132
+ return code.replace(/\n?\/\/# sourceMappingURL=(?!data:)\S*\s*$/, "").replace(/\n?\/\*# sourceMappingURL=(?!data:)[^*]*\*\/\s*$/, "");
133
+ }
134
+ /**
135
+ * Takes the entry's script and stylesheet out of the bundle, together with
136
+ * their map files, which the story cannot ship. Anything else the bundler
137
+ * emitted stays in the bundle, so a build writes it next to the HTML, and is
138
+ * also returned, so the dev server can serve it.
139
+ */
140
+ function takeEntryFromBundle(bundle) {
141
+ const entry = {
142
+ script: "",
143
+ style: "",
144
+ files: /* @__PURE__ */ new Set(),
145
+ assets: /* @__PURE__ */ new Map()
146
+ };
147
+ const styles = [];
148
+ for (const [fileName, item] of Object.entries(bundle)) if (item.type === "chunk") {
149
+ if (item.isEntry) {
150
+ entry.script = dropFileSourceMapComment(item.code);
151
+ for (const id of item.moduleIds) if (!id.startsWith("\0")) entry.files.add(toPosix(id));
152
+ }
153
+ delete bundle[fileName];
154
+ } else if (fileName.endsWith(".css")) {
155
+ const css = typeof item.source === "string" ? item.source : new TextDecoder().decode(item.source);
156
+ styles.push(dropFileSourceMapComment(css));
157
+ delete bundle[fileName];
158
+ } else if (fileName.endsWith(".map")) delete bundle[fileName];
159
+ else entry.assets.set(fileName, item.source);
160
+ entry.style = styles.join("\n");
161
+ return entry;
162
+ }
163
+ /** Absolute forward-slash paths whose changes recompile the story: sources, head file, modules. */
164
+ function watchedInputs(options) {
165
+ const extra = options.compileOptions;
166
+ return [
167
+ ...options.sources,
168
+ ...extra?.headFile ? [extra.headFile] : [],
169
+ ...extra?.modules ?? []
170
+ ].map((p) => toPosix(resolve(p)));
171
+ }
172
+ /** Adds Vite's client to the page so reloads and the error overlay reach it. */
173
+ function injectViteClient(html, base) {
174
+ const tag = `<script type="module" src="${base}@vite/client"><\/script>`;
175
+ const head = /<head[^>]*>/i.exec(html);
176
+ if (!head) return tag + html;
177
+ const at = head.index + head[0].length;
178
+ return html.slice(0, at) + tag + html.slice(at);
179
+ }
180
+ /** Served until the first successful compile, so the overlay has a page to appear on. */
181
+ function waitingPage(base) {
182
+ return `<!doctype html><html><head><meta charset="utf-8"><script type="module" src="${base}@vite/client"><\/script><title>twee-ts</title></head><body><p>The story has not compiled yet.</p></body></html>`;
183
+ }
184
+ function toOverlayError(e) {
185
+ const error = fatalError(e);
186
+ return {
187
+ message: stripVTControlCharacters(error.message),
188
+ stack: "",
189
+ plugin: "twee-ts",
190
+ ...error.id ? { id: error.id } : {},
191
+ ...error.loc ? { loc: error.loc } : {}
192
+ };
193
+ }
194
+ /** Bundles the entry for dev with the user's own Vite config, unminified, with an inline source map. */
195
+ /**
196
+ * The entry build's logger: its warnings go to the dev server's logger; its
197
+ * progress lines and its own "build failed" line are dropped, because the plugin
198
+ * reports a failed bundle itself.
199
+ */
200
+ function entryBuildLogger(outer) {
201
+ return {
202
+ info: () => {},
203
+ warn: (message, options) => outer.warn(message, options),
204
+ warnOnce: (message, options) => outer.warnOnce(message, options),
205
+ error: () => {},
206
+ clearScreen: () => {},
207
+ hasErrorLogged: () => false,
208
+ get hasWarned() {
209
+ return outer.hasWarned;
210
+ }
211
+ };
212
+ }
213
+ /**
214
+ * Keeps the entry build a one-off even when the user's config sets build.watch:
215
+ * Vite's config merge skips a null, so the inline `watch: null` alone can't.
216
+ */
217
+ const oneOffEntryBuild = {
218
+ name: "twee-ts:one-off-entry-build",
219
+ enforce: "post",
220
+ config(userConfig) {
221
+ if (userConfig.build) userConfig.build.watch = null;
222
+ }
69
223
  };
224
+ /** Bundles the entry for dev with the user's own Vite config, unminified, with an inline source map. */
225
+ async function bundleEntryForDev(config, entryPath) {
226
+ const inline = {
227
+ configFile: config.configFile ?? false,
228
+ root: config.root,
229
+ mode: config.mode,
230
+ customLogger: entryBuildLogger(config.logger),
231
+ publicDir: false,
232
+ ...config.configFile ? {} : {
233
+ define: config.define,
234
+ resolve: { alias: config.resolve.alias }
235
+ },
236
+ build: {
237
+ ...entryBuildOptions(entryPath),
238
+ write: false,
239
+ minify: false,
240
+ sourcemap: "inline",
241
+ emptyOutDir: false,
242
+ copyPublicDir: false,
243
+ watch: null
244
+ },
245
+ plugins: [oneOffEntryBuild],
246
+ [INNER_BUILD_FLAG]: true
247
+ };
248
+ const out = await build(inline);
249
+ const bundle = {};
250
+ for (const result of Array.isArray(out) ? out : [out]) {
251
+ if (!("output" in result)) {
252
+ await result.close();
253
+ throw new Error("twee-ts: the entry build returned a watcher instead of a bundle.");
254
+ }
255
+ for (const item of result.output) bundle[item.fileName] = item;
256
+ }
257
+ return takeEntryFromBundle(bundle);
258
+ }
259
+ function tweeTsPlugin(options) {
260
+ const outputFilename = options.outputFilename ?? "index.html";
261
+ const cache = /* @__PURE__ */ new Map();
262
+ let innerBuild = false;
263
+ let stopDev;
264
+ if (options.entry && viteMajor < 8) throw new Error(`twee-ts: the entry option needs Vite 8 or newer (found ${version}).`);
265
+ return {
266
+ name: "twee-ts",
267
+ config(userConfig, env) {
268
+ innerBuild = userConfig[INNER_BUILD_FLAG] === true;
269
+ if (innerBuild || env.command !== "build") return void 0;
270
+ if (options.entry) return { build: entryBuildOptions(resolve(options.entry)) };
271
+ if (hasUserInput(userConfig)) return void 0;
272
+ return { build: inputOnly(EMPTY_INPUT) };
273
+ },
274
+ configResolved(config) {
275
+ if (innerBuild || !options.entry) return;
276
+ const sources = options.sources.map((p) => toPosix(resolve(p)));
277
+ if (isInside(toPosix(resolve(options.entry)), sources)) config.logger.warn(`[twee-ts] The entry ${options.entry} is inside the story sources (${options.sources.join(", ")}). twee-ts also loads the .js and .css files it finds in source folders, unbundled, as Story JavaScript and Story Stylesheet; keep the entry's folder out of \`sources\`.`);
278
+ },
279
+ resolveId(id) {
280
+ return id === EMPTY_INPUT ? RESOLVED_EMPTY_INPUT : void 0;
281
+ },
282
+ load(id) {
283
+ return id === RESOLVED_EMPTY_INPUT ? "globalThis.tweeTsEmptyInput = true;" : void 0;
284
+ },
285
+ generateBundle: {
286
+ order: "post",
287
+ async handler(_outputOptions, bundle) {
288
+ if (innerBuild) return;
289
+ for (const [fileName, item] of Object.entries(bundle)) if (item.type === "chunk" && item.facadeModuleId === RESOLVED_EMPTY_INPUT) delete bundle[fileName];
290
+ const entry = options.entry ? takeEntryFromBundle(bundle) : void 0;
291
+ let result;
292
+ try {
293
+ result = await compileIncremental(buildCompileOptions(options, entry), cache);
294
+ } catch (e) {
295
+ return this.error(fatalError(e));
296
+ }
297
+ let warnings;
298
+ try {
299
+ warnings = splitDiagnostics(result);
300
+ } catch (e) {
301
+ return this.error(e);
302
+ }
303
+ for (const w of warnings) this.warn(formatDiagnostic(w));
304
+ this.emitFile({
305
+ type: "asset",
306
+ fileName: outputFilename,
307
+ source: result.output
308
+ });
309
+ }
310
+ },
311
+ async configureServer(server) {
312
+ if (innerBuild) return;
313
+ const base = server.config.base;
314
+ const servePaths = outputFilename === "index.html" ? [base, `${base}index.html`] : [`${base}${outputFilename}`];
315
+ const inputs = watchedInputs(options);
316
+ const entryPath = options.entry ? resolve(options.entry) : void 0;
317
+ const root = toPosix(server.config.root);
318
+ server.watcher.add(inputs);
319
+ let html = "";
320
+ let lastError;
321
+ let entry;
322
+ let entryStale = true;
323
+ let queue = Promise.resolve();
324
+ let pending = /* @__PURE__ */ new Set();
325
+ let timer;
326
+ let closed = false;
327
+ stopDev = () => {
328
+ closed = true;
329
+ clearTimeout(timer);
330
+ pending.clear();
331
+ };
332
+ const touchesEntry = (file) => entryPath !== void 0 && (entryStale ? isInside(file, [root]) : entry?.files.has(file) ?? false);
333
+ const rebuild = async (changed, initial = false) => {
334
+ if (closed) return;
335
+ for (const key of [...cache.keys()]) if (changed.has(toPosix(resolve(key)))) cache.delete(key);
336
+ try {
337
+ if (entryPath && (entryStale || [...changed].some(touchesEntry))) {
338
+ entryStale = true;
339
+ entry = await bundleEntryForDev(server.config, entryPath);
340
+ entryStale = false;
341
+ }
342
+ const result = await compileIncremental(buildCompileOptions(options, entry), cache);
343
+ for (const w of splitDiagnostics(result)) server.config.logger.warn(`[twee-ts] ${formatDiagnostic(w)}`);
344
+ html = injectViteClient(result.output, base);
345
+ lastError = void 0;
346
+ if (!initial) server.ws.send({ type: "full-reload" });
347
+ } catch (e) {
348
+ lastError = toOverlayError(e);
349
+ server.config.logger.error(`[twee-ts] ${lastError.message}`);
350
+ server.ws.send({
351
+ type: "error",
352
+ err: lastError
353
+ });
354
+ }
355
+ };
356
+ const keepQueueAlive = (e) => {
357
+ try {
358
+ server.config.logger.error(`[twee-ts] ${fatalError(e).message}`);
359
+ } catch {}
360
+ };
361
+ await rebuild(/* @__PURE__ */ new Set(), true);
362
+ server.watcher.on("all", (event, file) => {
363
+ if (event !== "add" && event !== "change" && event !== "unlink") return;
364
+ const changed = toPosix(resolve(file));
365
+ if (isViteConfigTemp(changed)) return;
366
+ if (!isInside(changed, inputs) && !touchesEntry(changed)) return;
367
+ pending.add(changed);
368
+ clearTimeout(timer);
369
+ timer = setTimeout(() => {
370
+ const files = pending;
371
+ pending = /* @__PURE__ */ new Set();
372
+ queue = queue.then(() => rebuild(files)).catch(keepQueueAlive);
373
+ }, 50);
374
+ });
375
+ server.ws.on("connection", () => {
376
+ if (lastError) server.ws.send({
377
+ type: "error",
378
+ err: lastError
379
+ });
380
+ });
381
+ server.middlewares.use((req, res, next) => {
382
+ const path = (req.url ?? "").split("?")[0] ?? "";
383
+ if (servePaths.includes(path)) {
384
+ res.statusCode = 200;
385
+ res.setHeader("Content-Type", "text/html; charset=utf-8");
386
+ res.end(html || waitingPage(base));
387
+ return;
388
+ }
389
+ const asset = path.startsWith(base) ? entry?.assets.get(path.slice(base.length)) : void 0;
390
+ if (asset !== void 0) {
391
+ res.statusCode = 200;
392
+ res.setHeader("Content-Type", mediaTypeFromFilename(path));
393
+ res.end(asset);
394
+ return;
395
+ }
396
+ next();
397
+ });
398
+ },
399
+ closeBundle() {
400
+ stopDev?.();
401
+ }
402
+ };
403
+ }
404
+ //#endregion
405
+ export { tweeTsPlugin };
406
+
70
407
  //# sourceMappingURL=vite.js.map