@jsenv/core 38.4.16 → 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 +708 -406
- package/package.json +6 -7
- package/src/dev/start_dev_server.js +9 -1
- package/src/kitchen/errors.js +8 -5
- package/src/kitchen/url_graph/references.js +7 -6
- 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 +480 -369
- package/src/plugins/ribbon/jsenv_plugin_ribbon.js +1 -1
package/dist/jsenv_core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdir, chmod, stat, lstat, promises, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, watch, readdirSync, statSync, createReadStream, readFile, existsSync, readFileSync, realpathSync } from "node:fs";
|
|
1
|
+
import { readdir, chmod, stat, lstat, promises, writeFileSync as writeFileSync$1, mkdirSync, unlink, openSync, closeSync, rmdir, watch, readdirSync, statSync, createReadStream, lstatSync, readFile, existsSync, readFileSync, realpathSync } from "node:fs";
|
|
2
2
|
import process$1 from "node:process";
|
|
3
3
|
import os, { networkInterfaces } from "node:os";
|
|
4
4
|
import tty from "node:tty";
|
|
@@ -13,7 +13,7 @@ import http from "node:http";
|
|
|
13
13
|
import { Readable, Stream, Writable } from "node:stream";
|
|
14
14
|
import { Http2ServerResponse } from "node:http2";
|
|
15
15
|
import { lookup } from "node:dns";
|
|
16
|
-
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, parseJsUrls, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition,
|
|
16
|
+
import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, parseJsUrls, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getHtmlNodeAttributePosition, parseSrcSet, getUrlForContentInsideHtml, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls, getUrlForContentInsideJs, analyzeLinkNode, findHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
|
|
17
17
|
import { sourcemapConverter, createMagicSource, composeTwoSourcemaps, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import { systemJsClientFileUrlDefault, convertJsModuleToJsClassic } from "@jsenv/js-module-fallback";
|
|
@@ -142,6 +142,19 @@ const applyMatching = (pattern, string) => {
|
|
|
142
142
|
consumeRemainingString();
|
|
143
143
|
return true;
|
|
144
144
|
}
|
|
145
|
+
if (remainingPattern.slice(0, 4) === "/**/") {
|
|
146
|
+
consumePattern(3); // consumes "/**/"
|
|
147
|
+
const skipResult = skipUntilMatch({
|
|
148
|
+
pattern: remainingPattern,
|
|
149
|
+
string: remainingString,
|
|
150
|
+
canSkipSlash: true,
|
|
151
|
+
});
|
|
152
|
+
groups.push(...skipResult.groups);
|
|
153
|
+
consumePattern(skipResult.patternIndex);
|
|
154
|
+
consumeRemainingString();
|
|
155
|
+
restoreIndexes = false;
|
|
156
|
+
return skipResult.matched;
|
|
157
|
+
}
|
|
145
158
|
// pattern leading **
|
|
146
159
|
if (remainingPattern.slice(0, 2) === "**") {
|
|
147
160
|
consumePattern(2); // consumes "**"
|
|
@@ -3159,6 +3172,14 @@ const readStat = (
|
|
|
3159
3172
|
});
|
|
3160
3173
|
};
|
|
3161
3174
|
|
|
3175
|
+
/*
|
|
3176
|
+
* - stats object documentation on Node.js
|
|
3177
|
+
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
3178
|
+
*/
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
process.platform === "win32";
|
|
3182
|
+
|
|
3162
3183
|
const statsToType = (stats) => {
|
|
3163
3184
|
if (stats.isFile()) return "file";
|
|
3164
3185
|
if (stats.isDirectory()) return "directory";
|
|
@@ -3471,14 +3492,6 @@ const removeDirectoryNaive = (
|
|
|
3471
3492
|
});
|
|
3472
3493
|
};
|
|
3473
3494
|
|
|
3474
|
-
process.platform === "win32";
|
|
3475
|
-
|
|
3476
|
-
/*
|
|
3477
|
-
* - stats object documentation on Node.js
|
|
3478
|
-
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
3479
|
-
*/
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
3495
|
process.platform === "win32";
|
|
3483
3496
|
|
|
3484
3497
|
process.platform === "win32";
|
|
@@ -7381,10 +7394,14 @@ const serveDirectory = (
|
|
|
7381
7394
|
<h1>Content of directory ${url}</h1>
|
|
7382
7395
|
<ul>
|
|
7383
7396
|
${directoryContentArray.map((filename) => {
|
|
7384
|
-
const
|
|
7385
|
-
const
|
|
7397
|
+
const fileUrlObject = new URL(filename, url);
|
|
7398
|
+
const fileUrl = String(fileUrlObject);
|
|
7399
|
+
let fileUrlRelativeToServer = fileUrl.slice(
|
|
7386
7400
|
String(rootDirectoryUrl).length,
|
|
7387
7401
|
);
|
|
7402
|
+
if (lstatSync(fileUrlObject).isDirectory()) {
|
|
7403
|
+
fileUrlRelativeToServer += "/";
|
|
7404
|
+
}
|
|
7388
7405
|
return `<li>
|
|
7389
7406
|
<a href="/${fileUrlRelativeToServer}">${fileUrlRelativeToServer}</a>
|
|
7390
7407
|
</li>`;
|
|
@@ -11528,13 +11545,14 @@ const createDependencies = (ownerUrlInfo) => {
|
|
|
11528
11545
|
const parentContent = isOriginalPosition
|
|
11529
11546
|
? ownerUrlInfo.originalContent
|
|
11530
11547
|
: ownerUrlInfo.content;
|
|
11548
|
+
const trace = traceFromUrlSite({
|
|
11549
|
+
url: parentUrl,
|
|
11550
|
+
content: parentContent,
|
|
11551
|
+
line: specifierLine,
|
|
11552
|
+
column: specifierColumn,
|
|
11553
|
+
});
|
|
11531
11554
|
const reference = createResolveAndFinalize({
|
|
11532
|
-
trace
|
|
11533
|
-
url: parentUrl,
|
|
11534
|
-
content: parentContent,
|
|
11535
|
-
line: specifierLine,
|
|
11536
|
-
column: specifierColumn,
|
|
11537
|
-
}),
|
|
11555
|
+
trace,
|
|
11538
11556
|
isOriginalPosition,
|
|
11539
11557
|
specifierLine,
|
|
11540
11558
|
specifierColumn,
|
|
@@ -13747,9 +13765,12 @@ const createTransformUrlContentError = ({
|
|
|
13747
13765
|
if (code === "PARSE_ERROR") {
|
|
13748
13766
|
transformError.reason = `parse error on ${urlInfo.type}`;
|
|
13749
13767
|
transformError.cause = error;
|
|
13768
|
+
let line = error.line;
|
|
13769
|
+
if (urlInfo.type === "js_module") {
|
|
13770
|
+
line = line - 1;
|
|
13771
|
+
}
|
|
13750
13772
|
if (urlInfo.isInline) {
|
|
13751
|
-
transformError.trace.line =
|
|
13752
|
-
urlInfo.firstReference.trace.line + error.line - 1;
|
|
13773
|
+
transformError.trace.line = urlInfo.firstReference.trace.line + line;
|
|
13753
13774
|
transformError.trace.column =
|
|
13754
13775
|
urlInfo.firstReference.trace.column + error.column;
|
|
13755
13776
|
transformError.trace.codeFrame = generateContentFrame({
|
|
@@ -13766,16 +13787,16 @@ const createTransformUrlContentError = ({
|
|
|
13766
13787
|
} else {
|
|
13767
13788
|
transformError.trace = {
|
|
13768
13789
|
url: urlInfo.url,
|
|
13769
|
-
line
|
|
13790
|
+
line,
|
|
13770
13791
|
column: error.column,
|
|
13771
13792
|
codeFrame: generateContentFrame({
|
|
13772
|
-
line
|
|
13793
|
+
line,
|
|
13773
13794
|
column: error.column,
|
|
13774
13795
|
content: urlInfo.content,
|
|
13775
13796
|
}),
|
|
13776
13797
|
message: stringifyUrlSite({
|
|
13777
13798
|
url: urlInfo.url,
|
|
13778
|
-
line
|
|
13799
|
+
line,
|
|
13779
13800
|
column: error.column,
|
|
13780
13801
|
content: urlInfo.content,
|
|
13781
13802
|
}),
|
|
@@ -15779,6 +15800,11 @@ const applyDefaultExtension = ({ url, importer, defaultExtension }) => {
|
|
|
15779
15800
|
return url
|
|
15780
15801
|
};
|
|
15781
15802
|
|
|
15803
|
+
const htmlSyntaxErrorFileUrl = new URL(
|
|
15804
|
+
"./html/html_syntax_error.html",
|
|
15805
|
+
import.meta.url,
|
|
15806
|
+
);
|
|
15807
|
+
|
|
15782
15808
|
const jsenvPluginHtmlReferenceAnalysis = ({
|
|
15783
15809
|
inlineContent,
|
|
15784
15810
|
inlineConvertedScript,
|
|
@@ -15886,427 +15912,532 @@ const jsenvPluginHtmlReferenceAnalysis = ({
|
|
|
15886
15912
|
},
|
|
15887
15913
|
html: async (urlInfo) => {
|
|
15888
15914
|
let importmapFound = false;
|
|
15889
|
-
const importmapLoaded = startLoadingImportmap(urlInfo);
|
|
15890
|
-
|
|
15891
|
-
const htmlAst = parseHtml({
|
|
15892
|
-
html: urlInfo.content,
|
|
15893
|
-
url: urlInfo.url,
|
|
15894
|
-
});
|
|
15895
15915
|
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15916
|
+
let htmlAst;
|
|
15917
|
+
try {
|
|
15918
|
+
htmlAst = parseHtml({
|
|
15919
|
+
html: urlInfo.content,
|
|
15920
|
+
url: urlInfo.url,
|
|
15921
|
+
});
|
|
15922
|
+
} catch (e) {
|
|
15923
|
+
if (e.code === "PARSE_ERROR") {
|
|
15924
|
+
const line = e.line;
|
|
15925
|
+
const column = e.column;
|
|
15926
|
+
const htmlErrorContentFrame = generateContentFrame({
|
|
15927
|
+
content: urlInfo.content,
|
|
15928
|
+
line,
|
|
15929
|
+
column,
|
|
15930
|
+
});
|
|
15931
|
+
console.error(`Error while handling ${urlInfo.context.request ? urlInfo.context.request.url : urlInfo.url}:
|
|
15932
|
+
${e.reasonCode}
|
|
15933
|
+
${urlInfo.url}:${line}:${column}
|
|
15934
|
+
${htmlErrorContentFrame}`);
|
|
15935
|
+
const html = generateHtmlForSyntaxError(e, {
|
|
15936
|
+
htmlUrl: urlInfo.url,
|
|
15937
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
15938
|
+
htmlErrorContentFrame,
|
|
15939
|
+
});
|
|
15940
|
+
htmlAst = parseHtml({
|
|
15941
|
+
html,
|
|
15942
|
+
url: htmlSyntaxErrorFileUrl,
|
|
15943
|
+
});
|
|
15911
15944
|
} else {
|
|
15912
|
-
|
|
15913
|
-
}
|
|
15914
|
-
const {
|
|
15915
|
-
line,
|
|
15916
|
-
column,
|
|
15917
|
-
// originalLine, originalColumn
|
|
15918
|
-
} = position;
|
|
15919
|
-
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15920
|
-
|
|
15921
|
-
const { crossorigin, integrity } = readFetchMetas(node);
|
|
15922
|
-
const isResourceHint = [
|
|
15923
|
-
"preconnect",
|
|
15924
|
-
"dns-prefetch",
|
|
15925
|
-
"prefetch",
|
|
15926
|
-
"preload",
|
|
15927
|
-
"modulepreload",
|
|
15928
|
-
].includes(subtype);
|
|
15929
|
-
let attributeLocation = node.sourceCodeLocation.attrs[attributeName];
|
|
15930
|
-
if (
|
|
15931
|
-
!attributeLocation &&
|
|
15932
|
-
attributeName === "href" &&
|
|
15933
|
-
(node.tagName === "use" || node.tagName === "image")
|
|
15934
|
-
) {
|
|
15935
|
-
attributeLocation = node.sourceCodeLocation.attrs["xlink:href"];
|
|
15945
|
+
throw e;
|
|
15936
15946
|
}
|
|
15937
|
-
|
|
15938
|
-
|
|
15947
|
+
}
|
|
15948
|
+
|
|
15949
|
+
const importmapLoaded = startLoadingImportmap(urlInfo);
|
|
15950
|
+
|
|
15951
|
+
try {
|
|
15952
|
+
const mutations = [];
|
|
15953
|
+
const actions = [];
|
|
15954
|
+
const finalizeCallbacks = [];
|
|
15955
|
+
|
|
15956
|
+
const createExternalReference = (
|
|
15957
|
+
node,
|
|
15958
|
+
attributeName,
|
|
15939
15959
|
attributeValue,
|
|
15940
|
-
|
|
15941
|
-
)
|
|
15942
|
-
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
15946
|
-
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
|
|
15955
|
-
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15960
|
+
{ type, subtype, expectedType, ...rest },
|
|
15961
|
+
) => {
|
|
15962
|
+
let position;
|
|
15963
|
+
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
15964
|
+
// when generated from inline content,
|
|
15965
|
+
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
15966
|
+
position = getHtmlNodePosition(node);
|
|
15967
|
+
} else {
|
|
15968
|
+
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
15969
|
+
}
|
|
15970
|
+
const {
|
|
15971
|
+
line,
|
|
15972
|
+
column,
|
|
15973
|
+
// originalLine, originalColumn
|
|
15974
|
+
} = position;
|
|
15975
|
+
const debug =
|
|
15976
|
+
getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
15977
|
+
|
|
15978
|
+
const { crossorigin, integrity } = readFetchMetas(node);
|
|
15979
|
+
const isResourceHint = [
|
|
15980
|
+
"preconnect",
|
|
15981
|
+
"dns-prefetch",
|
|
15982
|
+
"prefetch",
|
|
15983
|
+
"preload",
|
|
15984
|
+
"modulepreload",
|
|
15985
|
+
].includes(subtype);
|
|
15986
|
+
let attributeLocation =
|
|
15987
|
+
node.sourceCodeLocation.attrs[attributeName];
|
|
15988
|
+
if (
|
|
15989
|
+
!attributeLocation &&
|
|
15990
|
+
attributeName === "href" &&
|
|
15991
|
+
(node.tagName === "use" || node.tagName === "image")
|
|
15992
|
+
) {
|
|
15993
|
+
attributeLocation = node.sourceCodeLocation.attrs["xlink:href"];
|
|
15994
|
+
}
|
|
15995
|
+
const attributeStart = attributeLocation.startOffset;
|
|
15996
|
+
const attributeValueStart = urlInfo.content.indexOf(
|
|
15997
|
+
attributeValue,
|
|
15998
|
+
attributeStart + `${attributeName}=`.length,
|
|
15999
|
+
);
|
|
16000
|
+
const attributeValueEnd =
|
|
16001
|
+
attributeValueStart + attributeValue.length;
|
|
16002
|
+
const reference = urlInfo.dependencies.found({
|
|
16003
|
+
type,
|
|
16004
|
+
subtype,
|
|
16005
|
+
expectedType,
|
|
16006
|
+
specifier: attributeValue,
|
|
16007
|
+
specifierLine: line,
|
|
16008
|
+
specifierColumn: column,
|
|
16009
|
+
specifierStart: attributeValueStart,
|
|
16010
|
+
specifierEnd: attributeValueEnd,
|
|
16011
|
+
isResourceHint,
|
|
16012
|
+
isWeak: isResourceHint,
|
|
16013
|
+
crossorigin,
|
|
16014
|
+
integrity,
|
|
16015
|
+
debug,
|
|
16016
|
+
astInfo: { node, attributeName },
|
|
16017
|
+
...rest,
|
|
16018
|
+
});
|
|
16019
|
+
actions.push(async () => {
|
|
16020
|
+
await reference.readGeneratedSpecifier();
|
|
16021
|
+
mutations.push(() => {
|
|
16022
|
+
setHtmlNodeAttributes(node, {
|
|
16023
|
+
[attributeName]: reference.generatedSpecifier,
|
|
16024
|
+
});
|
|
15965
16025
|
});
|
|
15966
16026
|
});
|
|
15967
|
-
|
|
15968
|
-
|
|
15969
|
-
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
if (href) {
|
|
15973
|
-
return createExternalReference(node, "href", href, referenceProps);
|
|
15974
|
-
}
|
|
15975
|
-
return null;
|
|
15976
|
-
};
|
|
15977
|
-
const visitSrc = (node, referenceProps) => {
|
|
15978
|
-
const src = getHtmlNodeAttribute(node, "src");
|
|
15979
|
-
if (src) {
|
|
15980
|
-
return createExternalReference(node, "src", src, referenceProps);
|
|
15981
|
-
}
|
|
15982
|
-
return null;
|
|
15983
|
-
};
|
|
15984
|
-
const visitSrcset = (node, referenceProps) => {
|
|
15985
|
-
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
15986
|
-
if (srcset) {
|
|
15987
|
-
const srcCandidates = parseSrcSet(srcset);
|
|
15988
|
-
return srcCandidates.map((srcCandidate) => {
|
|
16027
|
+
return reference;
|
|
16028
|
+
};
|
|
16029
|
+
const visitHref = (node, referenceProps) => {
|
|
16030
|
+
const href = getHtmlNodeAttribute(node, "href");
|
|
16031
|
+
if (href) {
|
|
15989
16032
|
return createExternalReference(
|
|
15990
16033
|
node,
|
|
15991
|
-
"
|
|
15992
|
-
|
|
16034
|
+
"href",
|
|
16035
|
+
href,
|
|
15993
16036
|
referenceProps,
|
|
15994
16037
|
);
|
|
16038
|
+
}
|
|
16039
|
+
return null;
|
|
16040
|
+
};
|
|
16041
|
+
const visitSrc = (node, referenceProps) => {
|
|
16042
|
+
const src = getHtmlNodeAttribute(node, "src");
|
|
16043
|
+
if (src) {
|
|
16044
|
+
return createExternalReference(node, "src", src, referenceProps);
|
|
16045
|
+
}
|
|
16046
|
+
return null;
|
|
16047
|
+
};
|
|
16048
|
+
const visitSrcset = (node, referenceProps) => {
|
|
16049
|
+
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
16050
|
+
if (srcset) {
|
|
16051
|
+
const srcCandidates = parseSrcSet(srcset);
|
|
16052
|
+
return srcCandidates.map((srcCandidate) => {
|
|
16053
|
+
return createExternalReference(
|
|
16054
|
+
node,
|
|
16055
|
+
"srcset",
|
|
16056
|
+
srcCandidate.specifier,
|
|
16057
|
+
referenceProps,
|
|
16058
|
+
);
|
|
16059
|
+
});
|
|
16060
|
+
}
|
|
16061
|
+
return null;
|
|
16062
|
+
};
|
|
16063
|
+
const createInlineReference = (
|
|
16064
|
+
node,
|
|
16065
|
+
inlineContent,
|
|
16066
|
+
{ type, expectedType, contentType },
|
|
16067
|
+
) => {
|
|
16068
|
+
const hotAccept =
|
|
16069
|
+
getHtmlNodeAttribute(node, "hot-accept") !== undefined;
|
|
16070
|
+
const { line, column, isOriginal } = getHtmlNodePosition(node, {
|
|
16071
|
+
preferOriginal: true,
|
|
15995
16072
|
});
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
};
|
|
15999
|
-
|
|
16000
|
-
const createInlineReference = (
|
|
16001
|
-
node,
|
|
16002
|
-
inlineContent,
|
|
16003
|
-
{ type, expectedType, contentType },
|
|
16004
|
-
) => {
|
|
16005
|
-
const hotAccept =
|
|
16006
|
-
getHtmlNodeAttribute(node, "hot-accept") !== undefined;
|
|
16007
|
-
const { line, column, isOriginal } = getHtmlNodePosition(node, {
|
|
16008
|
-
preferOriginal: true,
|
|
16009
|
-
});
|
|
16010
|
-
const inlineContentUrl = getUrlForContentInsideHtml(node, {
|
|
16011
|
-
htmlUrl: urlInfo.url,
|
|
16012
|
-
});
|
|
16013
|
-
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
16014
|
-
const inlineReference = urlInfo.dependencies.foundInline({
|
|
16015
|
-
type,
|
|
16016
|
-
expectedType,
|
|
16017
|
-
isOriginalPosition: isOriginal,
|
|
16018
|
-
// we remove 1 to the line because imagine the following html:
|
|
16019
|
-
// <style>body { color: red; }</style>
|
|
16020
|
-
// -> content starts same line as <style> (same for <script>)
|
|
16021
|
-
specifierLine: line - 1,
|
|
16022
|
-
specifierColumn: column,
|
|
16023
|
-
specifier: inlineContentUrl,
|
|
16024
|
-
contentType,
|
|
16025
|
-
content: inlineContent,
|
|
16026
|
-
debug,
|
|
16027
|
-
astInfo: { node },
|
|
16028
|
-
});
|
|
16029
|
-
|
|
16030
|
-
actions.push(async () => {
|
|
16031
|
-
await inlineReference.urlInfo.cook();
|
|
16032
|
-
mutations.push(() => {
|
|
16033
|
-
if (hotAccept) {
|
|
16034
|
-
removeHtmlNodeText(node);
|
|
16035
|
-
setHtmlNodeAttributes(node, {
|
|
16036
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
16037
|
-
});
|
|
16038
|
-
} else {
|
|
16039
|
-
setHtmlNodeText(node, inlineReference.urlInfo.content, {
|
|
16040
|
-
indentation: false, // indentation would decrease stack trace precision
|
|
16041
|
-
});
|
|
16042
|
-
setHtmlNodeAttributes(node, {
|
|
16043
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
16044
|
-
});
|
|
16045
|
-
}
|
|
16073
|
+
const inlineContentUrl = getUrlForContentInsideHtml(node, {
|
|
16074
|
+
htmlUrl: urlInfo.url,
|
|
16046
16075
|
});
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
|
|
16050
|
-
|
|
16051
|
-
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
});
|
|
16064
|
-
};
|
|
16065
|
-
|
|
16066
|
-
visitHtmlNodes(htmlAst, {
|
|
16067
|
-
link: (linkNode) => {
|
|
16068
|
-
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
16069
|
-
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
16070
|
-
const ref = visitHref(linkNode, {
|
|
16071
|
-
type: "link_href",
|
|
16072
|
-
subtype: rel,
|
|
16073
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
16074
|
-
expectedContentType: type,
|
|
16076
|
+
const debug =
|
|
16077
|
+
getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
16078
|
+
const inlineReference = urlInfo.dependencies.foundInline({
|
|
16079
|
+
type,
|
|
16080
|
+
expectedType,
|
|
16081
|
+
isOriginalPosition: isOriginal,
|
|
16082
|
+
// we remove 1 to the line because imagine the following html:
|
|
16083
|
+
// <style>body { color: red; }</style>
|
|
16084
|
+
// -> content starts same line as <style> (same for <script>)
|
|
16085
|
+
specifierLine: line - 1,
|
|
16086
|
+
specifierColumn: column,
|
|
16087
|
+
specifier: inlineContentUrl,
|
|
16088
|
+
contentType,
|
|
16089
|
+
content: inlineContent,
|
|
16090
|
+
debug,
|
|
16091
|
+
astInfo: { node },
|
|
16075
16092
|
});
|
|
16076
|
-
|
|
16077
|
-
|
|
16078
|
-
|
|
16079
|
-
|
|
16093
|
+
|
|
16094
|
+
actions.push(async () => {
|
|
16095
|
+
await inlineReference.urlInfo.cook();
|
|
16096
|
+
mutations.push(() => {
|
|
16097
|
+
if (hotAccept) {
|
|
16098
|
+
removeHtmlNodeText(node);
|
|
16099
|
+
setHtmlNodeAttributes(node, {
|
|
16100
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
16101
|
+
});
|
|
16102
|
+
} else {
|
|
16103
|
+
setHtmlNodeText(node, inlineReference.urlInfo.content, {
|
|
16104
|
+
indentation: false, // indentation would decrease stack trace precision
|
|
16105
|
+
});
|
|
16106
|
+
setHtmlNodeAttributes(node, {
|
|
16107
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
16108
|
+
});
|
|
16080
16109
|
}
|
|
16081
16110
|
});
|
|
16111
|
+
});
|
|
16112
|
+
return inlineReference;
|
|
16113
|
+
};
|
|
16114
|
+
const visitTextContent = (
|
|
16115
|
+
node,
|
|
16116
|
+
{ type, subtype, expectedType, contentType },
|
|
16117
|
+
) => {
|
|
16118
|
+
const inlineContent = getHtmlNodeText(node);
|
|
16119
|
+
if (!inlineContent) {
|
|
16120
|
+
return null;
|
|
16082
16121
|
}
|
|
16083
|
-
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16122
|
+
return createInlineReference(node, inlineContent, {
|
|
16123
|
+
type,
|
|
16124
|
+
subtype,
|
|
16125
|
+
expectedType,
|
|
16126
|
+
contentType,
|
|
16127
|
+
});
|
|
16128
|
+
};
|
|
16129
|
+
|
|
16130
|
+
visitNonIgnoredHtmlNode(htmlAst, {
|
|
16131
|
+
link: (linkNode) => {
|
|
16132
|
+
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
16133
|
+
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
16134
|
+
const ref = visitHref(linkNode, {
|
|
16135
|
+
type: "link_href",
|
|
16136
|
+
subtype: rel,
|
|
16137
|
+
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
16138
|
+
expectedContentType: type,
|
|
16139
|
+
});
|
|
16140
|
+
if (ref) {
|
|
16141
|
+
finalizeCallbacks.push(() => {
|
|
16142
|
+
if (ref.expectedType) {
|
|
16143
|
+
// might be set by other plugins, in that case respect it
|
|
16144
|
+
} else {
|
|
16145
|
+
ref.expectedType = decideLinkExpectedType(ref, urlInfo);
|
|
16146
|
+
}
|
|
16090
16147
|
});
|
|
16091
16148
|
}
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
return;
|
|
16100
|
-
}
|
|
16101
|
-
if (type === "importmap") {
|
|
16102
|
-
importmapFound = true;
|
|
16103
|
-
|
|
16104
|
-
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
16105
|
-
if (src) {
|
|
16106
|
-
// Browser would throw on remote importmap
|
|
16107
|
-
// and won't sent a request to the server for it
|
|
16108
|
-
// We must precook the importmap to know its content and inline it into the HTML
|
|
16109
|
-
const importmapReference = createExternalReference(
|
|
16110
|
-
scriptNode,
|
|
16111
|
-
"src",
|
|
16112
|
-
src,
|
|
16113
|
-
{
|
|
16114
|
-
type: "script",
|
|
16115
|
-
subtype: "importmap",
|
|
16116
|
-
expectedType: "importmap",
|
|
16117
|
-
},
|
|
16118
|
-
);
|
|
16119
|
-
const { line, column, isOriginal } = getHtmlNodePosition(
|
|
16120
|
-
scriptNode,
|
|
16121
|
-
{
|
|
16122
|
-
preferOriginal: true,
|
|
16123
|
-
},
|
|
16124
|
-
);
|
|
16125
|
-
const importmapInlineUrl = getUrlForContentInsideHtml(
|
|
16126
|
-
scriptNode,
|
|
16127
|
-
{
|
|
16128
|
-
htmlUrl: urlInfo.url,
|
|
16129
|
-
},
|
|
16130
|
-
);
|
|
16131
|
-
const importmapReferenceInlined = importmapReference.inline({
|
|
16132
|
-
line: line - 1,
|
|
16133
|
-
column,
|
|
16134
|
-
isOriginal,
|
|
16135
|
-
specifier: importmapInlineUrl,
|
|
16136
|
-
contentType: "application/importmap+json",
|
|
16137
|
-
});
|
|
16138
|
-
const importmapInlineUrlInfo =
|
|
16139
|
-
importmapReferenceInlined.urlInfo;
|
|
16140
|
-
actions.push(async () => {
|
|
16141
|
-
await importmapInlineUrlInfo.cook();
|
|
16142
|
-
importmapLoaded(importmapInlineUrlInfo);
|
|
16143
|
-
mutations.push(() => {
|
|
16144
|
-
setHtmlNodeText(
|
|
16145
|
-
scriptNode,
|
|
16146
|
-
importmapInlineUrlInfo.content,
|
|
16147
|
-
{
|
|
16148
|
-
indentation: "auto",
|
|
16149
|
-
},
|
|
16150
|
-
);
|
|
16151
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
16152
|
-
"src": undefined,
|
|
16153
|
-
"jsenv-inlined-by": "jsenv:html_reference_analysis",
|
|
16154
|
-
"inlined-from-src": src,
|
|
16155
|
-
});
|
|
16149
|
+
},
|
|
16150
|
+
style: inlineContent
|
|
16151
|
+
? (styleNode) => {
|
|
16152
|
+
visitTextContent(styleNode, {
|
|
16153
|
+
type: "style",
|
|
16154
|
+
expectedType: "css",
|
|
16155
|
+
contentType: "text/css",
|
|
16156
16156
|
});
|
|
16157
|
-
}
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16157
|
+
}
|
|
16158
|
+
: null,
|
|
16159
|
+
script: (scriptNode) => {
|
|
16160
|
+
const { type, subtype, contentType, extension } =
|
|
16161
|
+
analyzeScriptNode(scriptNode);
|
|
16162
|
+
if (type === "text") {
|
|
16163
|
+
// ignore <script type="whatever">foobar</script>
|
|
16164
|
+
// per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
|
|
16165
|
+
return;
|
|
16166
|
+
}
|
|
16167
|
+
if (type === "importmap") {
|
|
16168
|
+
importmapFound = true;
|
|
16169
|
+
|
|
16170
|
+
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
16171
|
+
if (src) {
|
|
16172
|
+
// Browser would throw on remote importmap
|
|
16173
|
+
// and won't sent a request to the server for it
|
|
16174
|
+
// We must precook the importmap to know its content and inline it into the HTML
|
|
16175
|
+
const importmapReference = createExternalReference(
|
|
16162
16176
|
scriptNode,
|
|
16163
|
-
|
|
16177
|
+
"src",
|
|
16178
|
+
src,
|
|
16164
16179
|
{
|
|
16165
16180
|
type: "script",
|
|
16181
|
+
subtype: "importmap",
|
|
16166
16182
|
expectedType: "importmap",
|
|
16167
|
-
contentType: "application/importmap+json",
|
|
16168
16183
|
},
|
|
16169
16184
|
);
|
|
16170
|
-
const
|
|
16185
|
+
const { line, column, isOriginal } = getHtmlNodePosition(
|
|
16186
|
+
scriptNode,
|
|
16187
|
+
{
|
|
16188
|
+
preferOriginal: true,
|
|
16189
|
+
},
|
|
16190
|
+
);
|
|
16191
|
+
const importmapInlineUrl = getUrlForContentInsideHtml(
|
|
16192
|
+
scriptNode,
|
|
16193
|
+
{
|
|
16194
|
+
htmlUrl: urlInfo.url,
|
|
16195
|
+
},
|
|
16196
|
+
);
|
|
16197
|
+
const importmapReferenceInlined = importmapReference.inline({
|
|
16198
|
+
line: line - 1,
|
|
16199
|
+
column,
|
|
16200
|
+
isOriginal,
|
|
16201
|
+
specifier: importmapInlineUrl,
|
|
16202
|
+
contentType: "application/importmap+json",
|
|
16203
|
+
});
|
|
16204
|
+
const importmapInlineUrlInfo =
|
|
16205
|
+
importmapReferenceInlined.urlInfo;
|
|
16171
16206
|
actions.push(async () => {
|
|
16172
|
-
|
|
16173
|
-
|
|
16207
|
+
try {
|
|
16208
|
+
await importmapInlineUrlInfo.cook();
|
|
16209
|
+
} finally {
|
|
16210
|
+
importmapLoaded(importmapInlineUrlInfo);
|
|
16211
|
+
}
|
|
16174
16212
|
mutations.push(() => {
|
|
16175
16213
|
setHtmlNodeText(
|
|
16176
16214
|
scriptNode,
|
|
16177
|
-
|
|
16215
|
+
importmapInlineUrlInfo.content,
|
|
16178
16216
|
{
|
|
16179
16217
|
indentation: "auto",
|
|
16180
16218
|
},
|
|
16181
16219
|
);
|
|
16182
16220
|
setHtmlNodeAttributes(scriptNode, {
|
|
16183
|
-
"
|
|
16221
|
+
"src": undefined,
|
|
16222
|
+
"jsenv-inlined-by": "jsenv:html_reference_analysis",
|
|
16223
|
+
"inlined-from-src": src,
|
|
16224
|
+
});
|
|
16225
|
+
});
|
|
16226
|
+
});
|
|
16227
|
+
} else {
|
|
16228
|
+
const htmlNodeText = getHtmlNodeText(scriptNode);
|
|
16229
|
+
if (htmlNodeText) {
|
|
16230
|
+
const importmapReference = createInlineReference(
|
|
16231
|
+
scriptNode,
|
|
16232
|
+
htmlNodeText,
|
|
16233
|
+
{
|
|
16234
|
+
type: "script",
|
|
16235
|
+
expectedType: "importmap",
|
|
16236
|
+
contentType: "application/importmap+json",
|
|
16237
|
+
},
|
|
16238
|
+
);
|
|
16239
|
+
const inlineImportmapUrlInfo = importmapReference.urlInfo;
|
|
16240
|
+
actions.push(async () => {
|
|
16241
|
+
try {
|
|
16242
|
+
await inlineImportmapUrlInfo.cook();
|
|
16243
|
+
} finally {
|
|
16244
|
+
importmapLoaded(inlineImportmapUrlInfo);
|
|
16245
|
+
}
|
|
16246
|
+
mutations.push(() => {
|
|
16247
|
+
setHtmlNodeText(
|
|
16248
|
+
scriptNode,
|
|
16249
|
+
inlineImportmapUrlInfo.content,
|
|
16250
|
+
{
|
|
16251
|
+
indentation: "auto",
|
|
16252
|
+
},
|
|
16253
|
+
);
|
|
16254
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16255
|
+
"jsenv-cooked-by": "jsenv:html_reference_analysis",
|
|
16256
|
+
});
|
|
16184
16257
|
});
|
|
16185
16258
|
});
|
|
16259
|
+
}
|
|
16260
|
+
}
|
|
16261
|
+
// once this plugin knows the importmap, it will use it
|
|
16262
|
+
// to map imports. These import specifiers will be normalized
|
|
16263
|
+
// by "formatReference" making the importmap presence useless.
|
|
16264
|
+
// In dev/test we keep importmap into the HTML to see it even if useless
|
|
16265
|
+
// Duing build we get rid of it
|
|
16266
|
+
if (urlInfo.context.build) {
|
|
16267
|
+
mutations.push(() => {
|
|
16268
|
+
removeHtmlNode(scriptNode);
|
|
16186
16269
|
});
|
|
16187
16270
|
}
|
|
16271
|
+
return;
|
|
16188
16272
|
}
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
if (
|
|
16195
|
-
|
|
16196
|
-
removeHtmlNode(scriptNode);
|
|
16197
|
-
});
|
|
16273
|
+
const externalRef = visitSrc(scriptNode, {
|
|
16274
|
+
type: "script",
|
|
16275
|
+
subtype: type,
|
|
16276
|
+
expectedType: type,
|
|
16277
|
+
});
|
|
16278
|
+
if (externalRef) {
|
|
16279
|
+
return;
|
|
16198
16280
|
}
|
|
16199
|
-
return;
|
|
16200
|
-
}
|
|
16201
|
-
const externalRef = visitSrc(scriptNode, {
|
|
16202
|
-
type: "script",
|
|
16203
|
-
subtype: type,
|
|
16204
|
-
expectedType: type,
|
|
16205
|
-
});
|
|
16206
|
-
if (externalRef) {
|
|
16207
|
-
return;
|
|
16208
|
-
}
|
|
16209
16281
|
|
|
16210
|
-
|
|
16211
|
-
|
|
16212
|
-
|
|
16213
|
-
|
|
16214
|
-
|
|
16215
|
-
|
|
16216
|
-
|
|
16217
|
-
|
|
16218
|
-
|
|
16219
|
-
|
|
16220
|
-
|
|
16221
|
-
|
|
16222
|
-
|
|
16223
|
-
|
|
16282
|
+
// now visit the content, if any
|
|
16283
|
+
if (!inlineContent) {
|
|
16284
|
+
return;
|
|
16285
|
+
}
|
|
16286
|
+
// If the inline script was already handled by an other plugin, ignore it
|
|
16287
|
+
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
16288
|
+
// - we want to avoid cooking twice a script during build
|
|
16289
|
+
if (
|
|
16290
|
+
!inlineConvertedScript &&
|
|
16291
|
+
getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") ===
|
|
16292
|
+
"jsenv:js_module_fallback"
|
|
16293
|
+
) {
|
|
16294
|
+
return;
|
|
16295
|
+
}
|
|
16224
16296
|
|
|
16225
|
-
|
|
16226
|
-
|
|
16227
|
-
|
|
16228
|
-
|
|
16229
|
-
|
|
16230
|
-
|
|
16231
|
-
|
|
16232
|
-
|
|
16233
|
-
|
|
16234
|
-
|
|
16235
|
-
|
|
16236
|
-
|
|
16297
|
+
const inlineRef = visitTextContent(scriptNode, {
|
|
16298
|
+
type: "script",
|
|
16299
|
+
subtype,
|
|
16300
|
+
expectedType: type,
|
|
16301
|
+
contentType,
|
|
16302
|
+
});
|
|
16303
|
+
if (inlineRef) {
|
|
16304
|
+
// 1. <script type="jsx"> becomes <script>
|
|
16305
|
+
if (type === "js_classic" && extension !== ".js") {
|
|
16306
|
+
mutations.push(() => {
|
|
16307
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16308
|
+
type: undefined,
|
|
16309
|
+
});
|
|
16237
16310
|
});
|
|
16238
|
-
}
|
|
16239
|
-
|
|
16240
|
-
|
|
16241
|
-
|
|
16242
|
-
|
|
16243
|
-
|
|
16244
|
-
|
|
16311
|
+
}
|
|
16312
|
+
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
16313
|
+
if (type === "js_module" && extension !== ".js") {
|
|
16314
|
+
mutations.push(() => {
|
|
16315
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
16316
|
+
type: "module",
|
|
16317
|
+
});
|
|
16245
16318
|
});
|
|
16246
|
-
}
|
|
16319
|
+
}
|
|
16247
16320
|
}
|
|
16248
|
-
}
|
|
16249
|
-
|
|
16250
|
-
|
|
16251
|
-
|
|
16252
|
-
|
|
16253
|
-
}
|
|
16254
|
-
|
|
16255
|
-
|
|
16256
|
-
|
|
16257
|
-
|
|
16258
|
-
}
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16262
|
-
|
|
16263
|
-
|
|
16264
|
-
|
|
16265
|
-
|
|
16266
|
-
}
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
|
|
16274
|
-
}
|
|
16275
|
-
|
|
16276
|
-
|
|
16277
|
-
|
|
16278
|
-
|
|
16279
|
-
|
|
16280
|
-
}
|
|
16281
|
-
|
|
16282
|
-
|
|
16283
|
-
|
|
16284
|
-
|
|
16285
|
-
}
|
|
16286
|
-
}
|
|
16287
|
-
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
|
|
16291
|
-
|
|
16292
|
-
|
|
16293
|
-
});
|
|
16321
|
+
},
|
|
16322
|
+
a: (aNode) => {
|
|
16323
|
+
visitHref(aNode, {
|
|
16324
|
+
type: "a_href",
|
|
16325
|
+
});
|
|
16326
|
+
},
|
|
16327
|
+
iframe: (iframeNode) => {
|
|
16328
|
+
visitSrc(iframeNode, {
|
|
16329
|
+
type: "iframe_src",
|
|
16330
|
+
});
|
|
16331
|
+
},
|
|
16332
|
+
img: (imgNode) => {
|
|
16333
|
+
visitSrc(imgNode, {
|
|
16334
|
+
type: "img_src",
|
|
16335
|
+
});
|
|
16336
|
+
visitSrcset(imgNode, {
|
|
16337
|
+
type: "img_srcset",
|
|
16338
|
+
});
|
|
16339
|
+
},
|
|
16340
|
+
source: (sourceNode) => {
|
|
16341
|
+
visitSrc(sourceNode, {
|
|
16342
|
+
type: "source_src",
|
|
16343
|
+
});
|
|
16344
|
+
visitSrcset(sourceNode, {
|
|
16345
|
+
type: "source_srcset",
|
|
16346
|
+
});
|
|
16347
|
+
},
|
|
16348
|
+
// svg <image> tag
|
|
16349
|
+
image: (imageNode) => {
|
|
16350
|
+
visitHref(imageNode, {
|
|
16351
|
+
type: "image_href",
|
|
16352
|
+
});
|
|
16353
|
+
},
|
|
16354
|
+
use: (useNode) => {
|
|
16355
|
+
visitHref(useNode, {
|
|
16356
|
+
type: "use_href",
|
|
16357
|
+
});
|
|
16358
|
+
},
|
|
16359
|
+
});
|
|
16360
|
+
if (!importmapFound) {
|
|
16361
|
+
importmapLoaded();
|
|
16362
|
+
}
|
|
16363
|
+
finalizeCallbacks.forEach((finalizeCallback) => {
|
|
16364
|
+
finalizeCallback();
|
|
16365
|
+
});
|
|
16294
16366
|
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
|
|
16299
|
-
|
|
16300
|
-
|
|
16367
|
+
if (actions.length > 0) {
|
|
16368
|
+
await Promise.all(actions.map((action) => action()));
|
|
16369
|
+
actions.length = 0;
|
|
16370
|
+
}
|
|
16371
|
+
if (mutations.length === 0) {
|
|
16372
|
+
return null;
|
|
16373
|
+
}
|
|
16374
|
+
mutations.forEach((mutation) => mutation());
|
|
16375
|
+
mutations.length = 0;
|
|
16376
|
+
return stringifyHtmlAst(htmlAst);
|
|
16377
|
+
} catch (e) {
|
|
16378
|
+
importmapLoaded();
|
|
16379
|
+
throw e;
|
|
16301
16380
|
}
|
|
16302
|
-
mutations.forEach((mutation) => mutation());
|
|
16303
|
-
mutations.length = 0;
|
|
16304
|
-
return stringifyHtmlAst(htmlAst);
|
|
16305
16381
|
},
|
|
16306
16382
|
},
|
|
16307
16383
|
};
|
|
16308
16384
|
};
|
|
16309
16385
|
|
|
16386
|
+
const visitNonIgnoredHtmlNode = (htmlAst, visitors) => {
|
|
16387
|
+
const visitorsInstrumented = {};
|
|
16388
|
+
for (const key of Object.keys(visitors)) {
|
|
16389
|
+
visitorsInstrumented[key] = (node) => {
|
|
16390
|
+
const jsenvIgnoreAttribute = getHtmlNodeAttribute(node, "jsenv-ignore");
|
|
16391
|
+
if (jsenvIgnoreAttribute !== undefined) {
|
|
16392
|
+
return;
|
|
16393
|
+
}
|
|
16394
|
+
visitors[key](node);
|
|
16395
|
+
};
|
|
16396
|
+
}
|
|
16397
|
+
visitHtmlNodes(htmlAst, visitorsInstrumented);
|
|
16398
|
+
};
|
|
16399
|
+
|
|
16400
|
+
const generateHtmlForSyntaxError = (
|
|
16401
|
+
htmlSyntaxError,
|
|
16402
|
+
{ htmlUrl, rootDirectoryUrl, htmlErrorContentFrame },
|
|
16403
|
+
) => {
|
|
16404
|
+
const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
|
|
16405
|
+
const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
|
|
16406
|
+
const { line, column } = htmlSyntaxError;
|
|
16407
|
+
const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
|
|
16408
|
+
const replacers = {
|
|
16409
|
+
fileRelativeUrl: htmlRelativeUrl,
|
|
16410
|
+
reasonCode: htmlSyntaxError.reasonCode,
|
|
16411
|
+
errorLinkHref: `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
|
|
16412
|
+
urlWithLineAndColumn,
|
|
16413
|
+
)}')`,
|
|
16414
|
+
errorLinkText: `${htmlRelativeUrl}:${line}:${column}`,
|
|
16415
|
+
syntaxError: escapeHtml(htmlErrorContentFrame),
|
|
16416
|
+
};
|
|
16417
|
+
const html = replacePlaceholders$2(htmlForSyntaxError, replacers);
|
|
16418
|
+
return html;
|
|
16419
|
+
};
|
|
16420
|
+
const escapeHtml = (string) => {
|
|
16421
|
+
return string
|
|
16422
|
+
.replace(/&/g, "&")
|
|
16423
|
+
.replace(/</g, "<")
|
|
16424
|
+
.replace(/>/g, ">")
|
|
16425
|
+
.replace(/"/g, """)
|
|
16426
|
+
.replace(/'/g, "'");
|
|
16427
|
+
};
|
|
16428
|
+
const replacePlaceholders$2 = (html, replacers) => {
|
|
16429
|
+
return html.replace(/\${([\w]+)}/g, (match, name) => {
|
|
16430
|
+
const replacer = replacers[name];
|
|
16431
|
+
if (replacer === undefined) {
|
|
16432
|
+
return match;
|
|
16433
|
+
}
|
|
16434
|
+
if (typeof replacer === "function") {
|
|
16435
|
+
return replacer();
|
|
16436
|
+
}
|
|
16437
|
+
return replacer;
|
|
16438
|
+
});
|
|
16439
|
+
};
|
|
16440
|
+
|
|
16310
16441
|
const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
|
|
16311
16442
|
const integrityCompatibleTagNames = ["script", "link", "img", "source"];
|
|
16312
16443
|
const readFetchMetas = (node) => {
|
|
@@ -18036,6 +18167,16 @@ const jsenvPluginVersionSearchParam = () => {
|
|
|
18036
18167
|
};
|
|
18037
18168
|
};
|
|
18038
18169
|
|
|
18170
|
+
const html404AndParentDirIsEmptyFileUrl = new URL(
|
|
18171
|
+
"./html/html_404_and_parent_dir_is_empty.html",
|
|
18172
|
+
import.meta.url,
|
|
18173
|
+
);
|
|
18174
|
+
const html404AndParentDirFileUrl = new URL(
|
|
18175
|
+
"./html/html_404_and_parent_dir.html",
|
|
18176
|
+
import.meta.url,
|
|
18177
|
+
);
|
|
18178
|
+
const htmlFileUrlForDirectory = new URL("./html/directory.html", import.meta.url);
|
|
18179
|
+
|
|
18039
18180
|
const jsenvPluginProtocolFile = ({
|
|
18040
18181
|
magicExtensions = ["inherit", ".js"],
|
|
18041
18182
|
magicDirectoryIndex = true,
|
|
@@ -18122,7 +18263,9 @@ const jsenvPluginProtocolFile = ({
|
|
|
18122
18263
|
reference.leadsToADirectory = stat && stat.isDirectory();
|
|
18123
18264
|
if (reference.leadsToADirectory) {
|
|
18124
18265
|
let actionForDirectory;
|
|
18125
|
-
if (
|
|
18266
|
+
if (reference.type === "a_href") {
|
|
18267
|
+
actionForDirectory = "ignore";
|
|
18268
|
+
} else if (
|
|
18126
18269
|
reference.type === "http_request" ||
|
|
18127
18270
|
reference.type === "filesystem"
|
|
18128
18271
|
) {
|
|
@@ -18207,17 +18350,33 @@ const jsenvPluginProtocolFile = ({
|
|
|
18207
18350
|
urlInfo.filenameHint = `${urlToFilename$1(urlInfo.url)}/`;
|
|
18208
18351
|
}
|
|
18209
18352
|
}
|
|
18210
|
-
const
|
|
18211
|
-
|
|
18212
|
-
|
|
18213
|
-
|
|
18214
|
-
|
|
18215
|
-
|
|
18353
|
+
const directoryContentArray = readdirSync(urlObject);
|
|
18354
|
+
if (urlInfo.firstReference.type === "filesystem") {
|
|
18355
|
+
const content = JSON.stringify(directoryContentArray, null, " ");
|
|
18356
|
+
return {
|
|
18357
|
+
type: "directory",
|
|
18358
|
+
contentType: "application/json",
|
|
18359
|
+
content,
|
|
18360
|
+
};
|
|
18361
|
+
}
|
|
18362
|
+
const acceptsHtml = urlInfo.context.request
|
|
18363
|
+
? pickContentType(urlInfo.context.request, ["text/html"])
|
|
18364
|
+
: false;
|
|
18365
|
+
if (acceptsHtml) {
|
|
18366
|
+
const html = generateHtmlForDirectory(
|
|
18367
|
+
urlObject.href,
|
|
18368
|
+
directoryContentArray,
|
|
18369
|
+
urlInfo.context.rootDirectoryUrl,
|
|
18370
|
+
);
|
|
18371
|
+
return {
|
|
18372
|
+
contentType: "text/html",
|
|
18373
|
+
content: html,
|
|
18374
|
+
};
|
|
18375
|
+
}
|
|
18216
18376
|
return {
|
|
18217
18377
|
type: "directory",
|
|
18218
|
-
contentType:
|
|
18219
|
-
|
|
18220
|
-
content: body,
|
|
18378
|
+
contentType: "application/json",
|
|
18379
|
+
content: JSON.stringify(directoryContentArray, null, " "),
|
|
18221
18380
|
};
|
|
18222
18381
|
}
|
|
18223
18382
|
if (
|
|
@@ -18227,20 +18386,144 @@ const jsenvPluginProtocolFile = ({
|
|
|
18227
18386
|
urlInfo.dirnameHint =
|
|
18228
18387
|
urlInfo.firstReference.ownerUrlInfo.filenameHint;
|
|
18229
18388
|
}
|
|
18230
|
-
const fileBuffer = readFileSync(urlObject);
|
|
18231
18389
|
const contentType = CONTENT_TYPE.fromUrlExtension(urlInfo.url);
|
|
18390
|
+
if (contentType === "text/html") {
|
|
18391
|
+
try {
|
|
18392
|
+
const fileBuffer = readFileSync(urlObject);
|
|
18393
|
+
const content = String(fileBuffer);
|
|
18394
|
+
return {
|
|
18395
|
+
content,
|
|
18396
|
+
contentType,
|
|
18397
|
+
contentLength: fileBuffer.length,
|
|
18398
|
+
};
|
|
18399
|
+
} catch (e) {
|
|
18400
|
+
if (e.code !== "ENOENT") {
|
|
18401
|
+
throw e;
|
|
18402
|
+
}
|
|
18403
|
+
const parentDirectoryUrl = new URL("./", urlInfo.url);
|
|
18404
|
+
if (!existsSync(parentDirectoryUrl)) {
|
|
18405
|
+
throw e;
|
|
18406
|
+
}
|
|
18407
|
+
const parentDirectoryContentArray = readdirSync(
|
|
18408
|
+
new URL(parentDirectoryUrl),
|
|
18409
|
+
);
|
|
18410
|
+
const html = generateHtmlForENOENTOnHtmlFile(
|
|
18411
|
+
urlInfo.url,
|
|
18412
|
+
parentDirectoryContentArray,
|
|
18413
|
+
parentDirectoryUrl,
|
|
18414
|
+
urlInfo.context.rootDirectoryUrl,
|
|
18415
|
+
);
|
|
18416
|
+
return {
|
|
18417
|
+
contentType: "text/html",
|
|
18418
|
+
content: html,
|
|
18419
|
+
};
|
|
18420
|
+
}
|
|
18421
|
+
}
|
|
18422
|
+
const fileBuffer = readFileSync(urlObject);
|
|
18232
18423
|
const content = CONTENT_TYPE.isTextual(contentType)
|
|
18233
18424
|
? String(fileBuffer)
|
|
18234
18425
|
: fileBuffer;
|
|
18235
18426
|
return {
|
|
18236
18427
|
content,
|
|
18237
18428
|
contentType,
|
|
18429
|
+
contentLength: fileBuffer.length,
|
|
18238
18430
|
};
|
|
18239
18431
|
},
|
|
18240
18432
|
},
|
|
18241
18433
|
];
|
|
18242
18434
|
};
|
|
18243
18435
|
|
|
18436
|
+
const generateHtmlForDirectory = (
|
|
18437
|
+
directoryUrl,
|
|
18438
|
+
directoryContentArray,
|
|
18439
|
+
rootDirectoryUrl,
|
|
18440
|
+
) => {
|
|
18441
|
+
directoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
|
|
18442
|
+
const htmlForDirectory = String(readFileSync(htmlFileUrlForDirectory));
|
|
18443
|
+
const replacers = {
|
|
18444
|
+
directoryRelativeUrl: urlToRelativeUrl(directoryUrl, rootDirectoryUrl),
|
|
18445
|
+
directoryUrl,
|
|
18446
|
+
directoryContent: () =>
|
|
18447
|
+
generateDirectoryContent(
|
|
18448
|
+
directoryContentArray,
|
|
18449
|
+
directoryUrl,
|
|
18450
|
+
rootDirectoryUrl,
|
|
18451
|
+
),
|
|
18452
|
+
};
|
|
18453
|
+
const html = replacePlaceholders$1(htmlForDirectory, replacers);
|
|
18454
|
+
return html;
|
|
18455
|
+
};
|
|
18456
|
+
const generateHtmlForENOENTOnHtmlFile = (
|
|
18457
|
+
url,
|
|
18458
|
+
parentDirectoryContentArray,
|
|
18459
|
+
parentDirectoryUrl,
|
|
18460
|
+
rootDirectoryUrl,
|
|
18461
|
+
) => {
|
|
18462
|
+
if (parentDirectoryContentArray.length === 0) {
|
|
18463
|
+
const htmlFor404AndParentDirIsEmpty = String(
|
|
18464
|
+
readFileSync(html404AndParentDirIsEmptyFileUrl),
|
|
18465
|
+
);
|
|
18466
|
+
return replacePlaceholders$1(htmlFor404AndParentDirIsEmpty, {
|
|
18467
|
+
fileRelativeUrl: urlToRelativeUrl(url, rootDirectoryUrl),
|
|
18468
|
+
parentDirectoryRelativeUrl: urlToRelativeUrl(
|
|
18469
|
+
parentDirectoryUrl,
|
|
18470
|
+
rootDirectoryUrl,
|
|
18471
|
+
),
|
|
18472
|
+
});
|
|
18473
|
+
}
|
|
18474
|
+
const htmlFor404AndParentDir = String(
|
|
18475
|
+
readFileSync(html404AndParentDirFileUrl),
|
|
18476
|
+
);
|
|
18477
|
+
|
|
18478
|
+
const replacers = {
|
|
18479
|
+
fileUrl: url,
|
|
18480
|
+
fileRelativeUrl: urlToRelativeUrl(url, rootDirectoryUrl),
|
|
18481
|
+
parentDirectoryUrl,
|
|
18482
|
+
parentDirectoryRelativeUrl: urlToRelativeUrl(
|
|
18483
|
+
parentDirectoryUrl,
|
|
18484
|
+
rootDirectoryUrl,
|
|
18485
|
+
),
|
|
18486
|
+
parentDirectoryContent: () =>
|
|
18487
|
+
generateDirectoryContent(
|
|
18488
|
+
parentDirectoryContentArray,
|
|
18489
|
+
parentDirectoryUrl,
|
|
18490
|
+
rootDirectoryUrl,
|
|
18491
|
+
),
|
|
18492
|
+
};
|
|
18493
|
+
const html = replacePlaceholders$1(htmlFor404AndParentDir, replacers);
|
|
18494
|
+
return html;
|
|
18495
|
+
};
|
|
18496
|
+
const generateDirectoryContent = (
|
|
18497
|
+
directoryContentArray,
|
|
18498
|
+
directoryUrl,
|
|
18499
|
+
rootDirectoryUrl,
|
|
18500
|
+
) => {
|
|
18501
|
+
return directoryContentArray.map((filename) => {
|
|
18502
|
+
const fileUrlObject = new URL(filename, directoryUrl);
|
|
18503
|
+
const fileUrl = String(fileUrlObject);
|
|
18504
|
+
let fileUrlRelative = urlToRelativeUrl(fileUrl, rootDirectoryUrl);
|
|
18505
|
+
if (lstatSync(fileUrlObject).isDirectory()) {
|
|
18506
|
+
fileUrlRelative += "/";
|
|
18507
|
+
}
|
|
18508
|
+
return `<li>
|
|
18509
|
+
<a href="/${fileUrlRelative}">/${fileUrlRelative}</a>
|
|
18510
|
+
</li>`;
|
|
18511
|
+
}).join(`
|
|
18512
|
+
`);
|
|
18513
|
+
};
|
|
18514
|
+
const replacePlaceholders$1 = (html, replacers) => {
|
|
18515
|
+
return html.replace(/\${([\w]+)}/g, (match, name) => {
|
|
18516
|
+
const replacer = replacers[name];
|
|
18517
|
+
if (replacer === undefined) {
|
|
18518
|
+
return match;
|
|
18519
|
+
}
|
|
18520
|
+
if (typeof replacer === "function") {
|
|
18521
|
+
return replacer();
|
|
18522
|
+
}
|
|
18523
|
+
return replacer;
|
|
18524
|
+
});
|
|
18525
|
+
};
|
|
18526
|
+
|
|
18244
18527
|
const resolveSymlink = (fileUrl) => {
|
|
18245
18528
|
const urlObject = new URL(fileUrl);
|
|
18246
18529
|
const realpath = realpathSync(urlObject);
|
|
@@ -19409,12 +19692,21 @@ const jsenvPluginAutoreloadClient = () => {
|
|
|
19409
19692
|
expectedType: "js_module",
|
|
19410
19693
|
specifier: autoreloadClientFileUrl,
|
|
19411
19694
|
});
|
|
19695
|
+
const paramsJson = JSON.stringify(
|
|
19696
|
+
{
|
|
19697
|
+
mainFilePath: `/${htmlUrlInfo.kitchen.context.mainFilePath}`,
|
|
19698
|
+
},
|
|
19699
|
+
null,
|
|
19700
|
+
" ",
|
|
19701
|
+
);
|
|
19412
19702
|
injectHtmlNodeAsEarlyAsPossible(
|
|
19413
19703
|
htmlAst,
|
|
19414
19704
|
createHtmlNode({
|
|
19415
19705
|
tagName: "script",
|
|
19416
19706
|
type: "module",
|
|
19417
|
-
|
|
19707
|
+
textContent: `import { initAutoreload } from "${autoreloadClientReference.generatedSpecifier}";
|
|
19708
|
+
|
|
19709
|
+
initAutoreload(${paramsJson});`,
|
|
19418
19710
|
}),
|
|
19419
19711
|
"jsenv:autoreload_client",
|
|
19420
19712
|
);
|
|
@@ -19465,7 +19757,10 @@ const jsenvPluginAutoreloadServer = ({
|
|
|
19465
19757
|
: `a dependent file accepts hot reload`,
|
|
19466
19758
|
};
|
|
19467
19759
|
}
|
|
19468
|
-
if (
|
|
19760
|
+
if (
|
|
19761
|
+
urlInfo.data.hotDecline ||
|
|
19762
|
+
urlInfo.firstReference?.type === "http_request"
|
|
19763
|
+
) {
|
|
19469
19764
|
return {
|
|
19470
19765
|
declined: true,
|
|
19471
19766
|
reason: `file declines hot reload`,
|
|
@@ -19859,7 +20154,7 @@ const jsenvPluginRibbon = ({
|
|
|
19859
20154
|
createHtmlNode({
|
|
19860
20155
|
tagName: "script",
|
|
19861
20156
|
type: "module",
|
|
19862
|
-
textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}"
|
|
20157
|
+
textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}";
|
|
19863
20158
|
|
|
19864
20159
|
injectRibbon(${paramsJson});`,
|
|
19865
20160
|
}),
|
|
@@ -22302,11 +22597,18 @@ const startDevServer = async ({
|
|
|
22302
22597
|
sourceDirectoryUrl,
|
|
22303
22598
|
"sourceDirectoryUrl",
|
|
22304
22599
|
);
|
|
22600
|
+
if (!existsSync(new URL(sourceDirectoryUrl))) {
|
|
22601
|
+
throw new Error(`ENOENT on sourceDirectoryUrl at ${sourceDirectoryUrl}`);
|
|
22602
|
+
}
|
|
22305
22603
|
if (typeof sourceMainFilePath !== "string") {
|
|
22306
22604
|
throw new TypeError(
|
|
22307
22605
|
`sourceMainFilePath must be a string, got ${sourceMainFilePath}`,
|
|
22308
22606
|
);
|
|
22309
22607
|
}
|
|
22608
|
+
sourceMainFilePath = urlToRelativeUrl(
|
|
22609
|
+
new URL(sourceMainFilePath, sourceDirectoryUrl),
|
|
22610
|
+
sourceDirectoryUrl,
|
|
22611
|
+
);
|
|
22310
22612
|
if (outDirectoryUrl === undefined) {
|
|
22311
22613
|
if (!process.env.CI) {
|
|
22312
22614
|
const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
|