@eighty4/dank 0.0.4-1 → 0.0.4-3
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/client/client.js +1 -0
- package/lib/bin.ts +8 -11
- package/lib/build.ts +41 -70
- package/lib/build_tag.ts +3 -3
- package/lib/config.ts +372 -11
- package/lib/dank.ts +21 -150
- package/lib/define.ts +6 -4
- package/lib/developer.ts +146 -0
- package/lib/dirs.ts +83 -0
- package/lib/errors.ts +6 -0
- package/lib/esbuild.ts +19 -29
- package/lib/flags.ts +15 -121
- package/lib/html.ts +196 -112
- package/lib/http.ts +59 -43
- package/lib/public.ts +10 -10
- package/lib/{metadata.ts → registry.ts} +216 -83
- package/lib/serve.ts +118 -270
- package/lib/services.ts +8 -8
- package/lib/watch.ts +39 -0
- package/lib_js/bin.js +79 -85
- package/lib_js/build.js +63 -86
- package/lib_js/build_tag.js +20 -21
- package/lib_js/config.js +237 -18
- package/lib_js/dank.js +5 -122
- package/lib_js/define.js +8 -5
- package/lib_js/dirs.js +61 -0
- package/lib_js/errors.js +9 -0
- package/lib_js/esbuild.js +155 -167
- package/lib_js/flags.js +30 -123
- package/lib_js/html.js +280 -231
- package/lib_js/http.js +176 -195
- package/lib_js/public.js +45 -46
- package/lib_js/registry.js +260 -0
- package/lib_js/serve.js +109 -251
- package/lib_js/services.js +152 -171
- package/lib_js/watch.js +35 -0
- package/lib_types/dank.d.ts +13 -1
- package/package.json +10 -4
- package/client/esbuild.js +0 -91
- package/lib_js/metadata.js +0 -210
package/lib_js/html.js
CHANGED
|
@@ -1,253 +1,302 @@
|
|
|
1
|
-
import EventEmitter from
|
|
2
|
-
import { readFile } from
|
|
3
|
-
import { dirname, join, relative } from
|
|
4
|
-
import { extname } from
|
|
5
|
-
import { defaultTreeAdapter, parse, parseFragment, serialize
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
import EventEmitter from "node:events";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
4
|
+
import { extname } from "node:path/posix";
|
|
5
|
+
import { defaultTreeAdapter, parse, parseFragment, serialize } from "parse5";
|
|
6
|
+
import { DankError } from "./errors.js";
|
|
7
|
+
class HtmlEntrypoint extends EventEmitter {
|
|
8
|
+
#c;
|
|
9
|
+
#clientJS;
|
|
10
|
+
#document = defaultTreeAdapter.createDocument();
|
|
11
|
+
#entrypoints = /* @__PURE__ */ new Set();
|
|
12
|
+
// path within pages dir omitting pages/ segment
|
|
13
|
+
#fsPath;
|
|
14
|
+
#partials = [];
|
|
15
|
+
#resolver;
|
|
16
|
+
#scripts = [];
|
|
17
|
+
#update = Object();
|
|
18
|
+
#url;
|
|
19
|
+
constructor(c, resolver, url, fsPath) {
|
|
20
|
+
super({ captureRejections: true });
|
|
21
|
+
this.#c = c;
|
|
22
|
+
this.#clientJS = ClientJS.initialize(c);
|
|
23
|
+
this.#resolver = resolver;
|
|
24
|
+
this.#url = url;
|
|
25
|
+
this.#fsPath = fsPath;
|
|
26
|
+
this.on("change", this.#onChange);
|
|
27
|
+
}
|
|
28
|
+
get fsPath() {
|
|
29
|
+
return this.#fsPath;
|
|
30
|
+
}
|
|
31
|
+
get url() {
|
|
32
|
+
return this.#url;
|
|
33
|
+
}
|
|
34
|
+
async process() {
|
|
35
|
+
await this.#onChange();
|
|
36
|
+
}
|
|
37
|
+
output(hrefs) {
|
|
38
|
+
this.#injectPartials();
|
|
39
|
+
this.#rewriteHrefs(hrefs);
|
|
40
|
+
return serialize(this.#document);
|
|
41
|
+
}
|
|
42
|
+
usesPartial(fsPath) {
|
|
43
|
+
return this.#partials.some((partial) => partial.fsPath === fsPath);
|
|
44
|
+
}
|
|
45
|
+
#onChange = async () => {
|
|
46
|
+
const update = this.#update = Object();
|
|
47
|
+
let html;
|
|
48
|
+
try {
|
|
49
|
+
html = await this.#readFromPages(this.#fsPath);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
this.#error(`url \`${this.#url}\` html file \`${join(this.#c.dirs.pages, this.#fsPath)}\` does not exist`);
|
|
52
|
+
return;
|
|
43
53
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const document = parse(html);
|
|
49
|
-
const imports = {
|
|
50
|
-
partials: [],
|
|
51
|
-
scripts: [],
|
|
52
|
-
};
|
|
53
|
-
this.#collectImports(document, imports);
|
|
54
|
-
const partials = await this.#resolvePartialContent(imports.partials);
|
|
55
|
-
if (update !== this.#update) {
|
|
56
|
-
// another update has started so aborting this one
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
this.#addDecorations(document);
|
|
60
|
-
this.#update = update;
|
|
61
|
-
this.#document = document;
|
|
62
|
-
this.#partials = partials;
|
|
63
|
-
this.#scripts = imports.scripts;
|
|
64
|
-
const entrypoints = mergeEntrypoints(imports, ...partials.map(p => p.imports));
|
|
65
|
-
// this.#entrypoints = new Set(entrypoints.map(entrypoint => entrypoint.in))
|
|
66
|
-
this.emit('entrypoints', entrypoints);
|
|
67
|
-
this.emit('partials', this.#partials.map(p => p.fsPath));
|
|
68
|
-
if (this.listenerCount('output')) {
|
|
69
|
-
this.emit('output', this.output());
|
|
70
|
-
}
|
|
54
|
+
const document = parse(html);
|
|
55
|
+
const imports = {
|
|
56
|
+
partials: [],
|
|
57
|
+
scripts: []
|
|
71
58
|
};
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const fragment = parseFragment(html);
|
|
80
|
-
const imports = {
|
|
81
|
-
partials: [],
|
|
82
|
-
scripts: [],
|
|
83
|
-
};
|
|
84
|
-
this.#collectImports(fragment, imports, node => {
|
|
85
|
-
this.#rewritePartialRelativePaths(node, p.fsPath);
|
|
86
|
-
});
|
|
87
|
-
if (imports.partials.length) {
|
|
88
|
-
// todo recursive partials?
|
|
89
|
-
// await this.#resolvePartialContent(imports.partials)
|
|
90
|
-
errorExit(`partial ${p.fsPath} cannot recursively import partials`);
|
|
91
|
-
}
|
|
92
|
-
const content = {
|
|
93
|
-
...p,
|
|
94
|
-
fragment,
|
|
95
|
-
imports,
|
|
96
|
-
};
|
|
97
|
-
return content;
|
|
98
|
-
}));
|
|
99
|
-
}
|
|
100
|
-
// rewrite hrefs in a partial to be relative to the html entrypoint instead of the partial
|
|
101
|
-
#rewritePartialRelativePaths(elem, partialPath) {
|
|
102
|
-
let rewritePath = null;
|
|
103
|
-
if (elem.nodeName === 'script') {
|
|
104
|
-
rewritePath = 'src';
|
|
105
|
-
}
|
|
106
|
-
else if (elem.nodeName === 'link' &&
|
|
107
|
-
hasAttr(elem, 'rel', 'stylesheet')) {
|
|
108
|
-
rewritePath = 'href';
|
|
109
|
-
}
|
|
110
|
-
if (rewritePath !== null) {
|
|
111
|
-
const attr = getAttr(elem, rewritePath);
|
|
112
|
-
if (attr) {
|
|
113
|
-
attr.value = join(relative(dirname(this.#fsPath), dirname(partialPath)), attr.value);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
59
|
+
let partials;
|
|
60
|
+
this.#collectImports(document, imports);
|
|
61
|
+
const partialResults = await this.#resolvePartialContent(imports.partials);
|
|
62
|
+
partials = partialResults.filter((p) => p !== false);
|
|
63
|
+
if (partials.length !== partialResults.length) {
|
|
64
|
+
this.#error(`update to \`${join(this.#c.dirs.pages, this.#fsPath)}\` did not update to \`${this.#url}\` because of unresolved partials`);
|
|
65
|
+
return;
|
|
116
66
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
for (const decoration of this.#decorations) {
|
|
122
|
-
switch (decoration.type) {
|
|
123
|
-
case 'script':
|
|
124
|
-
const scriptNode = parseFragment(`<script type="module">${decoration.js}</script>`).childNodes[0];
|
|
125
|
-
const htmlNode = document.childNodes.find(node => node.nodeName === 'html');
|
|
126
|
-
const headNode = htmlNode.childNodes.find(node => node.nodeName === 'head');
|
|
127
|
-
defaultTreeAdapter.appendChild(headNode || htmlNode, scriptNode);
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
67
|
+
if (this.#clientJS !== null) {
|
|
68
|
+
const decoration = await this.#clientJS.retrieve(this.#c.esbuildPort);
|
|
69
|
+
this.#addScriptDecoration(document, decoration.js);
|
|
131
70
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
this.#rewriteHrefs(hrefs);
|
|
135
|
-
return serialize(this.#document);
|
|
136
|
-
}
|
|
137
|
-
// rewrites hrefs to content hashed urls
|
|
138
|
-
// call without hrefs to rewrite tsx? ext to js
|
|
139
|
-
#rewriteHrefs(hrefs) {
|
|
140
|
-
rewriteHrefs(this.#scripts, hrefs);
|
|
141
|
-
for (const partial of this.#partials) {
|
|
142
|
-
rewriteHrefs(partial.imports.scripts, hrefs);
|
|
143
|
-
}
|
|
71
|
+
if (update !== this.#update) {
|
|
72
|
+
return;
|
|
144
73
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
defaultTreeAdapter.insertBefore(commentNode.parentNode, node, commentNode);
|
|
152
|
-
}
|
|
153
|
-
if (this.#build.production) {
|
|
154
|
-
defaultTreeAdapter.detachNode(commentNode);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
74
|
+
this.#document = document;
|
|
75
|
+
this.#partials = partials;
|
|
76
|
+
this.#scripts = imports.scripts;
|
|
77
|
+
const entrypoints = mergeEntrypoints(imports, ...partials.map((p) => p.imports));
|
|
78
|
+
if (this.#haveEntrypointsChanged(entrypoints)) {
|
|
79
|
+
this.emit("entrypoints", entrypoints);
|
|
157
80
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
commentNode: childNode,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
else if (childNode.nodeName === 'script') {
|
|
181
|
-
const srcAttr = childNode.attrs.find(attr => attr.name === 'src');
|
|
182
|
-
if (srcAttr) {
|
|
183
|
-
collection.scripts.push(this.#parseImport('script', srcAttr.value, childNode));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
else if (childNode.nodeName === 'link' &&
|
|
187
|
-
hasAttr(childNode, 'rel', 'stylesheet')) {
|
|
188
|
-
const hrefAttr = getAttr(childNode, 'href');
|
|
189
|
-
if (hrefAttr) {
|
|
190
|
-
collection.scripts.push(this.#parseImport('style', hrefAttr.value, childNode));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else if ('childNodes' in childNode) {
|
|
194
|
-
this.#collectImports(childNode, collection);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
81
|
+
if (this.listenerCount("output")) {
|
|
82
|
+
this.emit("output", this.output());
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
#error(e) {
|
|
86
|
+
let message;
|
|
87
|
+
let error;
|
|
88
|
+
if (typeof e === "string") {
|
|
89
|
+
message = e;
|
|
90
|
+
error = new DankError(e);
|
|
91
|
+
} else {
|
|
92
|
+
message = e.message;
|
|
93
|
+
error = e;
|
|
94
|
+
}
|
|
95
|
+
if (this.listenerCount("error")) {
|
|
96
|
+
this.emit("error", error);
|
|
97
|
+
} else {
|
|
98
|
+
throw error;
|
|
197
99
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
100
|
+
}
|
|
101
|
+
#haveEntrypointsChanged(entrypoints) {
|
|
102
|
+
const set = new Set(entrypoints.map((entrypoint) => entrypoint.in));
|
|
103
|
+
const changed = set.symmetricDifference(this.#entrypoints).size > 0;
|
|
104
|
+
this.#entrypoints = set;
|
|
105
|
+
return changed;
|
|
106
|
+
}
|
|
107
|
+
async #readFromPages(p) {
|
|
108
|
+
return await readFile(this.#resolver.absPagesPath(p), "utf8");
|
|
109
|
+
}
|
|
110
|
+
async #resolvePartialContent(partials) {
|
|
111
|
+
return await Promise.all(partials.map(async (p) => {
|
|
112
|
+
let html;
|
|
113
|
+
if (isAbsolute(p.specifier)) {
|
|
114
|
+
this.#error(`partials cannot be referenced with an absolute path like \`${p.specifier}\` in webpage \`${join(this.#c.dirs.pages, this.#fsPath)}\``);
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (!this.#resolver.isPagesSubpathInPagesDir(p.fsPath)) {
|
|
118
|
+
this.#error(`partials cannot be referenced from outside the pages dir like \`${p.specifier}\` in webpage \`${join(this.#c.dirs.pages, this.#fsPath)}\``);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (extname(p.fsPath) !== ".html") {
|
|
122
|
+
this.#error(`partial path \`${p.fsPath}\` referenced by \`${this.#fsPath}\` is not a valid partial path`);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
html = await this.#readFromPages(p.fsPath);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
this.#error(`partial \`${join("pages", p.fsPath)}\` imported by \`${join("pages", this.#fsPath)}\` does not exist`);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
const fragment = parseFragment(html);
|
|
132
|
+
const imports = {
|
|
133
|
+
partials: [],
|
|
134
|
+
scripts: []
|
|
135
|
+
};
|
|
136
|
+
this.#collectImports(fragment, imports, (node) => {
|
|
137
|
+
this.#rewritePartialRelativePaths(node, p.fsPath);
|
|
138
|
+
});
|
|
139
|
+
if (imports.partials.length) {
|
|
140
|
+
this.#error(`partials cannot import another partial like \`${join(this.#c.dirs.pages, p.fsPath)}\``);
|
|
141
|
+
}
|
|
142
|
+
const content = {
|
|
143
|
+
...p,
|
|
144
|
+
fragment,
|
|
145
|
+
imports
|
|
146
|
+
};
|
|
147
|
+
return content;
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
// rewrite hrefs in a partial to be relative to the html entrypoint instead of the partial
|
|
151
|
+
#rewritePartialRelativePaths(elem, partialPath) {
|
|
152
|
+
let rewritePath = null;
|
|
153
|
+
if (elem.nodeName === "script") {
|
|
154
|
+
rewritePath = "src";
|
|
155
|
+
} else if (elem.nodeName === "link" && hasAttr(elem, "rel", "stylesheet")) {
|
|
156
|
+
rewritePath = "href";
|
|
157
|
+
}
|
|
158
|
+
if (rewritePath !== null) {
|
|
159
|
+
const attr = getAttr(elem, rewritePath);
|
|
160
|
+
if (attr) {
|
|
161
|
+
attr.value = join(relative(dirname(this.#fsPath), dirname(partialPath)), attr.value);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
#addScriptDecoration(document, js) {
|
|
166
|
+
const scriptNode = parseFragment(`<script type="module">${js}</script>`).childNodes[0];
|
|
167
|
+
const htmlNode = document.childNodes.find((node) => node.nodeName === "html");
|
|
168
|
+
const headNode = htmlNode.childNodes.find((node) => node.nodeName === "head");
|
|
169
|
+
defaultTreeAdapter.appendChild(headNode || htmlNode, scriptNode);
|
|
170
|
+
}
|
|
171
|
+
// rewrites hrefs to content hashed urls
|
|
172
|
+
// call without hrefs to rewrite tsx? ext to js
|
|
173
|
+
#rewriteHrefs(hrefs) {
|
|
174
|
+
rewriteHrefs(this.#scripts, hrefs);
|
|
175
|
+
for (const partial of this.#partials) {
|
|
176
|
+
rewriteHrefs(partial.imports.scripts, hrefs);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async #injectPartials() {
|
|
180
|
+
for (const { commentNode, fragment } of this.#partials) {
|
|
181
|
+
if (!this.#c.flags.production) {
|
|
182
|
+
defaultTreeAdapter.insertBefore(commentNode.parentNode, defaultTreeAdapter.createCommentNode(commentNode.data), commentNode);
|
|
183
|
+
}
|
|
184
|
+
for (const node of fragment.childNodes) {
|
|
185
|
+
defaultTreeAdapter.insertBefore(commentNode.parentNode, node, commentNode);
|
|
186
|
+
}
|
|
187
|
+
if (this.#c.flags.production) {
|
|
188
|
+
defaultTreeAdapter.detachNode(commentNode);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
#collectImports(node, collection, forEach) {
|
|
193
|
+
for (const childNode of node.childNodes) {
|
|
194
|
+
if (forEach && "tagName" in childNode) {
|
|
195
|
+
forEach(childNode);
|
|
196
|
+
}
|
|
197
|
+
if (childNode.nodeName === "#comment" && "data" in childNode) {
|
|
198
|
+
const partialMatch = childNode.data.match(/\{\{(?<pp>.+)\}\}/);
|
|
199
|
+
if (partialMatch) {
|
|
200
|
+
const specifier = partialMatch.groups.pp.trim();
|
|
201
|
+
collection.partials.push({
|
|
202
|
+
commentNode: childNode,
|
|
203
|
+
fsPath: join(dirname(this.#fsPath), specifier),
|
|
204
|
+
specifier
|
|
205
|
+
});
|
|
202
206
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
} else if (childNode.nodeName === "script") {
|
|
208
|
+
const srcAttr = childNode.attrs.find((attr) => attr.name === "src");
|
|
209
|
+
if (srcAttr) {
|
|
210
|
+
collection.scripts.push(this.#parseImport("script", srcAttr.value, childNode));
|
|
206
211
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
212
|
+
} else if (childNode.nodeName === "link" && hasAttr(childNode, "rel", "stylesheet")) {
|
|
213
|
+
const hrefAttr = getAttr(childNode, "href");
|
|
214
|
+
if (hrefAttr) {
|
|
215
|
+
collection.scripts.push(this.#parseImport("style", hrefAttr.value, childNode));
|
|
216
|
+
}
|
|
217
|
+
} else if ("childNodes" in childNode) {
|
|
218
|
+
this.#collectImports(childNode, collection);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
#parseImport(type, href, elem) {
|
|
223
|
+
const inPath = join(this.#c.dirs.pages, dirname(this.#fsPath), href);
|
|
224
|
+
if (!this.#resolver.isProjectSubpathInPagesDir(inPath)) {
|
|
225
|
+
throw new DankError(`href \`${href}\` in webpage \`${join(this.#c.dirs.pages, this.#fsPath)}\` cannot reference sources outside of the pages directory`);
|
|
226
|
+
}
|
|
227
|
+
let outPath = join(dirname(this.#fsPath), href);
|
|
228
|
+
if (type === "script" && !outPath.endsWith(".js")) {
|
|
229
|
+
outPath = outPath.replace(new RegExp(extname(outPath).substring(1) + "$"), "js");
|
|
216
230
|
}
|
|
231
|
+
return {
|
|
232
|
+
type,
|
|
233
|
+
href,
|
|
234
|
+
elem,
|
|
235
|
+
entrypoint: {
|
|
236
|
+
in: inPath,
|
|
237
|
+
out: outPath
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
217
241
|
}
|
|
218
242
|
function getAttr(elem, name) {
|
|
219
|
-
|
|
243
|
+
return elem.attrs.find((attr) => attr.name === name);
|
|
220
244
|
}
|
|
221
245
|
function hasAttr(elem, name, value) {
|
|
222
|
-
|
|
246
|
+
return elem.attrs.some((attr) => attr.name === name && attr.value === value);
|
|
223
247
|
}
|
|
224
248
|
function mergeEntrypoints(...imports) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
249
|
+
const entrypoints = [];
|
|
250
|
+
for (const { scripts } of imports) {
|
|
251
|
+
for (const script of scripts) {
|
|
252
|
+
entrypoints.push(script.entrypoint);
|
|
230
253
|
}
|
|
231
|
-
|
|
254
|
+
}
|
|
255
|
+
return entrypoints;
|
|
232
256
|
}
|
|
233
257
|
function rewriteHrefs(scripts, hrefs) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
else if (type === 'style') {
|
|
244
|
-
elem.attrs.find(attr => attr.name === 'href').value =
|
|
245
|
-
rewriteTo || `/${entrypoint.out}`;
|
|
246
|
-
}
|
|
258
|
+
for (const { elem, entrypoint, type } of scripts) {
|
|
259
|
+
const rewriteTo = hrefs ? hrefs.mappedHref(entrypoint.in) : null;
|
|
260
|
+
if (type === "script") {
|
|
261
|
+
if (entrypoint.in.endsWith(".tsx") || entrypoint.in.endsWith(".ts")) {
|
|
262
|
+
elem.attrs.find((attr) => attr.name === "src").value = rewriteTo || `/${entrypoint.out}`;
|
|
263
|
+
}
|
|
264
|
+
} else if (type === "style") {
|
|
265
|
+
elem.attrs.find((attr) => attr.name === "href").value = rewriteTo || `/${entrypoint.out}`;
|
|
247
266
|
}
|
|
267
|
+
}
|
|
248
268
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
269
|
+
class ClientJS {
|
|
270
|
+
static #instance = null;
|
|
271
|
+
static initialize(c) {
|
|
272
|
+
if (c.mode === "build" || c.flags.preview) {
|
|
273
|
+
return null;
|
|
274
|
+
} else if (!ClientJS.#instance) {
|
|
275
|
+
ClientJS.#instance = new ClientJS(c.esbuildPort);
|
|
276
|
+
}
|
|
277
|
+
return ClientJS.#instance;
|
|
278
|
+
}
|
|
279
|
+
#esbuildPort;
|
|
280
|
+
#read;
|
|
281
|
+
#result;
|
|
282
|
+
constructor(esbuildPort) {
|
|
283
|
+
this.#esbuildPort = esbuildPort;
|
|
284
|
+
this.#read = readFile(resolve(import.meta.dirname, join("..", "client", "client.js")), "utf-8");
|
|
285
|
+
this.#result = this.#read.then(this.#transform);
|
|
286
|
+
}
|
|
287
|
+
async retrieve(esbuildPort) {
|
|
288
|
+
if (esbuildPort !== this.#esbuildPort) {
|
|
289
|
+
this.#result = this.#read.then(this.#transform);
|
|
290
|
+
}
|
|
291
|
+
return await this.#result;
|
|
292
|
+
}
|
|
293
|
+
#transform = (js) => {
|
|
294
|
+
return {
|
|
295
|
+
type: "script",
|
|
296
|
+
js: js.replace("3995", "" + this.#esbuildPort)
|
|
297
|
+
};
|
|
298
|
+
};
|
|
253
299
|
}
|
|
300
|
+
export {
|
|
301
|
+
HtmlEntrypoint
|
|
302
|
+
};
|