@rohal12/twee-ts 1.17.0 → 1.18.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/dist/bin/twee-ts.js +2174 -648
- package/dist/bin/twee-ts.js.map +1 -1
- package/dist/index.cjs +2176 -637
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +156 -55
- package/dist/index.d.ts +156 -55
- package/dist/index.js +2177 -639
- package/dist/index.js.map +1 -1
- package/dist/{diagnostics-DZNS7W41.js → paths-DgO9oo6G.js} +1867 -565
- package/dist/paths-DgO9oo6G.js.map +1 -0
- package/dist/plugins/rollup.d.ts +11 -2
- package/dist/plugins/rollup.js +60 -6
- package/dist/plugins/rollup.js.map +1 -1
- package/dist/plugins/vite.d.ts +1 -1
- package/dist/plugins/vite.js +104 -57
- package/dist/plugins/vite.js.map +1 -1
- package/dist/{types-dR5vTVu2.d.ts → types-D8Xfe0l8.d.ts} +25 -8
- package/package.json +1 -1
- package/schemas/twee-ts.config.schema.json +6 -0
- package/dist/diagnostics-DZNS7W41.js.map +0 -1
package/dist/plugins/rollup.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as CompileOptions } from "../types-
|
|
1
|
+
import { t as CompileOptions } from "../types-D8Xfe0l8.js";
|
|
2
2
|
//#region src/plugins/diagnostics.d.ts
|
|
3
3
|
/** An error carrying the file and line the bundler reports (and Vite shows in its overlay). */
|
|
4
4
|
interface LocatedError extends Error {
|
|
@@ -10,6 +10,13 @@ interface LocatedError extends Error {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
//#endregion
|
|
13
|
+
//#region src/plugins/paths.d.ts
|
|
14
|
+
/** The output settings that say where a bundle is written, as Rollup and Vite pass them to generateBundle. */
|
|
15
|
+
interface OutputLocation {
|
|
16
|
+
readonly dir?: string | undefined;
|
|
17
|
+
readonly file?: string | undefined;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
13
20
|
//#region src/plugins/rollup.d.ts
|
|
14
21
|
export interface TweeTsRollupPluginOptions {
|
|
15
22
|
/** Source directories/files to compile. */
|
|
@@ -23,12 +30,14 @@ export interface TweeTsRollupPluginOptions {
|
|
|
23
30
|
}
|
|
24
31
|
export declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
|
|
25
32
|
name: string;
|
|
33
|
+
options(inputOptions: object): undefined;
|
|
26
34
|
buildStart(this: {
|
|
27
35
|
addWatchFile: (id: string) => void;
|
|
28
36
|
meta: {
|
|
29
37
|
watchMode: boolean;
|
|
30
38
|
};
|
|
31
39
|
}): void;
|
|
40
|
+
renderStart(outputOptions: OutputLocation): void;
|
|
32
41
|
generateBundle(this: {
|
|
33
42
|
emitFile: (opts: {
|
|
34
43
|
type: 'asset';
|
|
@@ -37,6 +46,6 @@ export declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
|
|
|
37
46
|
}) => void;
|
|
38
47
|
error: (error: LocatedError) => never;
|
|
39
48
|
warn: (message: string) => void;
|
|
40
|
-
}): Promise<void>;
|
|
49
|
+
}, outputOptions: OutputLocation, bundle: Readonly<Record<string, unknown>>): Promise<void>;
|
|
41
50
|
};
|
|
42
51
|
//#endregion
|
package/dist/plugins/rollup.js
CHANGED
|
@@ -1,33 +1,87 @@
|
|
|
1
|
-
import { i as
|
|
2
|
-
import {
|
|
1
|
+
import { c as splitDiagnostics, f as outputPaths, i as outputLocations, l as compileForOutputFile, m as walkedEntry, o as fatalError, p as realPathOf, s as formatDiagnostic, t as createOutputRecord } from "../paths-DgO9oo6G.js";
|
|
2
|
+
import { readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
3
4
|
//#region src/plugins/rollup.ts
|
|
4
5
|
/**
|
|
5
6
|
* Ready-made Rollup plugin for twee-ts.
|
|
6
7
|
* Compiles .tw files and emits HTML as an asset. Compile errors fail the build
|
|
7
8
|
* and emit nothing; warnings go through Rollup's warnings.
|
|
8
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* What `rollup --watch` watches for the input at `path`, whose real path is
|
|
12
|
+
* `real`. `isRoot`: the input itself, which is followed wherever it leads.
|
|
13
|
+
*
|
|
14
|
+
* Rollup watches a folder recursively and follows the links in it. So a folder
|
|
15
|
+
* is registered whole only when nothing under it is left out of the story: no
|
|
16
|
+
* file or folder the build writes (`outputs`), and no link to a folder, which
|
|
17
|
+
* source discovery doesn't follow and which may lead to the output. Any other
|
|
18
|
+
* folder is replaced by what it contains, minus those, so writing the outputs
|
|
19
|
+
* starts no build. A file added straight to such a folder is found at the next
|
|
20
|
+
* build. A path the build writes to is never registered itself: Rollup fails a
|
|
21
|
+
* watch build whose watched files include its `output.dir` or `output.file`.
|
|
22
|
+
*/
|
|
23
|
+
function watchTargets(path, real, outputs, isRoot) {
|
|
24
|
+
if (outputs.isFile(real) || !isRoot && outputs.isDir(real)) return [];
|
|
25
|
+
let entry;
|
|
26
|
+
try {
|
|
27
|
+
entry = isRoot ? {
|
|
28
|
+
stat: statSync(path),
|
|
29
|
+
real
|
|
30
|
+
} : walkedEntry(path, real);
|
|
31
|
+
} catch {
|
|
32
|
+
return isRoot && !outputs.isDir(real) ? [path] : [];
|
|
33
|
+
}
|
|
34
|
+
if (entry === void 0) return [];
|
|
35
|
+
if (outputs.isFile(entry.real)) return [];
|
|
36
|
+
if (!entry.stat.isDirectory()) return [path];
|
|
37
|
+
let names;
|
|
38
|
+
try {
|
|
39
|
+
names = readdirSync(path);
|
|
40
|
+
} catch {
|
|
41
|
+
return isRoot && !outputs.isDir(real) ? [path] : [];
|
|
42
|
+
}
|
|
43
|
+
const children = names.map((name) => {
|
|
44
|
+
const child = join(path, name);
|
|
45
|
+
return {
|
|
46
|
+
path: child,
|
|
47
|
+
targets: watchTargets(child, join(entry.real, name), outputs, false)
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
return !outputs.holds(entry.real) && children.every(({ path: child, targets }) => targets.length === 1 && targets[0] === child) ? [path] : children.flatMap(({ targets }) => targets);
|
|
51
|
+
}
|
|
9
52
|
function tweeTsPlugin(options) {
|
|
10
53
|
const outputFilename = options.outputFilename ?? "index.html";
|
|
54
|
+
const record = createOutputRecord(outputFilename);
|
|
11
55
|
return {
|
|
12
56
|
name: "twee-ts",
|
|
57
|
+
options(inputOptions) {
|
|
58
|
+
const { output } = inputOptions;
|
|
59
|
+
for (const location of outputLocations(output)) record.addLocation(location);
|
|
60
|
+
},
|
|
13
61
|
buildStart() {
|
|
14
62
|
if (!this.meta.watchMode) return;
|
|
63
|
+
const outputs = outputPaths(record.outputs());
|
|
15
64
|
const extra = options.compileOptions;
|
|
16
65
|
const inputs = [
|
|
17
66
|
...options.sources,
|
|
18
67
|
...extra?.headFile ? [extra.headFile] : [],
|
|
19
68
|
...extra?.modules ?? []
|
|
20
69
|
];
|
|
21
|
-
for (const input of inputs)
|
|
70
|
+
for (const input of inputs) for (const target of watchTargets(resolve(input), realPathOf(input), outputs, true)) this.addWatchFile(target);
|
|
71
|
+
},
|
|
72
|
+
renderStart(outputOptions) {
|
|
73
|
+
record.addLocation(outputOptions);
|
|
22
74
|
},
|
|
23
|
-
async generateBundle() {
|
|
75
|
+
async generateBundle(outputOptions, bundle) {
|
|
76
|
+
record.addLocation(outputOptions);
|
|
77
|
+
record.addFiles(outputOptions, Object.keys(bundle));
|
|
24
78
|
let result;
|
|
25
79
|
try {
|
|
26
|
-
result = await
|
|
80
|
+
result = await compileForOutputFile({
|
|
27
81
|
sources: options.sources,
|
|
28
82
|
formatId: options.format,
|
|
29
83
|
...options.compileOptions
|
|
30
|
-
});
|
|
84
|
+
}, record.outputs());
|
|
31
85
|
} catch (e) {
|
|
32
86
|
return this.error(fatalError(e));
|
|
33
87
|
}
|
|
@@ -1 +1 @@
|
|
|
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. Compile errors fail the build\n * and emit nothing; warnings go through Rollup's warnings.\n */\nimport { resolve } from 'node:path';\nimport type { CompileOptions, CompileResult, Diagnostic } from '../types.js';\nimport {
|
|
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. Compile errors fail the build\n * and emit nothing; warnings go through Rollup's warnings.\n */\nimport { readdirSync, statSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport type { CompileOptions, CompileResult, Diagnostic } from '../types.js';\nimport { compileForOutputFile } from '../compiler.js';\nimport { outputPaths, realPathOf, walkedEntry } from '../filesystem.js';\nimport type { OutputPaths } from '../filesystem.js';\nimport { fatalError, formatDiagnostic, splitDiagnostics } from './diagnostics.js';\nimport type { LocatedError } from './diagnostics.js';\nimport { createOutputRecord, outputLocations } from './paths.js';\nimport type { OutputLocation } from './paths.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\n/**\n * What `rollup --watch` watches for the input at `path`, whose real path is\n * `real`. `isRoot`: the input itself, which is followed wherever it leads.\n *\n * Rollup watches a folder recursively and follows the links in it. So a folder\n * is registered whole only when nothing under it is left out of the story: no\n * file or folder the build writes (`outputs`), and no link to a folder, which\n * source discovery doesn't follow and which may lead to the output. Any other\n * folder is replaced by what it contains, minus those, so writing the outputs\n * starts no build. A file added straight to such a folder is found at the next\n * build. A path the build writes to is never registered itself: Rollup fails a\n * watch build whose watched files include its `output.dir` or `output.file`.\n */\nfunction watchTargets(path: string, real: string, outputs: OutputPaths, isRoot: boolean): string[] {\n if (outputs.isFile(real) || (!isRoot && outputs.isDir(real))) return [];\n let entry;\n try {\n entry = isRoot ? { stat: statSync(path), real } : walkedEntry(path, real);\n } catch {\n // An input Rollup's watcher reports, unless it is an output location. Below an\n // input, what source discovery can't read (a link to nothing, say) is skipped.\n return isRoot && !outputs.isDir(real) ? [path] : [];\n }\n if (entry === undefined) return []; // A link to a folder, not followed.\n if (outputs.isFile(entry.real)) return [];\n if (!entry.stat.isDirectory()) return [path];\n let names: string[];\n try {\n names = readdirSync(path);\n } catch {\n return isRoot && !outputs.isDir(real) ? [path] : [];\n }\n const children = names.map((name) => {\n const child = join(path, name);\n return { path: child, targets: watchTargets(child, join(entry.real, name), outputs, false) };\n });\n const whole =\n !outputs.holds(entry.real) &&\n children.every(({ path: child, targets }) => targets.length === 1 && targets[0] === child);\n return whole ? [path] : children.flatMap(({ targets }) => targets);\n}\n\nexport function tweeTsPlugin(options: TweeTsRollupPluginOptions) {\n const outputFilename = options.outputFilename ?? 'index.html';\n // Every path this plugin's builds write: each output's folder or file, its story,\n // and the files of each bundle. A source folder may hold any of them, and none\n // may be read back as a source or rebuild under watch.\n const record = createOutputRecord(outputFilename);\n\n return {\n name: 'twee-ts',\n\n // Rollup's watch mode and CLI pass the whole config here, outputs included, so\n // they are known before the first build starts and before any is written.\n // Typed `object`: a type with only optional properties would share none with\n // Rollup's InputOptions, and the plugin would no longer be assignable to Plugin.\n options(inputOptions: object): undefined {\n const { output } = inputOptions as { readonly output?: unknown };\n for (const location of outputLocations(output)) record.addLocation(location);\n return undefined;\n },\n\n // `rollup --watch` rebuilds for the files the build registers. The story's\n // inputs are read in generateBundle, outside the module graph, so they are\n // registered here. Rollup's watcher watches a folder recursively, files added\n // to it included.\n buildStart(this: { addWatchFile: (id: string) => void; meta: { watchMode: boolean } }) {\n if (!this.meta.watchMode) return;\n const outputs = outputPaths(record.outputs());\n const extra = options.compileOptions;\n const inputs = [...options.sources, ...(extra?.headFile ? [extra.headFile] : []), ...(extra?.modules ?? [])];\n for (const input of inputs) {\n for (const target of watchTargets(resolve(input), realPathOf(input), outputs, true)) this.addWatchFile(target);\n }\n },\n\n // Runs for every output before any of them generates its bundle, when the\n // outputs are written together (as the CLI and watch mode write them).\n renderStart(outputOptions: OutputLocation): void {\n record.addLocation(outputOptions);\n },\n\n async generateBundle(\n this: {\n emitFile: (opts: { type: 'asset'; fileName: string; source: string }) => void;\n error: (error: LocatedError) => never;\n warn: (message: string) => void;\n },\n outputOptions: OutputLocation,\n bundle: Readonly<Record<string, unknown>>,\n ): Promise<void> {\n // Where this output writes the story and the bundle. A source folder may hold\n // them, or another output's, and no last build of them may be read back.\n record.addLocation(outputOptions);\n record.addFiles(outputOptions, Object.keys(bundle));\n let result: CompileResult;\n try {\n result = await compileForOutputFile(\n { sources: options.sources, formatId: options.format, ...options.compileOptions },\n record.outputs(),\n );\n } catch (e) {\n return this.error(fatalError(e));\n }\n let warnings: Diagnostic[];\n try {\n warnings = splitDiagnostics(result);\n } catch (e) {\n return this.error(e as LocatedError);\n }\n for (const w of warnings) this.warn(formatDiagnostic(w));\n this.emitFile({ type: 'asset', fileName: outputFilename, source: result.output });\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAS,aAAa,MAAc,MAAc,SAAsB,QAA2B;CACjG,IAAI,QAAQ,OAAO,IAAI,KAAM,CAAC,UAAU,QAAQ,MAAM,IAAI,GAAI,OAAO,CAAC;CACtE,IAAI;CACJ,IAAI;EACF,QAAQ,SAAS;GAAE,MAAM,SAAS,IAAI;GAAG;EAAK,IAAI,YAAY,MAAM,IAAI;CAC1E,QAAQ;EAGN,OAAO,UAAU,CAAC,QAAQ,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;CACpD;CACA,IAAI,UAAU,KAAA,GAAW,OAAO,CAAC;CACjC,IAAI,QAAQ,OAAO,MAAM,IAAI,GAAG,OAAO,CAAC;CACxC,IAAI,CAAC,MAAM,KAAK,YAAY,GAAG,OAAO,CAAC,IAAI;CAC3C,IAAI;CACJ,IAAI;EACF,QAAQ,YAAY,IAAI;CAC1B,QAAQ;EACN,OAAO,UAAU,CAAC,QAAQ,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;CACpD;CACA,MAAM,WAAW,MAAM,KAAK,SAAS;EACnC,MAAM,QAAQ,KAAK,MAAM,IAAI;EAC7B,OAAO;GAAE,MAAM;GAAO,SAAS,aAAa,OAAO,KAAK,MAAM,MAAM,IAAI,GAAG,SAAS,KAAK;EAAE;CAC7F,CAAC;CAID,OAFE,CAAC,QAAQ,MAAM,MAAM,IAAI,KACzB,SAAS,OAAO,EAAE,MAAM,OAAO,cAAc,QAAQ,WAAW,KAAK,QAAQ,OAAO,KAAK,IAC5E,CAAC,IAAI,IAAI,SAAS,SAAS,EAAE,cAAc,OAAO;AACnE;AAEA,SAAgB,aAAa,SAAoC;CAC/D,MAAM,iBAAiB,QAAQ,kBAAkB;CAIjD,MAAM,SAAS,mBAAmB,cAAc;CAEhD,OAAO;EACL,MAAM;EAMN,QAAQ,cAAiC;GACvC,MAAM,EAAE,WAAW;GACnB,KAAK,MAAM,YAAY,gBAAgB,MAAM,GAAG,OAAO,YAAY,QAAQ;EAE7E;EAMA,aAAuF;GACrF,IAAI,CAAC,KAAK,KAAK,WAAW;GAC1B,MAAM,UAAU,YAAY,OAAO,QAAQ,CAAC;GAC5C,MAAM,QAAQ,QAAQ;GACtB,MAAM,SAAS;IAAC,GAAG,QAAQ;IAAS,GAAI,OAAO,WAAW,CAAC,MAAM,QAAQ,IAAI,CAAC;IAAI,GAAI,OAAO,WAAW,CAAC;GAAE;GAC3G,KAAK,MAAM,SAAS,QAClB,KAAK,MAAM,UAAU,aAAa,QAAQ,KAAK,GAAG,WAAW,KAAK,GAAG,SAAS,IAAI,GAAG,KAAK,aAAa,MAAM;EAEjH;EAIA,YAAY,eAAqC;GAC/C,OAAO,YAAY,aAAa;EAClC;EAEA,MAAM,eAMJ,eACA,QACe;GAGf,OAAO,YAAY,aAAa;GAChC,OAAO,SAAS,eAAe,OAAO,KAAK,MAAM,CAAC;GAClD,IAAI;GACJ,IAAI;IACF,SAAS,MAAM,qBACb;KAAE,SAAS,QAAQ;KAAS,UAAU,QAAQ;KAAQ,GAAG,QAAQ;IAAe,GAChF,OAAO,QAAQ,CACjB;GACF,SAAS,GAAG;IACV,OAAO,KAAK,MAAM,WAAW,CAAC,CAAC;GACjC;GACA,IAAI;GACJ,IAAI;IACF,WAAW,iBAAiB,MAAM;GACpC,SAAS,GAAG;IACV,OAAO,KAAK,MAAM,CAAiB;GACrC;GACA,KAAK,MAAM,KAAK,UAAU,KAAK,KAAK,iBAAiB,CAAC,CAAC;GACvD,KAAK,SAAS;IAAE,MAAM;IAAS,UAAU;IAAgB,QAAQ,OAAO;GAAO,CAAC;EAClF;CACF;AACF"}
|
package/dist/plugins/vite.d.ts
CHANGED
package/dist/plugins/vite.js
CHANGED
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as toPosix, c as splitDiagnostics, d as isExcluded, f as outputPaths, h as mediaTypeFromFilename, i as outputLocations, l as compileForOutputFile, m as walkedEntry, n as isInside, o as fatalError, p as realPathOf, r as isViteConfigTemp, s as formatDiagnostic, t as createOutputRecord, u as getFilenames } from "../paths-DgO9oo6G.js";
|
|
2
2
|
import { readdirSync, statSync } from "node:fs";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { join, relative, resolve } from "node:path";
|
|
4
4
|
import { stripVTControlCharacters } from "node:util";
|
|
5
5
|
import { build, version } from "vite";
|
|
6
|
-
//#region src/plugins/paths.ts
|
|
7
|
-
/**
|
|
8
|
-
* Path helpers for the Vite plugin. Vite reports module ids with forward
|
|
9
|
-
* slashes on every platform, while node:path gives backslashes on Windows, so
|
|
10
|
-
* the plugin compares paths in forward-slash form only.
|
|
11
|
-
*/
|
|
12
|
-
/** The path with Windows separators turned into forward slashes. */
|
|
13
|
-
function toPosix(path) {
|
|
14
|
-
return path.replace(/\\/g, "/");
|
|
15
|
-
}
|
|
16
|
-
/** Whether `file` is one of `dirs` or inside one of them. All paths in forward-slash form. */
|
|
17
|
-
function isInside(file, dirs) {
|
|
18
|
-
return dirs.some((dir) => file === dir || file.startsWith(dir.endsWith("/") ? dir : `${dir}/`));
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Whether `file` is a temporary copy of a Vite config file. Vite writes one next
|
|
22
|
-
* to the config file each time it loads it (when no node_modules folder is
|
|
23
|
-
* above the config, and always under Deno), then deletes it.
|
|
24
|
-
*/
|
|
25
|
-
function isViteConfigTemp(file) {
|
|
26
|
-
return /\.timestamp-\d+-[0-9a-f]*\.mjs$/.test(file);
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
6
|
//#region src/plugins/vite.ts
|
|
30
7
|
/**
|
|
31
8
|
* Ready-made Vite plugin for twee-ts.
|
|
@@ -141,49 +118,104 @@ function headInputs(options) {
|
|
|
141
118
|
const extra = options.compileOptions;
|
|
142
119
|
return [...extra?.headFile ? [extra.headFile] : [], ...extra?.modules ?? []].map((p) => toPosix(resolve(p)));
|
|
143
120
|
}
|
|
144
|
-
/**
|
|
145
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Whether a file (forward-slash path) is a source `exclude` matches. `exclude`
|
|
123
|
+
* never applies to the head file and modules.
|
|
124
|
+
*/
|
|
125
|
+
function excludedByGlob(options) {
|
|
146
126
|
const exclude = options.compileOptions?.exclude ?? [];
|
|
147
127
|
const notExcludable = headInputs(options);
|
|
148
128
|
return (file) => isExcluded(file, exclude) && !isInside(file, notExcludable);
|
|
149
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Where a build with this config writes: each output's folder, the bundler's
|
|
132
|
+
* `output.dir` or else `build.outDir`, or the bundler's `output.file`. Vite
|
|
133
|
+
* resolves an `output.dir` against the root when it empties the folder and
|
|
134
|
+
* copies the public files into it, while the bundler resolves it against the
|
|
135
|
+
* working directory when it writes; both count.
|
|
136
|
+
*/
|
|
137
|
+
function configOutputLocations(config) {
|
|
138
|
+
const outDir = resolve(config.root, config.build.outDir);
|
|
139
|
+
const option = config.build[viteMajor >= 8 ? "rolldownOptions" : "rollupOptions"]?.output;
|
|
140
|
+
return (option === void 0 ? [{}] : Array.isArray(option) ? option : [option]).flatMap((output) => {
|
|
141
|
+
const [location] = outputLocations(output);
|
|
142
|
+
if (location === void 0) return [{ dir: outDir }];
|
|
143
|
+
if (location.dir === void 0) return [location];
|
|
144
|
+
return [{ dir: resolve(location.dir) }, { dir: resolve(config.root, location.dir) }];
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Every path a build with this config writes, as far as the config tells: each
|
|
149
|
+
* output's folder (see configOutputLocations), the story in it, and the copies
|
|
150
|
+
* of the public files Vite puts there. The plugin adds the files each bundle
|
|
151
|
+
* writes as it builds (see createOutputRecord).
|
|
152
|
+
*/
|
|
153
|
+
function configOutputs(config, outputFilename) {
|
|
154
|
+
const record = createOutputRecord(outputFilename);
|
|
155
|
+
const publicFiles = config.build.copyPublicDir && config.publicDir ? getFilenames([config.publicDir]).filenames.map((file) => relative(config.publicDir, resolve(file))) : [];
|
|
156
|
+
for (const location of configOutputLocations(config)) {
|
|
157
|
+
record.addLocation(location);
|
|
158
|
+
record.addFiles(location, publicFiles);
|
|
159
|
+
}
|
|
160
|
+
return record.outputs();
|
|
161
|
+
}
|
|
162
|
+
/** Both builds' outputs together. */
|
|
163
|
+
function mergeOutputs(a, b) {
|
|
164
|
+
return {
|
|
165
|
+
files: [...a.files, ...b.files],
|
|
166
|
+
dirs: [...a.dirs, ...b.dirs]
|
|
167
|
+
};
|
|
168
|
+
}
|
|
150
169
|
/** Absolute forward-slash paths whose changes recompile the story: sources, head file, modules. */
|
|
151
170
|
function watchedInputs(options) {
|
|
152
171
|
return [...options.sources.map((p) => toPosix(resolve(p))), ...headInputs(options)];
|
|
153
172
|
}
|
|
154
173
|
/**
|
|
155
174
|
* What `vite build --watch` watches for the story: every file under `inputs`
|
|
156
|
-
* (forward-slash paths) but those `skip` returns
|
|
157
|
-
* under them. The bundler watches each path on its
|
|
158
|
-
* folder is listed for the files added to it or
|
|
175
|
+
* (forward-slash paths) that source discovery reads, but those `skip` returns
|
|
176
|
+
* true for, and every folder under them. The bundler watches each path on its
|
|
177
|
+
* own, not recursively, so a folder is listed for the files added to it or
|
|
178
|
+
* deleted from it. As in source discovery, a link to a folder is not followed.
|
|
179
|
+
*
|
|
180
|
+
* A watched folder may still report changes in its subfolders (Rolldown's
|
|
181
|
+
* watcher on Linux does), so no path the build writes (`outputs`) is listed, nor
|
|
182
|
+
* a folder that holds one: writing the outputs would start the next build. A file
|
|
183
|
+
* added straight to such a folder is found when another change starts a build.
|
|
159
184
|
*/
|
|
160
|
-
function buildWatchTargets(inputs, skip) {
|
|
185
|
+
function buildWatchTargets(inputs, skip, outputs) {
|
|
161
186
|
const targets = [];
|
|
162
|
-
const walk = (path) => {
|
|
163
|
-
|
|
187
|
+
const walk = (path, real, isRoot) => {
|
|
188
|
+
if (outputs.isFile(real) || !isRoot && outputs.isDir(real)) return;
|
|
189
|
+
let entry;
|
|
190
|
+
let names;
|
|
164
191
|
try {
|
|
165
|
-
|
|
192
|
+
entry = isRoot ? {
|
|
193
|
+
stat: statSync(path),
|
|
194
|
+
real
|
|
195
|
+
} : walkedEntry(path, real);
|
|
196
|
+
if (entry === void 0 || outputs.isFile(entry.real)) return;
|
|
197
|
+
if (!entry.stat.isDirectory()) {
|
|
166
198
|
if (!skip(path)) targets.push(path);
|
|
167
199
|
return;
|
|
168
200
|
}
|
|
169
|
-
|
|
201
|
+
names = readdirSync(path);
|
|
170
202
|
} catch {
|
|
171
203
|
return;
|
|
172
204
|
}
|
|
173
|
-
targets.push(path);
|
|
174
|
-
for (const
|
|
205
|
+
if (!outputs.holds(entry.real)) targets.push(path);
|
|
206
|
+
for (const name of names) walk(`${path}/${name}`, join(entry.real, name), false);
|
|
175
207
|
};
|
|
176
|
-
for (const input of inputs) walk(input);
|
|
208
|
+
for (const input of inputs) walk(input, realPathOf(input), true);
|
|
177
209
|
return targets;
|
|
178
210
|
}
|
|
179
211
|
/**
|
|
180
|
-
* Every file under `inputs` (forward-slash paths)
|
|
181
|
-
*
|
|
182
|
-
* file replaced by a new one).
|
|
212
|
+
* Every file under `inputs` (forward-slash paths) that source discovery reads,
|
|
213
|
+
* leaving out `outputs`, but those `skip` returns true for, with what a change to
|
|
214
|
+
* it alters: modification time, size and inode (a file replaced by a new one).
|
|
183
215
|
*/
|
|
184
|
-
function inputFiles(inputs, skip) {
|
|
216
|
+
function inputFiles(inputs, skip, outputs) {
|
|
185
217
|
const files = /* @__PURE__ */ new Map();
|
|
186
|
-
for (const filename of getFilenames(
|
|
218
|
+
for (const filename of getFilenames(inputs, outputs).filenames) {
|
|
187
219
|
const file = toPosix(resolve(filename));
|
|
188
220
|
if (skip(file)) continue;
|
|
189
221
|
try {
|
|
@@ -377,7 +409,9 @@ function tweeTsPlugin(options) {
|
|
|
377
409
|
const cache = /* @__PURE__ */ new Map();
|
|
378
410
|
let innerBuild = false;
|
|
379
411
|
let building = false;
|
|
380
|
-
let
|
|
412
|
+
let buildConfig;
|
|
413
|
+
const record = createOutputRecord(outputFilename);
|
|
414
|
+
const allOutputs = (config) => mergeOutputs(configOutputs(config, outputFilename), record.outputs());
|
|
381
415
|
if (options.entry && viteMajor < 8) throw new Error(`twee-ts: the entry option needs Vite 8 or newer (found ${version}).`);
|
|
382
416
|
return {
|
|
383
417
|
name: "twee-ts",
|
|
@@ -390,13 +424,16 @@ function tweeTsPlugin(options) {
|
|
|
390
424
|
return { build: inputOnly(EMPTY_INPUT) };
|
|
391
425
|
},
|
|
392
426
|
configResolved(config) {
|
|
393
|
-
if (innerBuild
|
|
427
|
+
if (innerBuild) return;
|
|
428
|
+
if (building) buildConfig = config;
|
|
429
|
+
if (!options.entry) return;
|
|
394
430
|
const sources = options.sources.map((p) => toPosix(resolve(p)));
|
|
395
431
|
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\`.`);
|
|
396
432
|
},
|
|
397
433
|
buildStart() {
|
|
398
|
-
if (innerBuild || !building || !this.meta.watchMode) return;
|
|
399
|
-
|
|
434
|
+
if (innerBuild || !building || !this.meta.watchMode || buildConfig === void 0) return;
|
|
435
|
+
const outputs = outputPaths(allOutputs(buildConfig));
|
|
436
|
+
for (const target of buildWatchTargets(watchedInputs(options), excludedByGlob(options), outputs)) this.addWatchFile(target);
|
|
400
437
|
},
|
|
401
438
|
watchChange(id) {
|
|
402
439
|
if (innerBuild) return;
|
|
@@ -411,13 +448,16 @@ function tweeTsPlugin(options) {
|
|
|
411
448
|
},
|
|
412
449
|
generateBundle: {
|
|
413
450
|
order: "post",
|
|
414
|
-
async handler(
|
|
451
|
+
async handler(outputOptions, bundle) {
|
|
415
452
|
if (innerBuild) return;
|
|
416
453
|
for (const [fileName, item] of Object.entries(bundle)) if (item.type === "chunk" && item.facadeModuleId === RESOLVED_EMPTY_INPUT) delete bundle[fileName];
|
|
454
|
+
record.addLocation(outputOptions);
|
|
455
|
+
record.addFiles(outputOptions, Object.keys(bundle));
|
|
456
|
+
const outputs = buildConfig === void 0 ? record.outputs() : allOutputs(buildConfig);
|
|
417
457
|
const entry = options.entry ? takeEntryFromBundle(bundle) : void 0;
|
|
418
458
|
let result;
|
|
419
459
|
try {
|
|
420
|
-
result = await
|
|
460
|
+
result = await compileForOutputFile(buildCompileOptions(options, entry), outputs, cache);
|
|
421
461
|
} catch (e) {
|
|
422
462
|
return this.error(fatalError(e));
|
|
423
463
|
}
|
|
@@ -440,7 +480,14 @@ function tweeTsPlugin(options) {
|
|
|
440
480
|
const base = server.config.base;
|
|
441
481
|
const servePaths = outputFilename === "index.html" ? [base, `${base}index.html`] : [`${base}${outputFilename}`];
|
|
442
482
|
const inputs = watchedInputs(options);
|
|
443
|
-
|
|
483
|
+
let outputs = allOutputs(server.config);
|
|
484
|
+
let output = outputPaths(outputs);
|
|
485
|
+
const refreshOutputs = () => {
|
|
486
|
+
outputs = allOutputs(server.config);
|
|
487
|
+
output = outputPaths(outputs);
|
|
488
|
+
};
|
|
489
|
+
const excludedGlob = excludedByGlob(options);
|
|
490
|
+
const excluded = (file) => excludedGlob(file) || output.isOutput(file, inputs);
|
|
444
491
|
const entryPath = options.entry ? resolve(options.entry) : void 0;
|
|
445
492
|
const root = toPosix(server.config.root);
|
|
446
493
|
server.watcher.add(inputs);
|
|
@@ -454,15 +501,18 @@ function tweeTsPlugin(options) {
|
|
|
454
501
|
let closed = false;
|
|
455
502
|
let compiledInputs = /* @__PURE__ */ new Map();
|
|
456
503
|
let catchingUp;
|
|
457
|
-
|
|
504
|
+
const closeWatcher = server.watcher.close.bind(server.watcher);
|
|
505
|
+
server.watcher.close = async () => {
|
|
458
506
|
closed = true;
|
|
459
507
|
clearTimeout(timer);
|
|
460
508
|
pending.clear();
|
|
509
|
+
return closeWatcher();
|
|
461
510
|
};
|
|
462
511
|
const touchesEntry = (file) => entryPath !== void 0 && (entryStale ? isInside(file, [root]) : entry?.files.has(file) ?? false);
|
|
463
512
|
const rebuild = async (changed, initial = false) => {
|
|
464
513
|
if (closed) return;
|
|
465
|
-
|
|
514
|
+
refreshOutputs();
|
|
515
|
+
compiledInputs = inputFiles(inputs, excludedGlob, outputs);
|
|
466
516
|
for (const key of [...cache.keys()]) if (changed.has(toPosix(resolve(key)))) cache.delete(key);
|
|
467
517
|
try {
|
|
468
518
|
if (entryPath && (entryStale || [...changed].some(touchesEntry))) {
|
|
@@ -470,7 +520,7 @@ function tweeTsPlugin(options) {
|
|
|
470
520
|
entry = await bundleEntryForDev(server.config, entryPath);
|
|
471
521
|
entryStale = false;
|
|
472
522
|
}
|
|
473
|
-
const result = await
|
|
523
|
+
const result = await compileForOutputFile(buildCompileOptions(options, entry), outputs, cache);
|
|
474
524
|
for (const w of splitDiagnostics(result)) server.config.logger.warn(`[twee-ts] ${formatDiagnostic(w)}`);
|
|
475
525
|
html = injectViteClient(result.output, base);
|
|
476
526
|
lastError = void 0;
|
|
@@ -506,7 +556,7 @@ function tweeTsPlugin(options) {
|
|
|
506
556
|
const catchUp = () => {
|
|
507
557
|
catchingUp ??= (async () => {
|
|
508
558
|
await queue;
|
|
509
|
-
const changed = filesChanged(compiledInputs, inputFiles(inputs,
|
|
559
|
+
const changed = filesChanged(compiledInputs, inputFiles(inputs, excludedGlob, outputs));
|
|
510
560
|
if (changed.size === 0) return;
|
|
511
561
|
for (const file of pending) changed.add(file);
|
|
512
562
|
pending = /* @__PURE__ */ new Set();
|
|
@@ -543,9 +593,6 @@ function tweeTsPlugin(options) {
|
|
|
543
593
|
}
|
|
544
594
|
next();
|
|
545
595
|
});
|
|
546
|
-
},
|
|
547
|
-
closeBundle() {
|
|
548
|
-
stopDev?.();
|
|
549
596
|
}
|
|
550
597
|
};
|
|
551
598
|
}
|