@rohal12/twee-ts 1.17.1 → 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 +1914 -580
- package/dist/bin/twee-ts.js.map +1 -1
- package/dist/index.cjs +1911 -562
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -52
- package/dist/index.d.ts +139 -52
- package/dist/index.js +1912 -564
- package/dist/index.js.map +1 -1
- package/dist/{paths-w4ulhCFb.js → paths-DgO9oo6G.js} +1634 -485
- package/dist/paths-DgO9oo6G.js.map +1 -0
- package/dist/plugins/rollup.d.ts +3 -4
- package/dist/plugins/rollup.js +52 -28
- package/dist/plugins/rollup.js.map +1 -1
- package/dist/plugins/vite.d.ts +1 -1
- package/dist/plugins/vite.js +95 -50
- 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/paths-w4ulhCFb.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 {
|
|
@@ -30,12 +30,14 @@ export interface TweeTsRollupPluginOptions {
|
|
|
30
30
|
}
|
|
31
31
|
export declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
|
|
32
32
|
name: string;
|
|
33
|
+
options(inputOptions: object): undefined;
|
|
33
34
|
buildStart(this: {
|
|
34
35
|
addWatchFile: (id: string) => void;
|
|
35
36
|
meta: {
|
|
36
37
|
watchMode: boolean;
|
|
37
38
|
};
|
|
38
39
|
}): void;
|
|
40
|
+
renderStart(outputOptions: OutputLocation): void;
|
|
39
41
|
generateBundle(this: {
|
|
40
42
|
emitFile: (opts: {
|
|
41
43
|
type: 'asset';
|
|
@@ -44,9 +46,6 @@ export declare function tweeTsPlugin(options: TweeTsRollupPluginOptions): {
|
|
|
44
46
|
}) => void;
|
|
45
47
|
error: (error: LocatedError) => never;
|
|
46
48
|
warn: (message: string) => void;
|
|
47
|
-
meta: {
|
|
48
|
-
watchMode: boolean;
|
|
49
|
-
};
|
|
50
49
|
}, outputOptions: OutputLocation, bundle: Readonly<Record<string, unknown>>): Promise<void>;
|
|
51
50
|
};
|
|
52
51
|
//#endregion
|
package/dist/plugins/rollup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readdirSync } from "node:fs";
|
|
3
|
-
import { join, resolve
|
|
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";
|
|
4
4
|
//#region src/plugins/rollup.ts
|
|
5
5
|
/**
|
|
6
6
|
* Ready-made Rollup plugin for twee-ts.
|
|
@@ -8,52 +8,80 @@ import { join, resolve, sep } from "node:path";
|
|
|
8
8
|
* and emit nothing; warnings go through Rollup's warnings.
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
|
-
* What `rollup --watch` watches for the input at
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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`.
|
|
16
22
|
*/
|
|
17
|
-
function watchTargets(path,
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
let entries;
|
|
23
|
+
function watchTargets(path, real, outputs, isRoot) {
|
|
24
|
+
if (outputs.isFile(real) || !isRoot && outputs.isDir(real)) return [];
|
|
25
|
+
let entry;
|
|
21
26
|
try {
|
|
22
|
-
|
|
27
|
+
entry = isRoot ? {
|
|
28
|
+
stat: statSync(path),
|
|
29
|
+
real
|
|
30
|
+
} : walkedEntry(path, real);
|
|
23
31
|
} catch {
|
|
24
|
-
return [path];
|
|
32
|
+
return isRoot && !outputs.isDir(real) ? [path] : [];
|
|
25
33
|
}
|
|
26
|
-
|
|
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);
|
|
27
51
|
}
|
|
28
52
|
function tweeTsPlugin(options) {
|
|
29
53
|
const outputFilename = options.outputFilename ?? "index.html";
|
|
30
|
-
|
|
31
|
-
let writing = [];
|
|
54
|
+
const record = createOutputRecord(outputFilename);
|
|
32
55
|
return {
|
|
33
56
|
name: "twee-ts",
|
|
57
|
+
options(inputOptions) {
|
|
58
|
+
const { output } = inputOptions;
|
|
59
|
+
for (const location of outputLocations(output)) record.addLocation(location);
|
|
60
|
+
},
|
|
34
61
|
buildStart() {
|
|
35
62
|
if (!this.meta.watchMode) return;
|
|
36
|
-
|
|
37
|
-
written = writing;
|
|
38
|
-
writing = [];
|
|
39
|
-
}
|
|
63
|
+
const outputs = outputPaths(record.outputs());
|
|
40
64
|
const extra = options.compileOptions;
|
|
41
65
|
const inputs = [
|
|
42
66
|
...options.sources,
|
|
43
67
|
...extra?.headFile ? [extra.headFile] : [],
|
|
44
68
|
...extra?.modules ?? []
|
|
45
69
|
];
|
|
46
|
-
for (const input of inputs) for (const target of watchTargets(resolve(input),
|
|
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);
|
|
47
74
|
},
|
|
48
75
|
async generateBundle(outputOptions, bundle) {
|
|
49
|
-
|
|
76
|
+
record.addLocation(outputOptions);
|
|
77
|
+
record.addFiles(outputOptions, Object.keys(bundle));
|
|
50
78
|
let result;
|
|
51
79
|
try {
|
|
52
80
|
result = await compileForOutputFile({
|
|
53
81
|
sources: options.sources,
|
|
54
82
|
formatId: options.format,
|
|
55
83
|
...options.compileOptions
|
|
56
|
-
},
|
|
84
|
+
}, record.outputs());
|
|
57
85
|
} catch (e) {
|
|
58
86
|
return this.error(fatalError(e));
|
|
59
87
|
}
|
|
@@ -69,10 +97,6 @@ function tweeTsPlugin(options) {
|
|
|
69
97
|
fileName: outputFilename,
|
|
70
98
|
source: result.output
|
|
71
99
|
});
|
|
72
|
-
if (this.meta.watchMode) for (const fileName of /* @__PURE__ */ new Set([...Object.keys(bundle), outputFilename])) {
|
|
73
|
-
const path = emittedFilePath(outputOptions, fileName);
|
|
74
|
-
if (path !== void 0) writing.push(path);
|
|
75
|
-
}
|
|
76
100
|
}
|
|
77
101
|
};
|
|
78
102
|
}
|
|
@@ -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 { readdirSync } from 'node:fs';\nimport { join, resolve
|
|
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,6 +1,6 @@
|
|
|
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
6
|
//#region src/plugins/vite.ts
|
|
@@ -119,23 +119,52 @@ function headInputs(options) {
|
|
|
119
119
|
return [...extra?.headFile ? [extra.headFile] : [], ...extra?.modules ?? []].map((p) => toPosix(resolve(p)));
|
|
120
120
|
}
|
|
121
121
|
/**
|
|
122
|
-
* Whether a file (forward-slash path) is
|
|
123
|
-
*
|
|
124
|
-
* `exclude` matches. `exclude` never applies to the head file and modules.
|
|
122
|
+
* Whether a file (forward-slash path) is a source `exclude` matches. `exclude`
|
|
123
|
+
* never applies to the head file and modules.
|
|
125
124
|
*/
|
|
126
|
-
function
|
|
125
|
+
function excludedByGlob(options) {
|
|
127
126
|
const exclude = options.compileOptions?.exclude ?? [];
|
|
128
127
|
const notExcludable = headInputs(options);
|
|
129
|
-
|
|
130
|
-
return (file) => file === output || isExcluded(file, exclude) && !isInside(file, notExcludable);
|
|
128
|
+
return (file) => isExcluded(file, exclude) && !isInside(file, notExcludable);
|
|
131
129
|
}
|
|
132
130
|
/**
|
|
133
|
-
* Where a build
|
|
134
|
-
*
|
|
135
|
-
*
|
|
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
136
|
*/
|
|
137
|
-
function
|
|
138
|
-
|
|
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
|
+
};
|
|
139
168
|
}
|
|
140
169
|
/** Absolute forward-slash paths whose changes recompile the story: sources, head file, modules. */
|
|
141
170
|
function watchedInputs(options) {
|
|
@@ -143,43 +172,50 @@ function watchedInputs(options) {
|
|
|
143
172
|
}
|
|
144
173
|
/**
|
|
145
174
|
* What `vite build --watch` watches for the story: every file under `inputs`
|
|
146
|
-
* (forward-slash paths) but those `skip` returns
|
|
147
|
-
* under them. The bundler watches each path on its
|
|
148
|
-
* 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.
|
|
149
179
|
*
|
|
150
180
|
* A watched folder may still report changes in its subfolders (Rolldown's
|
|
151
|
-
* watcher on Linux does), so no
|
|
152
|
-
*
|
|
153
|
-
*
|
|
154
|
-
* change starts a build.
|
|
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.
|
|
155
184
|
*/
|
|
156
|
-
function buildWatchTargets(inputs, skip,
|
|
185
|
+
function buildWatchTargets(inputs, skip, outputs) {
|
|
157
186
|
const targets = [];
|
|
158
|
-
const walk = (path) => {
|
|
159
|
-
|
|
187
|
+
const walk = (path, real, isRoot) => {
|
|
188
|
+
if (outputs.isFile(real) || !isRoot && outputs.isDir(real)) return;
|
|
189
|
+
let entry;
|
|
190
|
+
let names;
|
|
160
191
|
try {
|
|
161
|
-
|
|
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()) {
|
|
162
198
|
if (!skip(path)) targets.push(path);
|
|
163
199
|
return;
|
|
164
200
|
}
|
|
165
|
-
|
|
201
|
+
names = readdirSync(path);
|
|
166
202
|
} catch {
|
|
167
203
|
return;
|
|
168
204
|
}
|
|
169
|
-
if (
|
|
170
|
-
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);
|
|
171
207
|
};
|
|
172
|
-
for (const input of inputs) walk(input);
|
|
208
|
+
for (const input of inputs) walk(input, realPathOf(input), true);
|
|
173
209
|
return targets;
|
|
174
210
|
}
|
|
175
211
|
/**
|
|
176
|
-
* Every file under `inputs` (forward-slash paths)
|
|
177
|
-
*
|
|
178
|
-
* 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).
|
|
179
215
|
*/
|
|
180
|
-
function inputFiles(inputs, skip) {
|
|
216
|
+
function inputFiles(inputs, skip, outputs) {
|
|
181
217
|
const files = /* @__PURE__ */ new Map();
|
|
182
|
-
for (const filename of getFilenames(
|
|
218
|
+
for (const filename of getFilenames(inputs, outputs).filenames) {
|
|
183
219
|
const file = toPosix(resolve(filename));
|
|
184
220
|
if (skip(file)) continue;
|
|
185
221
|
try {
|
|
@@ -373,8 +409,9 @@ function tweeTsPlugin(options) {
|
|
|
373
409
|
const cache = /* @__PURE__ */ new Map();
|
|
374
410
|
let innerBuild = false;
|
|
375
411
|
let building = false;
|
|
376
|
-
let
|
|
377
|
-
|
|
412
|
+
let buildConfig;
|
|
413
|
+
const record = createOutputRecord(outputFilename);
|
|
414
|
+
const allOutputs = (config) => mergeOutputs(configOutputs(config, outputFilename), record.outputs());
|
|
378
415
|
if (options.entry && viteMajor < 8) throw new Error(`twee-ts: the entry option needs Vite 8 or newer (found ${version}).`);
|
|
379
416
|
return {
|
|
380
417
|
name: "twee-ts",
|
|
@@ -388,15 +425,15 @@ function tweeTsPlugin(options) {
|
|
|
388
425
|
},
|
|
389
426
|
configResolved(config) {
|
|
390
427
|
if (innerBuild) return;
|
|
391
|
-
|
|
428
|
+
if (building) buildConfig = config;
|
|
392
429
|
if (!options.entry) return;
|
|
393
430
|
const sources = options.sources.map((p) => toPosix(resolve(p)));
|
|
394
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\`.`);
|
|
395
432
|
},
|
|
396
433
|
buildStart() {
|
|
397
|
-
if (innerBuild || !building || !this.meta.watchMode) return;
|
|
398
|
-
const
|
|
399
|
-
for (const target of buildWatchTargets(watchedInputs(options),
|
|
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;
|
|
@@ -414,11 +451,13 @@ function tweeTsPlugin(options) {
|
|
|
414
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
|
-
const outFile = emittedFilePath(outputOptions, outputFilename) ?? builtStory;
|
|
419
458
|
let result;
|
|
420
459
|
try {
|
|
421
|
-
result = await compileForOutputFile(buildCompileOptions(options, entry),
|
|
460
|
+
result = await compileForOutputFile(buildCompileOptions(options, entry), outputs, cache);
|
|
422
461
|
} catch (e) {
|
|
423
462
|
return this.error(fatalError(e));
|
|
424
463
|
}
|
|
@@ -441,8 +480,14 @@ function tweeTsPlugin(options) {
|
|
|
441
480
|
const base = server.config.base;
|
|
442
481
|
const servePaths = outputFilename === "index.html" ? [base, `${base}index.html`] : [`${base}${outputFilename}`];
|
|
443
482
|
const inputs = watchedInputs(options);
|
|
444
|
-
|
|
445
|
-
|
|
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);
|
|
446
491
|
const entryPath = options.entry ? resolve(options.entry) : void 0;
|
|
447
492
|
const root = toPosix(server.config.root);
|
|
448
493
|
server.watcher.add(inputs);
|
|
@@ -456,15 +501,18 @@ function tweeTsPlugin(options) {
|
|
|
456
501
|
let closed = false;
|
|
457
502
|
let compiledInputs = /* @__PURE__ */ new Map();
|
|
458
503
|
let catchingUp;
|
|
459
|
-
|
|
504
|
+
const closeWatcher = server.watcher.close.bind(server.watcher);
|
|
505
|
+
server.watcher.close = async () => {
|
|
460
506
|
closed = true;
|
|
461
507
|
clearTimeout(timer);
|
|
462
508
|
pending.clear();
|
|
509
|
+
return closeWatcher();
|
|
463
510
|
};
|
|
464
511
|
const touchesEntry = (file) => entryPath !== void 0 && (entryStale ? isInside(file, [root]) : entry?.files.has(file) ?? false);
|
|
465
512
|
const rebuild = async (changed, initial = false) => {
|
|
466
513
|
if (closed) return;
|
|
467
|
-
|
|
514
|
+
refreshOutputs();
|
|
515
|
+
compiledInputs = inputFiles(inputs, excludedGlob, outputs);
|
|
468
516
|
for (const key of [...cache.keys()]) if (changed.has(toPosix(resolve(key)))) cache.delete(key);
|
|
469
517
|
try {
|
|
470
518
|
if (entryPath && (entryStale || [...changed].some(touchesEntry))) {
|
|
@@ -472,7 +520,7 @@ function tweeTsPlugin(options) {
|
|
|
472
520
|
entry = await bundleEntryForDev(server.config, entryPath);
|
|
473
521
|
entryStale = false;
|
|
474
522
|
}
|
|
475
|
-
const result = await compileForOutputFile(buildCompileOptions(options, entry),
|
|
523
|
+
const result = await compileForOutputFile(buildCompileOptions(options, entry), outputs, cache);
|
|
476
524
|
for (const w of splitDiagnostics(result)) server.config.logger.warn(`[twee-ts] ${formatDiagnostic(w)}`);
|
|
477
525
|
html = injectViteClient(result.output, base);
|
|
478
526
|
lastError = void 0;
|
|
@@ -508,7 +556,7 @@ function tweeTsPlugin(options) {
|
|
|
508
556
|
const catchUp = () => {
|
|
509
557
|
catchingUp ??= (async () => {
|
|
510
558
|
await queue;
|
|
511
|
-
const changed = filesChanged(compiledInputs, inputFiles(inputs,
|
|
559
|
+
const changed = filesChanged(compiledInputs, inputFiles(inputs, excludedGlob, outputs));
|
|
512
560
|
if (changed.size === 0) return;
|
|
513
561
|
for (const file of pending) changed.add(file);
|
|
514
562
|
pending = /* @__PURE__ */ new Set();
|
|
@@ -545,9 +593,6 @@ function tweeTsPlugin(options) {
|
|
|
545
593
|
}
|
|
546
594
|
next();
|
|
547
595
|
});
|
|
548
|
-
},
|
|
549
|
-
closeBundle() {
|
|
550
|
-
stopDev?.();
|
|
551
596
|
}
|
|
552
597
|
};
|
|
553
598
|
}
|