@jsenv/core 38.4.17 → 38.4.18
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/html/directory.html +18 -0
- package/dist/html/html_404_and_parent_dir.html +19 -0
- package/dist/html/html_404_and_parent_dir_is_empty.html +16 -0
- package/dist/html/html_syntax_error.html +14 -0
- package/dist/js/autoreload.js +135 -132
- package/dist/jsenv_core.js +302 -28
- package/package.json +5 -6
- package/src/dev/start_dev_server.js +5 -0
- package/src/plugins/autoreload/client/autoreload.js +138 -137
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +10 -1
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +4 -1
- package/src/plugins/protocol_file/directory.html +20 -0
- package/src/plugins/protocol_file/html_404_and_parent_dir.html +21 -0
- package/src/plugins/protocol_file/html_404_and_parent_dir_is_empty.html +18 -0
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +173 -13
- package/src/plugins/reference_analysis/html/html_syntax_error.html +14 -0
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +95 -3
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +1 -1
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
3
|
+
import { generateContentFrame } from "@jsenv/humanize";
|
|
1
4
|
import {
|
|
2
5
|
parseHtml,
|
|
3
6
|
visitHtmlNodes,
|
|
@@ -20,6 +23,11 @@ import {
|
|
|
20
23
|
normalizeImportMap,
|
|
21
24
|
} from "@jsenv/importmap";
|
|
22
25
|
|
|
26
|
+
const htmlSyntaxErrorFileUrl = new URL(
|
|
27
|
+
"./html_syntax_error.html",
|
|
28
|
+
import.meta.url,
|
|
29
|
+
);
|
|
30
|
+
|
|
23
31
|
export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
24
32
|
inlineContent,
|
|
25
33
|
inlineConvertedScript,
|
|
@@ -127,14 +135,43 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
127
135
|
},
|
|
128
136
|
html: async (urlInfo) => {
|
|
129
137
|
let importmapFound = false;
|
|
130
|
-
const importmapLoaded = startLoadingImportmap(urlInfo);
|
|
131
138
|
|
|
139
|
+
let htmlAst;
|
|
132
140
|
try {
|
|
133
|
-
|
|
141
|
+
htmlAst = parseHtml({
|
|
134
142
|
html: urlInfo.content,
|
|
135
143
|
url: urlInfo.url,
|
|
136
144
|
});
|
|
145
|
+
} catch (e) {
|
|
146
|
+
if (e.code === "PARSE_ERROR") {
|
|
147
|
+
const line = e.line;
|
|
148
|
+
const column = e.column;
|
|
149
|
+
const htmlErrorContentFrame = generateContentFrame({
|
|
150
|
+
content: urlInfo.content,
|
|
151
|
+
line,
|
|
152
|
+
column,
|
|
153
|
+
});
|
|
154
|
+
console.error(`Error while handling ${urlInfo.context.request ? urlInfo.context.request.url : urlInfo.url}:
|
|
155
|
+
${e.reasonCode}
|
|
156
|
+
${urlInfo.url}:${line}:${column}
|
|
157
|
+
${htmlErrorContentFrame}`);
|
|
158
|
+
const html = generateHtmlForSyntaxError(e, {
|
|
159
|
+
htmlUrl: urlInfo.url,
|
|
160
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
161
|
+
htmlErrorContentFrame,
|
|
162
|
+
});
|
|
163
|
+
htmlAst = parseHtml({
|
|
164
|
+
html,
|
|
165
|
+
url: htmlSyntaxErrorFileUrl,
|
|
166
|
+
});
|
|
167
|
+
} else {
|
|
168
|
+
throw e;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const importmapLoaded = startLoadingImportmap(urlInfo);
|
|
137
173
|
|
|
174
|
+
try {
|
|
138
175
|
const mutations = [];
|
|
139
176
|
const actions = [];
|
|
140
177
|
const finalizeCallbacks = [];
|
|
@@ -313,7 +350,7 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
313
350
|
});
|
|
314
351
|
};
|
|
315
352
|
|
|
316
|
-
|
|
353
|
+
visitNonIgnoredHtmlNode(htmlAst, {
|
|
317
354
|
link: (linkNode) => {
|
|
318
355
|
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
319
356
|
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
@@ -569,6 +606,61 @@ export const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
569
606
|
};
|
|
570
607
|
};
|
|
571
608
|
|
|
609
|
+
const visitNonIgnoredHtmlNode = (htmlAst, visitors) => {
|
|
610
|
+
const visitorsInstrumented = {};
|
|
611
|
+
for (const key of Object.keys(visitors)) {
|
|
612
|
+
visitorsInstrumented[key] = (node) => {
|
|
613
|
+
const jsenvIgnoreAttribute = getHtmlNodeAttribute(node, "jsenv-ignore");
|
|
614
|
+
if (jsenvIgnoreAttribute !== undefined) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
visitors[key](node);
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
visitHtmlNodes(htmlAst, visitorsInstrumented);
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
const generateHtmlForSyntaxError = (
|
|
624
|
+
htmlSyntaxError,
|
|
625
|
+
{ htmlUrl, rootDirectoryUrl, htmlErrorContentFrame },
|
|
626
|
+
) => {
|
|
627
|
+
const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
|
|
628
|
+
const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
|
|
629
|
+
const { line, column } = htmlSyntaxError;
|
|
630
|
+
const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
|
|
631
|
+
const replacers = {
|
|
632
|
+
fileRelativeUrl: htmlRelativeUrl,
|
|
633
|
+
reasonCode: htmlSyntaxError.reasonCode,
|
|
634
|
+
errorLinkHref: `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
|
|
635
|
+
urlWithLineAndColumn,
|
|
636
|
+
)}')`,
|
|
637
|
+
errorLinkText: `${htmlRelativeUrl}:${line}:${column}`,
|
|
638
|
+
syntaxError: escapeHtml(htmlErrorContentFrame),
|
|
639
|
+
};
|
|
640
|
+
const html = replacePlaceholders(htmlForSyntaxError, replacers);
|
|
641
|
+
return html;
|
|
642
|
+
};
|
|
643
|
+
const escapeHtml = (string) => {
|
|
644
|
+
return string
|
|
645
|
+
.replace(/&/g, "&")
|
|
646
|
+
.replace(/</g, "<")
|
|
647
|
+
.replace(/>/g, ">")
|
|
648
|
+
.replace(/"/g, """)
|
|
649
|
+
.replace(/'/g, "'");
|
|
650
|
+
};
|
|
651
|
+
const replacePlaceholders = (html, replacers) => {
|
|
652
|
+
return html.replace(/\${([\w]+)}/g, (match, name) => {
|
|
653
|
+
const replacer = replacers[name];
|
|
654
|
+
if (replacer === undefined) {
|
|
655
|
+
return match;
|
|
656
|
+
}
|
|
657
|
+
if (typeof replacer === "function") {
|
|
658
|
+
return replacer();
|
|
659
|
+
}
|
|
660
|
+
return replacer;
|
|
661
|
+
});
|
|
662
|
+
};
|
|
663
|
+
|
|
572
664
|
const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
|
|
573
665
|
const integrityCompatibleTagNames = ["script", "link", "img", "source"];
|
|
574
666
|
const readFetchMetas = (node) => {
|
|
@@ -62,7 +62,7 @@ export const jsenvPluginRibbon = ({
|
|
|
62
62
|
createHtmlNode({
|
|
63
63
|
tagName: "script",
|
|
64
64
|
type: "module",
|
|
65
|
-
textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}"
|
|
65
|
+
textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}";
|
|
66
66
|
|
|
67
67
|
injectRibbon(${paramsJson});`,
|
|
68
68
|
}),
|