@jsenv/core 35.0.5 → 36.0.1
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/README.md +1 -1
- package/dist/js/inline_content.js +5 -4
- package/dist/jsenv_core.js +1127 -1497
- package/package.json +8 -8
- package/src/build/build.js +49 -41
- package/src/dev/file_service.js +7 -17
- package/src/dev/start_dev_server.js +12 -7
- package/src/kitchen/kitchen.js +38 -19
- package/src/kitchen/url_graph.js +1 -1
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +2 -2
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +4 -4
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +1 -1
- package/src/plugins/importmap/jsenv_plugin_importmap.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining.js +1 -1
- package/src/plugins/inlining/jsenv_plugin_inlining_as_data_url.js +13 -2
- package/src/plugins/plugin_controller.js +19 -10
- package/src/plugins/plugins.js +21 -25
- package/src/plugins/{url_analysis/css/css_urls.js → reference_analysis/css/jsenv_plugin_css_reference_analysis.js} +11 -1
- package/src/plugins/{inline_content_analysis/jsenv_plugin_data_urls.js → reference_analysis/data_urls/jsenv_plugin_data_urls_analysis.js} +19 -19
- package/src/plugins/reference_analysis/directory/jsenv_plugin_directory_reference_analysis.js +51 -0
- package/src/plugins/reference_analysis/html/jsenv_plugin_html_reference_analysis.js +429 -0
- package/src/plugins/reference_analysis/inline_content.js +7 -0
- package/src/plugins/reference_analysis/js/jsenv_plugin_js_reference_analysis.js +161 -0
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +120 -0
- package/src/plugins/{url_analysis → reference_analysis}/jsenv_plugin_reference_expected_types.js +19 -12
- package/src/plugins/{url_analysis/webmanifest/webmanifest_urls.js → reference_analysis/webmanifest/jsenv_plugin_webmanifest_reference_analysis.js} +13 -1
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +74 -0
- package/src/plugins/{url_resolution → resolution_node_esm}/node_esm_resolver.js +8 -0
- package/src/plugins/resolution_web/jsenv_plugin_web_resolution.js +45 -0
- package/src/plugins/transpilation/as_js_module/jsenv_plugin_as_js_module.js +1 -1
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_conversion.js +1 -1
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_inside_html.js +4 -6
- package/src/plugins/transpilation/js_module_fallback/jsenv_plugin_js_module_fallback_on_workers.js +1 -1
- package/src/plugins/url_type_from_reference.js +13 -0
- package/src/plugins/{url_version/jsenv_plugin_url_version.js → version_search_param/jsenv_plugin_version_search_param.js} +4 -4
- package/dist/html/explorer.html +0 -559
- package/dist/other/jsenv.png +0 -0
- package/src/plugins/explorer/client/explorer.html +0 -608
- package/src/plugins/explorer/client/jsenv.png +0 -0
- package/src/plugins/explorer/jsenv_plugin_explorer.js +0 -86
- package/src/plugins/inline_content_analysis/client/inline_content.js +0 -6
- package/src/plugins/inline_content_analysis/jsenv_plugin_html_inline_content_analysis.js +0 -206
- package/src/plugins/inline_content_analysis/jsenv_plugin_inline_content_analysis.js +0 -34
- package/src/plugins/inline_content_analysis/jsenv_plugin_js_inline_content_analysis.js +0 -314
- package/src/plugins/url_analysis/html/html_urls.js +0 -313
- package/src/plugins/url_analysis/js/js_urls.js +0 -65
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +0 -116
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +0 -140
package/dist/jsenv_core.js
CHANGED
|
@@ -14,7 +14,7 @@ import { Readable, Stream, Writable } from "node:stream";
|
|
|
14
14
|
import { Http2ServerResponse } from "node:http2";
|
|
15
15
|
import { lookup } from "node:dns";
|
|
16
16
|
import { SOURCEMAP, generateSourcemapFileUrl, composeTwoSourcemaps, generateSourcemapDataUrl, createMagicSource, getOriginalPosition } from "@jsenv/sourcemap";
|
|
17
|
-
import { parseHtmlString,
|
|
17
|
+
import { parseHtmlString, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, stringifyHtmlAst, parseSrcSet, getHtmlNodeText, setHtmlNodeAttributes, getHtmlNodePosition, getHtmlNodeAttributePosition, removeHtmlNodeText, setHtmlNodeText, parseCssUrls, parseJsUrls, applyBabelPlugins, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, findHtmlNode, removeHtmlNode, injectJsImport, analyzeLinkNode, injectHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
19
19
|
import babelParser from "@babel/parser";
|
|
20
20
|
|
|
@@ -139,6 +139,10 @@ const generateInlineContentUrl = ({
|
|
|
139
139
|
};
|
|
140
140
|
|
|
141
141
|
// consider switching to https://babeljs.io/docs/en/babel-code-frame
|
|
142
|
+
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/css-syntax-error.js#L43
|
|
143
|
+
// https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/terminal-highlight.js#L50
|
|
144
|
+
// https://github.com/babel/babel/blob/eea156b2cb8deecfcf82d52aa1b71ba4995c7d68/packages/babel-code-frame/src/index.js#L1
|
|
145
|
+
|
|
142
146
|
const stringifyUrlSite = ({
|
|
143
147
|
url,
|
|
144
148
|
line,
|
|
@@ -791,6 +795,7 @@ const getPermissionOrComputeDefault = (action, subject, permissions) => {
|
|
|
791
795
|
* - stats object documentation on Node.js
|
|
792
796
|
* https://nodejs.org/docs/latest-v13.x/api/fs.html#fs_class_fs_stats
|
|
793
797
|
*/
|
|
798
|
+
|
|
794
799
|
const isWindows$3 = process.platform === "win32";
|
|
795
800
|
const readEntryStat = async (source, {
|
|
796
801
|
nullIfNotFound = false,
|
|
@@ -861,6 +866,7 @@ const readStat = (sourcePath, {
|
|
|
861
866
|
* - eTag documentation on MDN
|
|
862
867
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
|
|
863
868
|
*/
|
|
869
|
+
|
|
864
870
|
const ETAG_FOR_EMPTY_CONTENT$1 = '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
|
|
865
871
|
const bufferToEtag$1 = buffer => {
|
|
866
872
|
if (!Buffer.isBuffer(buffer)) {
|
|
@@ -1023,6 +1029,7 @@ const removeNoop = () => {};
|
|
|
1023
1029
|
/*
|
|
1024
1030
|
* https://github.com/whatwg/dom/issues/920
|
|
1025
1031
|
*/
|
|
1032
|
+
|
|
1026
1033
|
const Abort = {
|
|
1027
1034
|
isAbortError: error => {
|
|
1028
1035
|
return error && error.name === "AbortError";
|
|
@@ -1414,6 +1421,7 @@ const asFlatAssociations = associations => {
|
|
|
1414
1421
|
* https://github.com/kaelzhang/node-ignore
|
|
1415
1422
|
*/
|
|
1416
1423
|
|
|
1424
|
+
|
|
1417
1425
|
/** @module jsenv_url_meta **/
|
|
1418
1426
|
/**
|
|
1419
1427
|
* An object representing the result of applying a pattern to an url
|
|
@@ -1881,80 +1889,6 @@ const comparePathnames = (leftPathame, rightPathname) => {
|
|
|
1881
1889
|
return 0;
|
|
1882
1890
|
};
|
|
1883
1891
|
|
|
1884
|
-
const collectFiles = async ({
|
|
1885
|
-
signal = new AbortController().signal,
|
|
1886
|
-
directoryUrl,
|
|
1887
|
-
associations,
|
|
1888
|
-
predicate
|
|
1889
|
-
}) => {
|
|
1890
|
-
const rootDirectoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
|
|
1891
|
-
if (typeof predicate !== "function") {
|
|
1892
|
-
throw new TypeError(`predicate must be a function, got ${predicate}`);
|
|
1893
|
-
}
|
|
1894
|
-
associations = URL_META.resolveAssociations(associations, rootDirectoryUrl);
|
|
1895
|
-
const collectOperation = Abort.startOperation();
|
|
1896
|
-
collectOperation.addAbortSignal(signal);
|
|
1897
|
-
const matchingFileResultArray = [];
|
|
1898
|
-
const visitDirectory = async directoryUrl => {
|
|
1899
|
-
collectOperation.throwIfAborted();
|
|
1900
|
-
const directoryItems = await readDirectory(directoryUrl);
|
|
1901
|
-
await Promise.all(directoryItems.map(async directoryItem => {
|
|
1902
|
-
const directoryChildNodeUrl = `${directoryUrl}${directoryItem}`;
|
|
1903
|
-
collectOperation.throwIfAborted();
|
|
1904
|
-
const directoryChildNodeStats = await readEntryStat(directoryChildNodeUrl, {
|
|
1905
|
-
// we ignore symlink because recursively traversed
|
|
1906
|
-
// so symlinked file will be discovered.
|
|
1907
|
-
// Moreover if they lead outside of directoryPath it can become a problem
|
|
1908
|
-
// like infinite recursion of whatever.
|
|
1909
|
-
// that we could handle using an object of pathname already seen but it will be useless
|
|
1910
|
-
// because directoryPath is recursively traversed
|
|
1911
|
-
followLink: false
|
|
1912
|
-
});
|
|
1913
|
-
if (directoryChildNodeStats.isDirectory()) {
|
|
1914
|
-
const subDirectoryUrl = `${directoryChildNodeUrl}/`;
|
|
1915
|
-
if (!URL_META.urlChildMayMatch({
|
|
1916
|
-
url: subDirectoryUrl,
|
|
1917
|
-
associations,
|
|
1918
|
-
predicate
|
|
1919
|
-
})) {
|
|
1920
|
-
return;
|
|
1921
|
-
}
|
|
1922
|
-
await visitDirectory(subDirectoryUrl);
|
|
1923
|
-
return;
|
|
1924
|
-
}
|
|
1925
|
-
if (directoryChildNodeStats.isFile()) {
|
|
1926
|
-
const meta = URL_META.applyAssociations({
|
|
1927
|
-
url: directoryChildNodeUrl,
|
|
1928
|
-
associations
|
|
1929
|
-
});
|
|
1930
|
-
if (!predicate(meta)) return;
|
|
1931
|
-
const relativeUrl = urlToRelativeUrl(directoryChildNodeUrl, rootDirectoryUrl);
|
|
1932
|
-
matchingFileResultArray.push({
|
|
1933
|
-
url: new URL(relativeUrl, rootDirectoryUrl).href,
|
|
1934
|
-
relativeUrl: decodeURIComponent(relativeUrl),
|
|
1935
|
-
meta,
|
|
1936
|
-
fileStats: directoryChildNodeStats
|
|
1937
|
-
});
|
|
1938
|
-
return;
|
|
1939
|
-
}
|
|
1940
|
-
}));
|
|
1941
|
-
};
|
|
1942
|
-
try {
|
|
1943
|
-
await visitDirectory(rootDirectoryUrl);
|
|
1944
|
-
|
|
1945
|
-
// When we operate on thoose files later it feels more natural
|
|
1946
|
-
// to perform operation in the same order they appear in the filesystem.
|
|
1947
|
-
// It also allow to get a predictable return value.
|
|
1948
|
-
// For that reason we sort matchingFileResultArray
|
|
1949
|
-
matchingFileResultArray.sort((leftFile, rightFile) => {
|
|
1950
|
-
return comparePathnames(leftFile.relativeUrl, rightFile.relativeUrl);
|
|
1951
|
-
});
|
|
1952
|
-
return matchingFileResultArray;
|
|
1953
|
-
} finally {
|
|
1954
|
-
await collectOperation.end();
|
|
1955
|
-
}
|
|
1956
|
-
};
|
|
1957
|
-
|
|
1958
1892
|
// https://nodejs.org/dist/latest-v13.x/docs/api/fs.html#fs_fspromises_mkdir_path_options
|
|
1959
1893
|
const {
|
|
1960
1894
|
mkdir
|
|
@@ -3011,6 +2945,7 @@ function isUnicodeSupported() {
|
|
|
3011
2945
|
}
|
|
3012
2946
|
|
|
3013
2947
|
// see also https://github.com/sindresorhus/figures
|
|
2948
|
+
|
|
3014
2949
|
const canUseUnicode = isUnicodeSupported();
|
|
3015
2950
|
const COMMAND_RAW = canUseUnicode ? `❯` : `>`;
|
|
3016
2951
|
const OK_RAW = canUseUnicode ? `✔` : `√`;
|
|
@@ -3428,6 +3363,7 @@ const spyStreamOutput = stream => {
|
|
|
3428
3363
|
/*
|
|
3429
3364
|
* see also https://github.com/vadimdemedes/ink
|
|
3430
3365
|
*/
|
|
3366
|
+
|
|
3431
3367
|
const createLog = ({
|
|
3432
3368
|
stream = process.stdout,
|
|
3433
3369
|
newLine = "after"
|
|
@@ -4022,6 +3958,7 @@ const listenEvent = (objectWithEventEmitter, eventName, callback, {
|
|
|
4022
3958
|
https://stackoverflow.com/a/42019773/2634179
|
|
4023
3959
|
|
|
4024
3960
|
*/
|
|
3961
|
+
|
|
4025
3962
|
const createPolyglotServer = async ({
|
|
4026
3963
|
http2 = false,
|
|
4027
3964
|
http1Allowed = true,
|
|
@@ -4481,6 +4418,7 @@ const normalizeHeaderValue = headerValue => {
|
|
|
4481
4418
|
https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
|
4482
4419
|
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
|
|
4483
4420
|
*/
|
|
4421
|
+
|
|
4484
4422
|
const headersFromObject = headersObject => {
|
|
4485
4423
|
const headers = {};
|
|
4486
4424
|
Object.keys(headersObject).forEach(headerName => {
|
|
@@ -6769,6 +6707,7 @@ const serveDirectory = (url, {
|
|
|
6769
6707
|
* { status: 200, body: "Hello world" }.
|
|
6770
6708
|
* It is meant to be used inside "requestToResponse"
|
|
6771
6709
|
*/
|
|
6710
|
+
|
|
6772
6711
|
const fetchFileSystem = async (filesystemUrl, {
|
|
6773
6712
|
// signal,
|
|
6774
6713
|
method = "GET",
|
|
@@ -7856,7 +7795,7 @@ const createUrlInfo = url => {
|
|
|
7856
7795
|
dependents: new Set(),
|
|
7857
7796
|
implicitUrls: new Set(),
|
|
7858
7797
|
type: undefined,
|
|
7859
|
-
// "html", "css", "js_classic", "js_module", "importmap", "json", "webmanifest", ...
|
|
7798
|
+
// "html", "css", "js_classic", "js_module", "importmap", "sourcemap", "json", "webmanifest", ...
|
|
7860
7799
|
subtype: undefined,
|
|
7861
7800
|
// "worker", "service_worker", "shared_worker" for js, otherwise undefined
|
|
7862
7801
|
typeHint: undefined,
|
|
@@ -7891,7 +7830,7 @@ const createUrlInfo = url => {
|
|
|
7891
7830
|
|
|
7892
7831
|
const HOOK_NAMES = ["init", "serve",
|
|
7893
7832
|
// is called only during dev/tests
|
|
7894
|
-
"
|
|
7833
|
+
"resolveReference", "redirectReference", "transformReferenceSearchParams", "formatReference", "fetchUrlContent", "transformUrlContent", "finalizeUrlContent", "bundle",
|
|
7895
7834
|
// is called only during build
|
|
7896
7835
|
"optimizeUrlContent",
|
|
7897
7836
|
// is called only during build
|
|
@@ -7905,8 +7844,19 @@ const createPluginController = kitchenContext => {
|
|
|
7905
7844
|
// also it should increase perf as there is less work to do
|
|
7906
7845
|
const hookGroups = {};
|
|
7907
7846
|
const addPlugin = (plugin, {
|
|
7908
|
-
position = "
|
|
7847
|
+
position = "end"
|
|
7909
7848
|
}) => {
|
|
7849
|
+
if (Array.isArray(plugin)) {
|
|
7850
|
+
if (position === "start") {
|
|
7851
|
+
plugin = plugin.slice().reverse();
|
|
7852
|
+
}
|
|
7853
|
+
plugin.forEach(plugin => {
|
|
7854
|
+
addPlugin(plugin, {
|
|
7855
|
+
position
|
|
7856
|
+
});
|
|
7857
|
+
});
|
|
7858
|
+
return;
|
|
7859
|
+
}
|
|
7910
7860
|
if (plugin === null || typeof plugin !== "object") {
|
|
7911
7861
|
throw new TypeError(`plugin must be objects, got ${plugin}`);
|
|
7912
7862
|
}
|
|
@@ -7938,9 +7888,9 @@ const createPluginController = kitchenContext => {
|
|
|
7938
7888
|
value: hookValue
|
|
7939
7889
|
};
|
|
7940
7890
|
if (position === "start") {
|
|
7941
|
-
group.push(hook);
|
|
7942
|
-
} else {
|
|
7943
7891
|
group.unshift(hook);
|
|
7892
|
+
} else {
|
|
7893
|
+
group.push(hook);
|
|
7944
7894
|
}
|
|
7945
7895
|
}
|
|
7946
7896
|
});
|
|
@@ -7993,12 +7943,12 @@ const createPluginController = kitchenContext => {
|
|
|
7993
7943
|
};
|
|
7994
7944
|
const pushPlugin = plugin => {
|
|
7995
7945
|
addPlugin(plugin, {
|
|
7996
|
-
position: "
|
|
7946
|
+
position: "end"
|
|
7997
7947
|
});
|
|
7998
7948
|
};
|
|
7999
7949
|
const unshiftPlugin = plugin => {
|
|
8000
7950
|
addPlugin(plugin, {
|
|
8001
|
-
position: "
|
|
7951
|
+
position: "start"
|
|
8002
7952
|
});
|
|
8003
7953
|
};
|
|
8004
7954
|
let lastPluginUsed = null;
|
|
@@ -8155,7 +8105,7 @@ const assertAndNormalizeReturnValue = (hookName, returnValue) => {
|
|
|
8155
8105
|
};
|
|
8156
8106
|
const returnValueAssertions = [{
|
|
8157
8107
|
name: "url_assertion",
|
|
8158
|
-
appliesTo: ["
|
|
8108
|
+
appliesTo: ["resolveReference", "redirectReference"],
|
|
8159
8109
|
assertion: valueReturned => {
|
|
8160
8110
|
if (valueReturned instanceof URL) {
|
|
8161
8111
|
return valueReturned.href;
|
|
@@ -9151,6 +9101,7 @@ const createKitchen = ({
|
|
|
9151
9101
|
signal,
|
|
9152
9102
|
logLevel,
|
|
9153
9103
|
rootDirectoryUrl,
|
|
9104
|
+
mainFilePath,
|
|
9154
9105
|
urlGraph,
|
|
9155
9106
|
dev = false,
|
|
9156
9107
|
build = false,
|
|
@@ -9175,6 +9126,7 @@ const createKitchen = ({
|
|
|
9175
9126
|
signal,
|
|
9176
9127
|
logger,
|
|
9177
9128
|
rootDirectoryUrl,
|
|
9129
|
+
mainFilePath,
|
|
9178
9130
|
urlGraph,
|
|
9179
9131
|
dev,
|
|
9180
9132
|
build,
|
|
@@ -9192,16 +9144,34 @@ const createKitchen = ({
|
|
|
9192
9144
|
outDirectoryUrl
|
|
9193
9145
|
};
|
|
9194
9146
|
const pluginController = createPluginController(kitchenContext);
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9147
|
+
plugins.forEach(pluginEntry => {
|
|
9148
|
+
pluginController.pushPlugin(pluginEntry);
|
|
9149
|
+
});
|
|
9150
|
+
|
|
9151
|
+
/*
|
|
9152
|
+
* - "http_request"
|
|
9153
|
+
* - "entry_point"
|
|
9154
|
+
* - "link_href"
|
|
9155
|
+
* - "style"
|
|
9156
|
+
* - "script"
|
|
9157
|
+
* - "a_href"
|
|
9158
|
+
* - "iframe_src
|
|
9159
|
+
* - "img_src"
|
|
9160
|
+
* - "img_srcset"
|
|
9161
|
+
* - "source_src"
|
|
9162
|
+
* - "source_srcset"
|
|
9163
|
+
* - "image_href"
|
|
9164
|
+
* - "use_href"
|
|
9165
|
+
* - "css_@import"
|
|
9166
|
+
* - "css_url"
|
|
9167
|
+
* - "js_import"
|
|
9168
|
+
* - "js_import_script"
|
|
9169
|
+
* - "js_url"
|
|
9170
|
+
* - "js_inline_content"
|
|
9171
|
+
* - "sourcemap_comment"
|
|
9172
|
+
* - "webmanifest_icon_src"
|
|
9173
|
+
* - "package_json"
|
|
9174
|
+
* */
|
|
9205
9175
|
const createReference = ({
|
|
9206
9176
|
data = {},
|
|
9207
9177
|
node,
|
|
@@ -9306,14 +9276,14 @@ const createKitchen = ({
|
|
|
9306
9276
|
resolveReference: (reference, context = referenceContext) => resolveReference(reference, context)
|
|
9307
9277
|
};
|
|
9308
9278
|
try {
|
|
9309
|
-
let
|
|
9310
|
-
if (!
|
|
9279
|
+
let url = pluginController.callHooksUntil("resolveReference", reference, referenceContext);
|
|
9280
|
+
if (!url) {
|
|
9311
9281
|
throw new Error(`NO_RESOLVE`);
|
|
9312
9282
|
}
|
|
9313
|
-
if (
|
|
9283
|
+
if (url.includes("?debug")) {
|
|
9314
9284
|
reference.debug = true;
|
|
9315
9285
|
}
|
|
9316
|
-
|
|
9286
|
+
url = normalizeUrl(url);
|
|
9317
9287
|
let referencedUrlObject;
|
|
9318
9288
|
let searchParams;
|
|
9319
9289
|
const onReferenceUrlChange = referenceUrl => {
|
|
@@ -9322,14 +9292,14 @@ const createKitchen = ({
|
|
|
9322
9292
|
reference.url = referenceUrl;
|
|
9323
9293
|
reference.searchParams = searchParams;
|
|
9324
9294
|
};
|
|
9325
|
-
onReferenceUrlChange(
|
|
9295
|
+
onReferenceUrlChange(url);
|
|
9326
9296
|
if (reference.debug) {
|
|
9327
9297
|
logger.debug(`url resolved by "${pluginController.getLastPluginUsed().name}"
|
|
9328
9298
|
${ANSI.color(reference.specifier, ANSI.GREY)} ->
|
|
9329
9299
|
${ANSI.color(reference.url, ANSI.YELLOW)}
|
|
9330
9300
|
`);
|
|
9331
9301
|
}
|
|
9332
|
-
pluginController.callHooks("
|
|
9302
|
+
pluginController.callHooks("redirectReference", reference, referenceContext, (returnValue, plugin) => {
|
|
9333
9303
|
const normalizedReturnValue = normalizeUrl(returnValue);
|
|
9334
9304
|
if (normalizedReturnValue === reference.url) {
|
|
9335
9305
|
return;
|
|
@@ -9356,13 +9326,13 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
9356
9326
|
// - convey information (?hmr)
|
|
9357
9327
|
// But do not represent an other resource, it is considered as
|
|
9358
9328
|
// the same resource under the hood
|
|
9359
|
-
pluginController.callHooks("
|
|
9329
|
+
pluginController.callHooks("transformReferenceSearchParams", reference, referenceContext, returnValue => {
|
|
9360
9330
|
Object.keys(returnValue).forEach(key => {
|
|
9361
9331
|
searchParams.set(key, returnValue[key]);
|
|
9362
9332
|
});
|
|
9363
9333
|
reference.generatedUrl = normalizeUrl(referencedUrlObject.href);
|
|
9364
9334
|
});
|
|
9365
|
-
const returnValue = pluginController.callHooksUntil("
|
|
9335
|
+
const returnValue = pluginController.callHooksUntil("formatReference", reference, referenceContext);
|
|
9366
9336
|
reference.generatedSpecifier = returnValue || reference.generatedUrl;
|
|
9367
9337
|
reference.generatedSpecifier = urlSpecifierEncoding.encode(reference);
|
|
9368
9338
|
return [reference, urlInfo];
|
|
@@ -10259,7 +10229,7 @@ const createRepartitionMessage = ({
|
|
|
10259
10229
|
};
|
|
10260
10230
|
|
|
10261
10231
|
const jsenvPluginReferenceExpectedTypes = () => {
|
|
10262
|
-
const
|
|
10232
|
+
const redirectJsReference = reference => {
|
|
10263
10233
|
const urlObject = new URL(reference.url);
|
|
10264
10234
|
const {
|
|
10265
10235
|
searchParams
|
|
@@ -10269,16 +10239,23 @@ const jsenvPluginReferenceExpectedTypes = () => {
|
|
|
10269
10239
|
}
|
|
10270
10240
|
if (searchParams.has("js_classic")) {
|
|
10271
10241
|
reference.expectedType = "js_classic";
|
|
10272
|
-
} else if (searchParams.has("
|
|
10242
|
+
} else if (searchParams.has("js_module")) {
|
|
10243
|
+
reference.expectedType = "js_module";
|
|
10244
|
+
}
|
|
10245
|
+
// we need to keep these checks here because during versioning:
|
|
10246
|
+
// - only reference anlysis plugin is executed
|
|
10247
|
+
// -> plugin about js transpilation don't apply and can't set expectedType: 'js_classic'
|
|
10248
|
+
// - query params like ?js_module_fallback are still there
|
|
10249
|
+
// - without this check build would throw as reference could expect js module and find js classic
|
|
10250
|
+
else if (searchParams.has("js_module_fallback") || searchParams.has("as_js_classic")) {
|
|
10273
10251
|
reference.expectedType = "js_classic";
|
|
10274
10252
|
} else if (searchParams.has("as_js_module")) {
|
|
10275
10253
|
reference.expectedType = "js_module";
|
|
10276
|
-
}
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
// new URL('./file.js?js_classic', import.meta.url)
|
|
10254
|
+
}
|
|
10255
|
+
// by default, js referenced by new URL is considered as "js_module"
|
|
10256
|
+
// in case this is not desired code must use "?js_classic" like
|
|
10257
|
+
// new URL('./file.js?js_classic', import.meta.url)
|
|
10258
|
+
else if (reference.type === "js_url" && reference.expectedType === undefined && CONTENT_TYPE.fromUrlExtension(reference.url) === "text/javascript") {
|
|
10282
10259
|
reference.expectedType = "js_module";
|
|
10283
10260
|
}
|
|
10284
10261
|
if (searchParams.has("worker")) {
|
|
@@ -10293,40 +10270,175 @@ const jsenvPluginReferenceExpectedTypes = () => {
|
|
|
10293
10270
|
return {
|
|
10294
10271
|
name: "jsenv:reference_expected_types",
|
|
10295
10272
|
appliesDuring: "*",
|
|
10296
|
-
|
|
10297
|
-
script:
|
|
10298
|
-
js_url:
|
|
10299
|
-
js_import:
|
|
10273
|
+
redirectReference: {
|
|
10274
|
+
script: redirectJsReference,
|
|
10275
|
+
js_url: redirectJsReference,
|
|
10276
|
+
js_import: redirectJsReference
|
|
10277
|
+
}
|
|
10278
|
+
};
|
|
10279
|
+
};
|
|
10280
|
+
|
|
10281
|
+
const jsenvPluginDirectoryReferenceAnalysis = () => {
|
|
10282
|
+
return {
|
|
10283
|
+
name: "jsenv:directory_reference_analysis",
|
|
10284
|
+
transformUrlContent: {
|
|
10285
|
+
directory: (urlInfo, context) => {
|
|
10286
|
+
const originalDirectoryReference = findOriginalDirectoryReference(urlInfo, context);
|
|
10287
|
+
const directoryRelativeUrl = urlToRelativeUrl(urlInfo.url, context.rootDirectoryUrl);
|
|
10288
|
+
JSON.parse(urlInfo.content).forEach(directoryEntryName => {
|
|
10289
|
+
context.referenceUtils.found({
|
|
10290
|
+
type: "filesystem",
|
|
10291
|
+
subtype: "directory_entry",
|
|
10292
|
+
specifier: directoryEntryName,
|
|
10293
|
+
trace: {
|
|
10294
|
+
message: `"${directoryRelativeUrl}${directoryEntryName}" entry in directory referenced by ${originalDirectoryReference.trace.message}`
|
|
10295
|
+
}
|
|
10296
|
+
});
|
|
10297
|
+
});
|
|
10298
|
+
}
|
|
10299
|
+
}
|
|
10300
|
+
};
|
|
10301
|
+
};
|
|
10302
|
+
const findOriginalDirectoryReference = (urlInfo, context) => {
|
|
10303
|
+
const findNonFileSystemAncestor = urlInfo => {
|
|
10304
|
+
for (const dependentUrl of urlInfo.dependents) {
|
|
10305
|
+
const dependentUrlInfo = context.urlGraph.getUrlInfo(dependentUrl);
|
|
10306
|
+
if (dependentUrlInfo.type !== "directory") {
|
|
10307
|
+
return [dependentUrlInfo, urlInfo];
|
|
10308
|
+
}
|
|
10309
|
+
const found = findNonFileSystemAncestor(dependentUrlInfo);
|
|
10310
|
+
if (found) {
|
|
10311
|
+
return found;
|
|
10312
|
+
}
|
|
10313
|
+
}
|
|
10314
|
+
return [];
|
|
10315
|
+
};
|
|
10316
|
+
const [ancestor, child] = findNonFileSystemAncestor(urlInfo);
|
|
10317
|
+
if (!ancestor) {
|
|
10318
|
+
return null;
|
|
10319
|
+
}
|
|
10320
|
+
const ref = ancestor.references.find(ref => ref.url === child.url);
|
|
10321
|
+
return ref;
|
|
10322
|
+
};
|
|
10323
|
+
|
|
10324
|
+
const jsenvPluginDataUrlsAnalysis = () => {
|
|
10325
|
+
return {
|
|
10326
|
+
name: "jsenv:data_urls_analysis",
|
|
10327
|
+
appliesDuring: "*",
|
|
10328
|
+
resolveReference: reference => {
|
|
10329
|
+
if (!reference.specifier.startsWith("data:")) {
|
|
10330
|
+
return null;
|
|
10331
|
+
}
|
|
10332
|
+
return reference.specifier;
|
|
10333
|
+
},
|
|
10334
|
+
formatReference: (reference, context) => {
|
|
10335
|
+
if (!reference.generatedUrl.startsWith("data:")) {
|
|
10336
|
+
return null;
|
|
10337
|
+
}
|
|
10338
|
+
if (reference.type === "sourcemap_comment") {
|
|
10339
|
+
return null;
|
|
10340
|
+
}
|
|
10341
|
+
return (async () => {
|
|
10342
|
+
const urlInfo = context.urlGraph.getUrlInfo(reference.url);
|
|
10343
|
+
await context.cook(urlInfo, {
|
|
10344
|
+
reference
|
|
10345
|
+
});
|
|
10346
|
+
if (urlInfo.originalContent === urlInfo.content) {
|
|
10347
|
+
return reference.generatedUrl;
|
|
10348
|
+
}
|
|
10349
|
+
const specifier = DATA_URL.stringify({
|
|
10350
|
+
contentType: urlInfo.contentType,
|
|
10351
|
+
base64Flag: urlInfo.data.base64Flag,
|
|
10352
|
+
data: urlInfo.data.base64Flag ? dataToBase64(urlInfo.content) : String(urlInfo.content)
|
|
10353
|
+
});
|
|
10354
|
+
return specifier;
|
|
10355
|
+
})();
|
|
10356
|
+
},
|
|
10357
|
+
fetchUrlContent: urlInfo => {
|
|
10358
|
+
if (!urlInfo.url.startsWith("data:")) {
|
|
10359
|
+
return null;
|
|
10360
|
+
}
|
|
10361
|
+
const {
|
|
10362
|
+
contentType,
|
|
10363
|
+
base64Flag,
|
|
10364
|
+
data: urlData
|
|
10365
|
+
} = DATA_URL.parse(urlInfo.url);
|
|
10366
|
+
urlInfo.data.base64Flag = base64Flag;
|
|
10367
|
+
return {
|
|
10368
|
+
content: contentFromUrlData({
|
|
10369
|
+
contentType,
|
|
10370
|
+
base64Flag,
|
|
10371
|
+
urlData
|
|
10372
|
+
}),
|
|
10373
|
+
contentType
|
|
10374
|
+
};
|
|
10300
10375
|
}
|
|
10301
10376
|
};
|
|
10302
10377
|
};
|
|
10378
|
+
const contentFromUrlData = ({
|
|
10379
|
+
contentType,
|
|
10380
|
+
base64Flag,
|
|
10381
|
+
urlData
|
|
10382
|
+
}) => {
|
|
10383
|
+
if (CONTENT_TYPE.isTextual(contentType)) {
|
|
10384
|
+
if (base64Flag) {
|
|
10385
|
+
return base64ToString(urlData);
|
|
10386
|
+
}
|
|
10387
|
+
return urlData;
|
|
10388
|
+
}
|
|
10389
|
+
if (base64Flag) {
|
|
10390
|
+
return base64ToBuffer(urlData);
|
|
10391
|
+
}
|
|
10392
|
+
return Buffer.from(urlData);
|
|
10393
|
+
};
|
|
10394
|
+
const base64ToBuffer = base64String => Buffer.from(base64String, "base64");
|
|
10395
|
+
const base64ToString = base64String => Buffer.from(base64String, "base64").toString("utf8");
|
|
10396
|
+
const dataToBase64 = data => Buffer.from(data).toString("base64");
|
|
10303
10397
|
|
|
10304
|
-
const
|
|
10398
|
+
const jsenvPluginHtmlReferenceAnalysis = ({
|
|
10399
|
+
inlineContent,
|
|
10400
|
+
inlineConvertedScript
|
|
10401
|
+
}) => {
|
|
10402
|
+
return {
|
|
10403
|
+
name: "jsenv:html_reference_analysis",
|
|
10404
|
+
appliesDuring: "*",
|
|
10405
|
+
transformUrlContent: {
|
|
10406
|
+
html: (urlInfo, context) => parseAndTransformHtmlReferences(urlInfo, context, {
|
|
10407
|
+
inlineContent,
|
|
10408
|
+
inlineConvertedScript
|
|
10409
|
+
})
|
|
10410
|
+
}
|
|
10411
|
+
};
|
|
10412
|
+
};
|
|
10413
|
+
const parseAndTransformHtmlReferences = async (urlInfo, context, {
|
|
10414
|
+
inlineContent,
|
|
10415
|
+
inlineConvertedScript
|
|
10416
|
+
}) => {
|
|
10305
10417
|
const url = urlInfo.originalUrl;
|
|
10306
10418
|
const content = urlInfo.content;
|
|
10307
|
-
const htmlAst = parseHtmlString(content
|
|
10308
|
-
storeOriginalPositions: context.dev
|
|
10309
|
-
});
|
|
10310
|
-
const mentions = visitHtmlUrls({
|
|
10311
|
-
url,
|
|
10312
|
-
htmlAst
|
|
10313
|
-
});
|
|
10419
|
+
const htmlAst = parseHtmlString(content);
|
|
10314
10420
|
const mutations = [];
|
|
10315
10421
|
const actions = [];
|
|
10316
|
-
|
|
10422
|
+
const finalizeCallbacks = [];
|
|
10423
|
+
const createExternalReference = (node, attributeName, attributeValue, {
|
|
10424
|
+
type,
|
|
10425
|
+
subtype,
|
|
10426
|
+
expectedType
|
|
10427
|
+
}) => {
|
|
10428
|
+
let position;
|
|
10429
|
+
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
10430
|
+
// when generated from inline content,
|
|
10431
|
+
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
10432
|
+
position = getHtmlNodePosition(node);
|
|
10433
|
+
} else {
|
|
10434
|
+
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
10435
|
+
}
|
|
10317
10436
|
const {
|
|
10318
|
-
type,
|
|
10319
|
-
subtype,
|
|
10320
|
-
expectedType,
|
|
10321
10437
|
line,
|
|
10322
|
-
column
|
|
10323
|
-
originalLine,
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
attributeName,
|
|
10327
|
-
debug,
|
|
10328
|
-
specifier
|
|
10329
|
-
} = mention;
|
|
10438
|
+
column
|
|
10439
|
+
// originalLine, originalColumn
|
|
10440
|
+
} = position;
|
|
10441
|
+
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
10330
10442
|
const {
|
|
10331
10443
|
crossorigin,
|
|
10332
10444
|
integrity
|
|
@@ -10336,9 +10448,7 @@ const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
|
10336
10448
|
type,
|
|
10337
10449
|
subtype,
|
|
10338
10450
|
expectedType,
|
|
10339
|
-
|
|
10340
|
-
originalColumn,
|
|
10341
|
-
specifier,
|
|
10451
|
+
specifier: attributeValue,
|
|
10342
10452
|
specifierLine: line,
|
|
10343
10453
|
specifierColumn: column,
|
|
10344
10454
|
isResourceHint,
|
|
@@ -10354,221 +10464,283 @@ const parseAndTransformHtmlUrls = async (urlInfo, context) => {
|
|
|
10354
10464
|
});
|
|
10355
10465
|
});
|
|
10356
10466
|
});
|
|
10357
|
-
}
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10467
|
+
};
|
|
10468
|
+
const visitHref = (node, referenceProps) => {
|
|
10469
|
+
const href = getHtmlNodeAttribute(node, "href");
|
|
10470
|
+
if (href) {
|
|
10471
|
+
return createExternalReference(node, "href", href, referenceProps);
|
|
10472
|
+
}
|
|
10473
|
+
const inlinedFromHref = getHtmlNodeAttribute(node, "inlined-from-href");
|
|
10474
|
+
if (inlinedFromHref) {
|
|
10475
|
+
return createExternalReference(node, "inlined-from-href", new URL(inlinedFromHref, url).href, referenceProps);
|
|
10476
|
+
}
|
|
10362
10477
|
return null;
|
|
10363
|
-
}
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
const
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
|
|
10373
|
-
|
|
10374
|
-
}
|
|
10375
|
-
|
|
10376
|
-
const
|
|
10377
|
-
|
|
10378
|
-
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10384
|
-
}
|
|
10385
|
-
const
|
|
10386
|
-
|
|
10387
|
-
const addMention = ({
|
|
10478
|
+
};
|
|
10479
|
+
const visitSrc = (node, referenceProps) => {
|
|
10480
|
+
const src = getHtmlNodeAttribute(node, "src");
|
|
10481
|
+
if (src) {
|
|
10482
|
+
return createExternalReference(node, "src", src, referenceProps);
|
|
10483
|
+
}
|
|
10484
|
+
const inlinedFromSrc = getHtmlNodeAttribute(node, "inlined-from-src");
|
|
10485
|
+
if (inlinedFromSrc) {
|
|
10486
|
+
return createExternalReference(node, "inlined-from-src", new URL(inlinedFromSrc, url).href, referenceProps);
|
|
10487
|
+
}
|
|
10488
|
+
return null;
|
|
10489
|
+
};
|
|
10490
|
+
const visitSrcset = (node, referenceProps) => {
|
|
10491
|
+
const srcset = getHtmlNodeAttribute(node, "srcset");
|
|
10492
|
+
if (srcset) {
|
|
10493
|
+
const srcCandidates = parseSrcSet(srcset);
|
|
10494
|
+
return srcCandidates.map(srcCandidate => {
|
|
10495
|
+
return createExternalReference(node, "srcset", srcCandidate.specifier, referenceProps);
|
|
10496
|
+
});
|
|
10497
|
+
}
|
|
10498
|
+
return null;
|
|
10499
|
+
};
|
|
10500
|
+
const createInlineReference = (node, inlineContent, {
|
|
10501
|
+
extension,
|
|
10388
10502
|
type,
|
|
10389
|
-
subtype,
|
|
10390
10503
|
expectedType,
|
|
10391
|
-
|
|
10392
|
-
attributeName,
|
|
10393
|
-
specifier
|
|
10504
|
+
contentType
|
|
10394
10505
|
}) => {
|
|
10395
|
-
|
|
10396
|
-
if (getHtmlNodeAttribute(node, "jsenv-cooked-by")) {
|
|
10397
|
-
// when generated from inline content,
|
|
10398
|
-
// line, column is not "src" nor "inlined-from-src" but "original-position"
|
|
10399
|
-
position = getHtmlNodePosition(node);
|
|
10400
|
-
} else {
|
|
10401
|
-
position = getHtmlNodeAttributePosition(node, attributeName);
|
|
10402
|
-
}
|
|
10506
|
+
const hotAccept = getHtmlNodeAttribute(node, "hot-accept") !== undefined;
|
|
10403
10507
|
const {
|
|
10404
10508
|
line,
|
|
10405
|
-
column
|
|
10406
|
-
|
|
10407
|
-
|
|
10408
|
-
|
|
10409
|
-
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10509
|
+
column,
|
|
10510
|
+
lineEnd,
|
|
10511
|
+
columnEnd,
|
|
10512
|
+
isOriginal
|
|
10513
|
+
} = getHtmlNodePosition(node, {
|
|
10514
|
+
preferOriginal: true
|
|
10515
|
+
});
|
|
10516
|
+
const inlineContentUrl = generateInlineContentUrl({
|
|
10517
|
+
url: urlInfo.url,
|
|
10518
|
+
extension,
|
|
10413
10519
|
line,
|
|
10414
10520
|
column,
|
|
10415
|
-
|
|
10416
|
-
|
|
10521
|
+
lineEnd,
|
|
10522
|
+
columnEnd
|
|
10523
|
+
});
|
|
10524
|
+
const debug = getHtmlNodeAttribute(node, "jsenv-debug") !== undefined;
|
|
10525
|
+
const [inlineReference, inlineUrlInfo] = context.referenceUtils.foundInline({
|
|
10417
10526
|
node,
|
|
10418
|
-
|
|
10527
|
+
type,
|
|
10528
|
+
expectedType,
|
|
10529
|
+
isOriginalPosition: isOriginal,
|
|
10530
|
+
// we remove 1 to the line because imagine the following html:
|
|
10531
|
+
// <style>body { color: red; }</style>
|
|
10532
|
+
// -> content starts same line as <style> (same for <script>)
|
|
10533
|
+
specifierLine: line - 1,
|
|
10534
|
+
specifierColumn: column,
|
|
10535
|
+
specifier: inlineContentUrl,
|
|
10536
|
+
contentType,
|
|
10537
|
+
content: inlineContent,
|
|
10419
10538
|
debug
|
|
10420
|
-
};
|
|
10421
|
-
|
|
10422
|
-
|
|
10423
|
-
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
attributeName,
|
|
10427
|
-
...rest
|
|
10428
|
-
}) => {
|
|
10429
|
-
const value = getHtmlNodeAttribute(node, attributeName);
|
|
10430
|
-
if (value) {
|
|
10431
|
-
if (getHtmlNodeAttribute(node, "jsenv-inlined-by") === "jsenv:importmap") {
|
|
10432
|
-
// during build the importmap is inlined
|
|
10433
|
-
// and shoud not be considered as a dependency anymore
|
|
10434
|
-
return null;
|
|
10435
|
-
}
|
|
10436
|
-
return addMention({
|
|
10437
|
-
...rest,
|
|
10438
|
-
node,
|
|
10439
|
-
attributeName,
|
|
10440
|
-
specifier: attributeName === "inlined-from-src" || attributeName === "inlined-from-href" ? new URL(value, url).href : value
|
|
10441
|
-
});
|
|
10442
|
-
}
|
|
10443
|
-
if (attributeName === "src") {
|
|
10444
|
-
return visitAttributeAsUrlSpecifier({
|
|
10445
|
-
...rest,
|
|
10446
|
-
node,
|
|
10447
|
-
attributeName: "inlined-from-src"
|
|
10539
|
+
});
|
|
10540
|
+
actions.push(async () => {
|
|
10541
|
+
await cookInlineContent({
|
|
10542
|
+
context,
|
|
10543
|
+
inlineContentUrlInfo: inlineUrlInfo,
|
|
10544
|
+
inlineContentReference: inlineReference
|
|
10448
10545
|
});
|
|
10449
|
-
|
|
10450
|
-
|
|
10451
|
-
|
|
10452
|
-
|
|
10453
|
-
|
|
10454
|
-
|
|
10546
|
+
mutations.push(() => {
|
|
10547
|
+
if (hotAccept) {
|
|
10548
|
+
removeHtmlNodeText(node);
|
|
10549
|
+
setHtmlNodeAttributes(node, {
|
|
10550
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis"
|
|
10551
|
+
});
|
|
10552
|
+
} else {
|
|
10553
|
+
setHtmlNodeText(node, inlineUrlInfo.content, {
|
|
10554
|
+
indentation: false // indentation would decrease stack trace precision
|
|
10555
|
+
});
|
|
10556
|
+
|
|
10557
|
+
setHtmlNodeAttributes(node, {
|
|
10558
|
+
"jsenv-cooked-by": "jsenv:html_inline_content_analysis"
|
|
10559
|
+
});
|
|
10560
|
+
}
|
|
10455
10561
|
});
|
|
10456
|
-
}
|
|
10457
|
-
return
|
|
10562
|
+
});
|
|
10563
|
+
return inlineReference;
|
|
10458
10564
|
};
|
|
10459
|
-
const
|
|
10565
|
+
const visitTextContent = (node, {
|
|
10566
|
+
extension,
|
|
10460
10567
|
type,
|
|
10461
|
-
|
|
10568
|
+
expectedType,
|
|
10569
|
+
contentType
|
|
10462
10570
|
}) => {
|
|
10463
|
-
const
|
|
10464
|
-
if (
|
|
10465
|
-
|
|
10466
|
-
srcCandidates.forEach(srcCandidate => {
|
|
10467
|
-
addMention({
|
|
10468
|
-
type,
|
|
10469
|
-
node,
|
|
10470
|
-
attributeName: "srcset",
|
|
10471
|
-
specifier: srcCandidate.specifier
|
|
10472
|
-
});
|
|
10473
|
-
});
|
|
10571
|
+
const inlineContent = getHtmlNodeText(node);
|
|
10572
|
+
if (!inlineContent) {
|
|
10573
|
+
return null;
|
|
10474
10574
|
}
|
|
10575
|
+
return createInlineReference(node, inlineContent, {
|
|
10576
|
+
extension,
|
|
10577
|
+
type,
|
|
10578
|
+
expectedType,
|
|
10579
|
+
contentType
|
|
10580
|
+
});
|
|
10475
10581
|
};
|
|
10476
10582
|
visitHtmlNodes(htmlAst, {
|
|
10477
|
-
link:
|
|
10478
|
-
const rel = getHtmlNodeAttribute(
|
|
10479
|
-
const type = getHtmlNodeAttribute(
|
|
10480
|
-
const
|
|
10583
|
+
link: linkNode => {
|
|
10584
|
+
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
10585
|
+
const type = getHtmlNodeAttribute(linkNode, "type");
|
|
10586
|
+
const ref = visitHref(linkNode, {
|
|
10481
10587
|
type: "link_href",
|
|
10482
10588
|
subtype: rel,
|
|
10483
|
-
node,
|
|
10484
|
-
attributeName: "href",
|
|
10485
10589
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#including_a_mime_type
|
|
10486
10590
|
expectedContentType: type
|
|
10487
10591
|
});
|
|
10488
|
-
if (
|
|
10592
|
+
if (ref) {
|
|
10489
10593
|
finalizeCallbacks.push(() => {
|
|
10490
|
-
|
|
10594
|
+
ref.expectedType = decideLinkExpectedType(ref, context);
|
|
10491
10595
|
});
|
|
10492
10596
|
}
|
|
10493
10597
|
},
|
|
10494
|
-
|
|
10495
|
-
|
|
10598
|
+
style: inlineContent ? styleNode => {
|
|
10599
|
+
visitTextContent(styleNode, {
|
|
10600
|
+
extension: ".css",
|
|
10601
|
+
type: "style",
|
|
10602
|
+
expectedType: "css",
|
|
10603
|
+
contentType: "text/css"
|
|
10604
|
+
});
|
|
10605
|
+
} : null,
|
|
10606
|
+
script: scriptNode => {
|
|
10607
|
+
// during build the importmap is inlined
|
|
10608
|
+
// and shoud not be considered as a dependency anymore
|
|
10609
|
+
if (getHtmlNodeAttribute(scriptNode, "jsenv-inlined-by") === "jsenv:importmap") {
|
|
10610
|
+
return;
|
|
10611
|
+
}
|
|
10496
10612
|
const {
|
|
10497
|
-
type
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
|
|
10502
|
-
|
|
10613
|
+
type,
|
|
10614
|
+
contentType,
|
|
10615
|
+
extension
|
|
10616
|
+
} = analyzeScriptNode(scriptNode);
|
|
10617
|
+
// ignore <script type="whatever">foobar</script>
|
|
10618
|
+
// per HTML spec https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
|
|
10619
|
+
if (type !== "text") {
|
|
10620
|
+
const externalRef = visitSrc(scriptNode, {
|
|
10621
|
+
type: "script",
|
|
10622
|
+
subtype: type,
|
|
10623
|
+
expectedType: type
|
|
10624
|
+
});
|
|
10625
|
+
if (externalRef) {
|
|
10626
|
+
return;
|
|
10627
|
+
}
|
|
10628
|
+
}
|
|
10629
|
+
|
|
10630
|
+
// now visit the content, if any
|
|
10631
|
+
if (!inlineContent) {
|
|
10503
10632
|
return;
|
|
10504
10633
|
}
|
|
10505
|
-
|
|
10634
|
+
// If the inline script was already handled by an other plugin, ignore it
|
|
10635
|
+
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
10636
|
+
// - we want to avoid cooking twice a script during build
|
|
10637
|
+
if (!inlineConvertedScript && getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") === "jsenv:js_module_fallback") {
|
|
10638
|
+
return;
|
|
10639
|
+
}
|
|
10640
|
+
const inlineRef = visitTextContent(scriptNode, {
|
|
10641
|
+
extension: extension || CONTENT_TYPE.asFileExtension(contentType),
|
|
10506
10642
|
type: "script",
|
|
10507
|
-
subtype: type,
|
|
10508
10643
|
expectedType: type,
|
|
10509
|
-
|
|
10510
|
-
attributeName: "src"
|
|
10644
|
+
contentType
|
|
10511
10645
|
});
|
|
10646
|
+
if (inlineRef && extension) {
|
|
10647
|
+
// 1. <script type="jsx"> becomes <script>
|
|
10648
|
+
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
10649
|
+
mutations.push(() => {
|
|
10650
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
10651
|
+
type: type === "js_module" ? "module" : undefined
|
|
10652
|
+
});
|
|
10653
|
+
});
|
|
10654
|
+
}
|
|
10512
10655
|
},
|
|
10513
|
-
a:
|
|
10514
|
-
|
|
10515
|
-
type: "a_href"
|
|
10516
|
-
node,
|
|
10517
|
-
attributeName: "href"
|
|
10656
|
+
a: aNode => {
|
|
10657
|
+
visitHref(aNode, {
|
|
10658
|
+
type: "a_href"
|
|
10518
10659
|
});
|
|
10519
10660
|
},
|
|
10520
|
-
iframe:
|
|
10521
|
-
|
|
10522
|
-
type: "iframe_src"
|
|
10523
|
-
node,
|
|
10524
|
-
attributeName: "src"
|
|
10661
|
+
iframe: iframeNode => {
|
|
10662
|
+
visitSrc(iframeNode, {
|
|
10663
|
+
type: "iframe_src"
|
|
10525
10664
|
});
|
|
10526
10665
|
},
|
|
10527
|
-
img:
|
|
10528
|
-
|
|
10529
|
-
type: "img_src"
|
|
10530
|
-
node,
|
|
10531
|
-
attributeName: "src"
|
|
10666
|
+
img: imgNode => {
|
|
10667
|
+
visitSrc(imgNode, {
|
|
10668
|
+
type: "img_src"
|
|
10532
10669
|
});
|
|
10533
|
-
visitSrcset({
|
|
10534
|
-
type: "img_srcset"
|
|
10535
|
-
node
|
|
10670
|
+
visitSrcset(imgNode, {
|
|
10671
|
+
type: "img_srcset"
|
|
10536
10672
|
});
|
|
10537
10673
|
},
|
|
10538
|
-
source:
|
|
10539
|
-
|
|
10540
|
-
type: "source_src"
|
|
10541
|
-
node,
|
|
10542
|
-
attributeName: "src"
|
|
10674
|
+
source: sourceNode => {
|
|
10675
|
+
visitSrc(sourceNode, {
|
|
10676
|
+
type: "source_src"
|
|
10543
10677
|
});
|
|
10544
|
-
visitSrcset({
|
|
10545
|
-
type: "source_srcset"
|
|
10546
|
-
node
|
|
10678
|
+
visitSrcset(sourceNode, {
|
|
10679
|
+
type: "source_srcset"
|
|
10547
10680
|
});
|
|
10548
10681
|
},
|
|
10549
10682
|
// svg <image> tag
|
|
10550
|
-
image:
|
|
10551
|
-
|
|
10552
|
-
type: "image_href"
|
|
10553
|
-
node,
|
|
10554
|
-
attributeName: "href"
|
|
10683
|
+
image: imageNode => {
|
|
10684
|
+
visitHref(imageNode, {
|
|
10685
|
+
type: "image_href"
|
|
10555
10686
|
});
|
|
10556
10687
|
},
|
|
10557
|
-
use:
|
|
10558
|
-
|
|
10559
|
-
type: "use_href"
|
|
10560
|
-
node,
|
|
10561
|
-
attributeName: "href"
|
|
10688
|
+
use: useNode => {
|
|
10689
|
+
visitHref(useNode, {
|
|
10690
|
+
type: "use_href"
|
|
10562
10691
|
});
|
|
10563
10692
|
}
|
|
10564
10693
|
});
|
|
10565
10694
|
finalizeCallbacks.forEach(finalizeCallback => {
|
|
10566
10695
|
finalizeCallback();
|
|
10567
10696
|
});
|
|
10568
|
-
|
|
10697
|
+
if (actions.length > 0) {
|
|
10698
|
+
await Promise.all(actions.map(action => action()));
|
|
10699
|
+
}
|
|
10700
|
+
if (mutations.length === 0) {
|
|
10701
|
+
return null;
|
|
10702
|
+
}
|
|
10703
|
+
mutations.forEach(mutation => mutation());
|
|
10704
|
+
return stringifyHtmlAst(htmlAst);
|
|
10705
|
+
};
|
|
10706
|
+
const cookInlineContent = async ({
|
|
10707
|
+
context,
|
|
10708
|
+
inlineContentUrlInfo,
|
|
10709
|
+
inlineContentReference
|
|
10710
|
+
}) => {
|
|
10711
|
+
try {
|
|
10712
|
+
await context.cook(inlineContentUrlInfo, {
|
|
10713
|
+
reference: inlineContentReference
|
|
10714
|
+
});
|
|
10715
|
+
} catch (e) {
|
|
10716
|
+
if (e.code === "PARSE_ERROR") {
|
|
10717
|
+
// When something like <style> or <script> contains syntax error
|
|
10718
|
+
// the HTML in itself it still valid
|
|
10719
|
+
// keep the syntax error and continue with the HTML
|
|
10720
|
+
const messageStart = inlineContentUrlInfo.type === "css" ? `Syntax error on css declared inside <style>` : `Syntax error on js declared inside <script>`;
|
|
10721
|
+
context.logger.error(`${messageStart}: ${e.cause.reasonCode}
|
|
10722
|
+
${e.traceMessage}`);
|
|
10723
|
+
} else {
|
|
10724
|
+
throw e;
|
|
10725
|
+
}
|
|
10726
|
+
}
|
|
10727
|
+
};
|
|
10728
|
+
const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
|
|
10729
|
+
const integrityCompatibleTagNames = ["script", "link", "img", "source"];
|
|
10730
|
+
const readFetchMetas = node => {
|
|
10731
|
+
const meta = {};
|
|
10732
|
+
if (crossOriginCompatibleTagNames.includes(node.nodeName)) {
|
|
10733
|
+
const crossorigin = getHtmlNodeAttribute(node, "crossorigin") !== undefined;
|
|
10734
|
+
meta.crossorigin = crossorigin;
|
|
10735
|
+
}
|
|
10736
|
+
if (integrityCompatibleTagNames.includes(node.nodeName)) {
|
|
10737
|
+
const integrity = getHtmlNodeAttribute(node, "integrity");
|
|
10738
|
+
meta.integrity = integrity;
|
|
10739
|
+
}
|
|
10740
|
+
return meta;
|
|
10569
10741
|
};
|
|
10570
|
-
const decideLinkExpectedType = (
|
|
10571
|
-
const rel = getHtmlNodeAttribute(
|
|
10742
|
+
const decideLinkExpectedType = (linkReference, context) => {
|
|
10743
|
+
const rel = getHtmlNodeAttribute(linkReference.node, "rel");
|
|
10572
10744
|
if (rel === "webmanifest") {
|
|
10573
10745
|
return "webmanifest";
|
|
10574
10746
|
}
|
|
@@ -10580,7 +10752,7 @@ const decideLinkExpectedType = (linkMention, mentions) => {
|
|
|
10580
10752
|
}
|
|
10581
10753
|
if (rel === "preload") {
|
|
10582
10754
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload#what_types_of_content_can_be_preloaded
|
|
10583
|
-
const as = getHtmlNodeAttribute(
|
|
10755
|
+
const as = getHtmlNodeAttribute(linkReference.node, "as");
|
|
10584
10756
|
if (as === "document") {
|
|
10585
10757
|
return "html";
|
|
10586
10758
|
}
|
|
@@ -10588,7 +10760,7 @@ const decideLinkExpectedType = (linkMention, mentions) => {
|
|
|
10588
10760
|
return "css";
|
|
10589
10761
|
}
|
|
10590
10762
|
if (as === "script") {
|
|
10591
|
-
const firstScriptOnThisUrl =
|
|
10763
|
+
const firstScriptOnThisUrl = context.referenceUtils.find(refCandidate => refCandidate.url === linkReference.url && refCandidate.type === "script");
|
|
10592
10764
|
if (firstScriptOnThisUrl) {
|
|
10593
10765
|
return firstScriptOnThisUrl.expectedType;
|
|
10594
10766
|
}
|
|
@@ -10598,9 +10770,53 @@ const decideLinkExpectedType = (linkMention, mentions) => {
|
|
|
10598
10770
|
return undefined;
|
|
10599
10771
|
};
|
|
10600
10772
|
|
|
10773
|
+
// css: parseAndTransformCssUrls,
|
|
10774
|
+
|
|
10775
|
+
const jsenvPluginWebmanifestReferenceAnalysis = () => {
|
|
10776
|
+
return {
|
|
10777
|
+
name: "jsenv:webmanifest_reference_analysis",
|
|
10778
|
+
appliesDuring: "*",
|
|
10779
|
+
transformUrlContent: {
|
|
10780
|
+
webmanifest: parseAndTransformWebmanifestUrls
|
|
10781
|
+
}
|
|
10782
|
+
};
|
|
10783
|
+
};
|
|
10784
|
+
const parseAndTransformWebmanifestUrls = async (urlInfo, context) => {
|
|
10785
|
+
const content = urlInfo.content;
|
|
10786
|
+
const manifest = JSON.parse(content);
|
|
10787
|
+
const actions = [];
|
|
10788
|
+
const {
|
|
10789
|
+
icons = []
|
|
10790
|
+
} = manifest;
|
|
10791
|
+
icons.forEach(icon => {
|
|
10792
|
+
const [reference] = context.referenceUtils.found({
|
|
10793
|
+
type: "webmanifest_icon_src",
|
|
10794
|
+
specifier: icon.src
|
|
10795
|
+
});
|
|
10796
|
+
actions.push(async () => {
|
|
10797
|
+
icon.src = await context.referenceUtils.readGeneratedSpecifier(reference);
|
|
10798
|
+
});
|
|
10799
|
+
});
|
|
10800
|
+
if (actions.length === 0) {
|
|
10801
|
+
return null;
|
|
10802
|
+
}
|
|
10803
|
+
await Promise.all(actions.map(action => action()));
|
|
10804
|
+
return JSON.stringify(manifest, null, " ");
|
|
10805
|
+
};
|
|
10806
|
+
|
|
10601
10807
|
/*
|
|
10602
10808
|
* https://github.com/parcel-bundler/parcel/blob/v2/packages/transformers/css/src/CSSTransformer.js
|
|
10603
10809
|
*/
|
|
10810
|
+
|
|
10811
|
+
const jsenvPluginCssReferenceAnalysis = () => {
|
|
10812
|
+
return {
|
|
10813
|
+
name: "jsenv:css_reference_analysis",
|
|
10814
|
+
appliesDuring: "*",
|
|
10815
|
+
transformUrlContent: {
|
|
10816
|
+
css: parseAndTransformCssUrls
|
|
10817
|
+
}
|
|
10818
|
+
};
|
|
10819
|
+
};
|
|
10604
10820
|
const parseAndTransformCssUrls = async (urlInfo, context) => {
|
|
10605
10821
|
const cssUrls = await parseCssUrls({
|
|
10606
10822
|
css: urlInfo.content,
|
|
@@ -10632,121 +10848,315 @@ const parseAndTransformCssUrls = async (urlInfo, context) => {
|
|
|
10632
10848
|
return magicSource.toContentAndSourcemap();
|
|
10633
10849
|
};
|
|
10634
10850
|
|
|
10635
|
-
const
|
|
10636
|
-
|
|
10637
|
-
|
|
10638
|
-
|
|
10639
|
-
|
|
10640
|
-
|
|
10641
|
-
});
|
|
10642
|
-
const actions = [];
|
|
10643
|
-
const magicSource = createMagicSource(urlInfo.content);
|
|
10644
|
-
for (const jsMention of jsMentions) {
|
|
10645
|
-
if (jsMention.subtype === "import_static" || jsMention.subtype === "import_dynamic") {
|
|
10646
|
-
urlInfo.data.usesImport = true;
|
|
10851
|
+
const isEscaped = (i, string) => {
|
|
10852
|
+
let backslashBeforeCount = 0;
|
|
10853
|
+
while (i--) {
|
|
10854
|
+
const previousChar = string[i];
|
|
10855
|
+
if (previousChar === "\\") {
|
|
10856
|
+
backslashBeforeCount++;
|
|
10647
10857
|
}
|
|
10648
|
-
|
|
10649
|
-
node: jsMention.node,
|
|
10650
|
-
type: jsMention.type,
|
|
10651
|
-
subtype: jsMention.subtype,
|
|
10652
|
-
expectedType: jsMention.expectedType,
|
|
10653
|
-
expectedSubtype: jsMention.expectedSubtype || urlInfo.subtype,
|
|
10654
|
-
specifier: jsMention.specifier,
|
|
10655
|
-
specifierStart: jsMention.start,
|
|
10656
|
-
specifierEnd: jsMention.end,
|
|
10657
|
-
specifierLine: jsMention.line,
|
|
10658
|
-
specifierColumn: jsMention.column,
|
|
10659
|
-
data: jsMention.data,
|
|
10660
|
-
baseUrl: {
|
|
10661
|
-
"StringLiteral": jsMention.baseUrl,
|
|
10662
|
-
"window.location": urlInfo.url,
|
|
10663
|
-
"window.origin": context.rootDirectoryUrl,
|
|
10664
|
-
"import.meta.url": urlInfo.url,
|
|
10665
|
-
"context.meta.url": urlInfo.url,
|
|
10666
|
-
"document.currentScript.src": urlInfo.url
|
|
10667
|
-
}[jsMention.baseUrlType],
|
|
10668
|
-
assert: jsMention.assert,
|
|
10669
|
-
assertNode: jsMention.assertNode,
|
|
10670
|
-
typePropertyNode: jsMention.typePropertyNode
|
|
10671
|
-
});
|
|
10672
|
-
actions.push(async () => {
|
|
10673
|
-
const replacement = await context.referenceUtils.readGeneratedSpecifier(reference);
|
|
10674
|
-
magicSource.replace({
|
|
10675
|
-
start: jsMention.start,
|
|
10676
|
-
end: jsMention.end,
|
|
10677
|
-
replacement
|
|
10678
|
-
});
|
|
10679
|
-
if (reference.mutation) {
|
|
10680
|
-
reference.mutation(magicSource);
|
|
10681
|
-
}
|
|
10682
|
-
});
|
|
10683
|
-
}
|
|
10684
|
-
if (actions.length > 0) {
|
|
10685
|
-
await Promise.all(actions.map(action => action()));
|
|
10686
|
-
}
|
|
10687
|
-
const {
|
|
10688
|
-
content,
|
|
10689
|
-
sourcemap
|
|
10690
|
-
} = magicSource.toContentAndSourcemap();
|
|
10691
|
-
return {
|
|
10692
|
-
content,
|
|
10693
|
-
sourcemap
|
|
10694
|
-
};
|
|
10695
|
-
};
|
|
10696
|
-
|
|
10697
|
-
const parseAndTransformWebmanifestUrls = async (urlInfo, context) => {
|
|
10698
|
-
const content = urlInfo.content;
|
|
10699
|
-
const manifest = JSON.parse(content);
|
|
10700
|
-
const actions = [];
|
|
10701
|
-
const {
|
|
10702
|
-
icons = []
|
|
10703
|
-
} = manifest;
|
|
10704
|
-
icons.forEach(icon => {
|
|
10705
|
-
const [reference] = context.referenceUtils.found({
|
|
10706
|
-
type: "webmanifest_icon_src",
|
|
10707
|
-
specifier: icon.src
|
|
10708
|
-
});
|
|
10709
|
-
actions.push(async () => {
|
|
10710
|
-
icon.src = await context.referenceUtils.readGeneratedSpecifier(reference);
|
|
10711
|
-
});
|
|
10712
|
-
});
|
|
10713
|
-
if (actions.length === 0) {
|
|
10714
|
-
return null;
|
|
10858
|
+
break;
|
|
10715
10859
|
}
|
|
10716
|
-
|
|
10717
|
-
return
|
|
10860
|
+
const isEven = backslashBeforeCount % 2 === 0;
|
|
10861
|
+
return !isEven;
|
|
10718
10862
|
};
|
|
10719
10863
|
|
|
10720
|
-
const
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
}) => {
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10864
|
+
const JS_QUOTES = {
|
|
10865
|
+
pickBest: (string, {
|
|
10866
|
+
canUseTemplateString,
|
|
10867
|
+
defaultQuote = DOUBLE
|
|
10868
|
+
} = {}) => {
|
|
10869
|
+
// check default first, once tested do no re-test it
|
|
10870
|
+
if (!string.includes(defaultQuote)) {
|
|
10871
|
+
return defaultQuote;
|
|
10872
|
+
}
|
|
10873
|
+
if (defaultQuote !== DOUBLE && !string.includes(DOUBLE)) {
|
|
10874
|
+
return DOUBLE;
|
|
10875
|
+
}
|
|
10876
|
+
if (defaultQuote !== SINGLE && !string.includes(SINGLE)) {
|
|
10877
|
+
return SINGLE;
|
|
10878
|
+
}
|
|
10879
|
+
if (canUseTemplateString && defaultQuote !== BACKTICK && !string.includes(BACKTICK)) {
|
|
10880
|
+
return BACKTICK;
|
|
10881
|
+
}
|
|
10882
|
+
return defaultQuote;
|
|
10883
|
+
},
|
|
10884
|
+
escapeSpecialChars: (string, {
|
|
10885
|
+
quote = "pickBest",
|
|
10886
|
+
canUseTemplateString,
|
|
10887
|
+
defaultQuote,
|
|
10888
|
+
allowEscapeForVersioning = false
|
|
10889
|
+
}) => {
|
|
10890
|
+
quote = quote === "pickBest" ? JS_QUOTES.pickBest(string, {
|
|
10891
|
+
canUseTemplateString,
|
|
10892
|
+
defaultQuote
|
|
10893
|
+
}) : quote;
|
|
10894
|
+
const replacements = JS_QUOTE_REPLACEMENTS[quote];
|
|
10895
|
+
let result = "";
|
|
10896
|
+
let last = 0;
|
|
10897
|
+
let i = 0;
|
|
10898
|
+
while (i < string.length) {
|
|
10899
|
+
const char = string[i];
|
|
10900
|
+
i++;
|
|
10901
|
+
if (isEscaped(i - 1, string)) continue;
|
|
10902
|
+
const replacement = replacements[char];
|
|
10903
|
+
if (replacement) {
|
|
10904
|
+
if (allowEscapeForVersioning && char === quote && string.slice(i, i + 6) === "+__v__") {
|
|
10905
|
+
let isVersioningConcatenation = false;
|
|
10906
|
+
let j = i + 6; // start after the +
|
|
10907
|
+
while (j < string.length) {
|
|
10908
|
+
const lookAheadChar = string[j];
|
|
10909
|
+
j++;
|
|
10910
|
+
if (lookAheadChar === "+" && string[j] === quote && !isEscaped(j - 1, string)) {
|
|
10911
|
+
isVersioningConcatenation = true;
|
|
10912
|
+
break;
|
|
10913
|
+
}
|
|
10914
|
+
}
|
|
10915
|
+
if (isVersioningConcatenation) {
|
|
10916
|
+
// it's a concatenation
|
|
10917
|
+
// skip until the end of concatenation (the second +)
|
|
10918
|
+
// and resume from there
|
|
10919
|
+
i = j + 1;
|
|
10920
|
+
continue;
|
|
10921
|
+
}
|
|
10922
|
+
}
|
|
10923
|
+
if (last === i - 1) {
|
|
10924
|
+
result += replacement;
|
|
10925
|
+
} else {
|
|
10926
|
+
result += `${string.slice(last, i - 1)}${replacement}`;
|
|
10927
|
+
}
|
|
10928
|
+
last = i;
|
|
10929
|
+
}
|
|
10930
|
+
}
|
|
10931
|
+
if (last !== string.length) {
|
|
10932
|
+
result += string.slice(last);
|
|
10933
|
+
}
|
|
10934
|
+
return `${quote}${result}${quote}`;
|
|
10935
|
+
}
|
|
10936
|
+
};
|
|
10937
|
+
const DOUBLE = `"`;
|
|
10938
|
+
const SINGLE = `'`;
|
|
10939
|
+
const BACKTICK = "`";
|
|
10940
|
+
const lineEndingEscapes = {
|
|
10941
|
+
"\n": "\\n",
|
|
10942
|
+
"\r": "\\r",
|
|
10943
|
+
"\u2028": "\\u2028",
|
|
10944
|
+
"\u2029": "\\u2029"
|
|
10945
|
+
};
|
|
10946
|
+
const JS_QUOTE_REPLACEMENTS = {
|
|
10947
|
+
[DOUBLE]: {
|
|
10948
|
+
'"': '\\"',
|
|
10949
|
+
...lineEndingEscapes
|
|
10950
|
+
},
|
|
10951
|
+
[SINGLE]: {
|
|
10952
|
+
"'": "\\'",
|
|
10953
|
+
...lineEndingEscapes
|
|
10954
|
+
},
|
|
10955
|
+
[BACKTICK]: {
|
|
10956
|
+
"`": "\\`",
|
|
10957
|
+
"$": "\\$"
|
|
10958
|
+
}
|
|
10959
|
+
};
|
|
10960
|
+
|
|
10961
|
+
const jsenvPluginJsReferenceAnalysis = ({
|
|
10962
|
+
inlineContent,
|
|
10963
|
+
allowEscapeForVersioning
|
|
10964
|
+
}) => {
|
|
10965
|
+
return [{
|
|
10966
|
+
name: "jsenv:js_reference_analysis",
|
|
10967
|
+
appliesDuring: "*",
|
|
10968
|
+
transformUrlContent: {
|
|
10969
|
+
js_classic: (urlInfo, context) => parseAndTransformJsReferences(urlInfo, context, {
|
|
10970
|
+
inlineContent,
|
|
10971
|
+
allowEscapeForVersioning
|
|
10972
|
+
}),
|
|
10973
|
+
js_module: (urlInfo, context) => parseAndTransformJsReferences(urlInfo, context, {
|
|
10974
|
+
inlineContent,
|
|
10975
|
+
allowEscapeForVersioning
|
|
10976
|
+
})
|
|
10977
|
+
}
|
|
10978
|
+
}];
|
|
10979
|
+
};
|
|
10980
|
+
const parseAndTransformJsReferences = async (urlInfo, context, {
|
|
10981
|
+
inlineContent,
|
|
10982
|
+
allowEscapeForVersioning
|
|
10983
|
+
}) => {
|
|
10984
|
+
const magicSource = createMagicSource(urlInfo.content);
|
|
10985
|
+
const parallelActions = [];
|
|
10986
|
+
const sequentialActions = [];
|
|
10987
|
+
const onInlineReference = inlineReferenceInfo => {
|
|
10988
|
+
const inlineUrl = generateInlineContentUrl({
|
|
10989
|
+
url: urlInfo.url,
|
|
10990
|
+
extension: CONTENT_TYPE.asFileExtension(inlineReferenceInfo.contentType),
|
|
10991
|
+
line: inlineReferenceInfo.line,
|
|
10992
|
+
column: inlineReferenceInfo.column,
|
|
10993
|
+
lineEnd: inlineReferenceInfo.lineEnd,
|
|
10994
|
+
columnEnd: inlineReferenceInfo.columnEnd
|
|
10995
|
+
});
|
|
10996
|
+
let {
|
|
10997
|
+
quote
|
|
10998
|
+
} = inlineReferenceInfo;
|
|
10999
|
+
if (quote === "`" && !context.isSupportedOnCurrentClients("template_literals")) {
|
|
11000
|
+
// if quote is "`" and template literals are not supported
|
|
11001
|
+
// we'll use a regular string (single or double quote)
|
|
11002
|
+
// when rendering the string
|
|
11003
|
+
quote = JS_QUOTES.pickBest(inlineReferenceInfo.content);
|
|
11004
|
+
}
|
|
11005
|
+
const [inlineReference, inlineUrlInfo] = context.referenceUtils.foundInline({
|
|
11006
|
+
type: "js_inline_content",
|
|
11007
|
+
subtype: inlineReferenceInfo.type,
|
|
11008
|
+
// "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
11009
|
+
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
11010
|
+
specifierLine: inlineReferenceInfo.line,
|
|
11011
|
+
specifierColumn: inlineReferenceInfo.column,
|
|
11012
|
+
specifier: inlineUrl,
|
|
11013
|
+
contentType: inlineReferenceInfo.contentType,
|
|
11014
|
+
content: inlineReferenceInfo.content
|
|
11015
|
+
});
|
|
11016
|
+
inlineUrlInfo.jsQuote = quote;
|
|
11017
|
+
inlineReference.escape = value => JS_QUOTES.escapeSpecialChars(value.slice(1, -1), {
|
|
11018
|
+
quote
|
|
11019
|
+
});
|
|
11020
|
+
sequentialActions.push(async () => {
|
|
11021
|
+
await context.cook(inlineUrlInfo, {
|
|
11022
|
+
reference: inlineReference
|
|
11023
|
+
});
|
|
11024
|
+
const replacement = JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
11025
|
+
quote,
|
|
11026
|
+
allowEscapeForVersioning
|
|
11027
|
+
});
|
|
11028
|
+
magicSource.replace({
|
|
11029
|
+
start: inlineReferenceInfo.start,
|
|
11030
|
+
end: inlineReferenceInfo.end,
|
|
11031
|
+
replacement
|
|
11032
|
+
});
|
|
11033
|
+
});
|
|
11034
|
+
};
|
|
11035
|
+
const onExternalReference = externalReferenceInfo => {
|
|
11036
|
+
if (externalReferenceInfo.subtype === "import_static" || externalReferenceInfo.subtype === "import_dynamic") {
|
|
11037
|
+
urlInfo.data.usesImport = true;
|
|
11038
|
+
}
|
|
11039
|
+
const [reference] = context.referenceUtils.found({
|
|
11040
|
+
node: externalReferenceInfo.node,
|
|
11041
|
+
type: externalReferenceInfo.type,
|
|
11042
|
+
subtype: externalReferenceInfo.subtype,
|
|
11043
|
+
expectedType: externalReferenceInfo.expectedType,
|
|
11044
|
+
expectedSubtype: externalReferenceInfo.expectedSubtype || urlInfo.subtype,
|
|
11045
|
+
specifier: externalReferenceInfo.specifier,
|
|
11046
|
+
specifierStart: externalReferenceInfo.start,
|
|
11047
|
+
specifierEnd: externalReferenceInfo.end,
|
|
11048
|
+
specifierLine: externalReferenceInfo.line,
|
|
11049
|
+
specifierColumn: externalReferenceInfo.column,
|
|
11050
|
+
data: externalReferenceInfo.data,
|
|
11051
|
+
baseUrl: {
|
|
11052
|
+
"StringLiteral": externalReferenceInfo.baseUrl,
|
|
11053
|
+
"window.location": urlInfo.url,
|
|
11054
|
+
"window.origin": context.rootDirectoryUrl,
|
|
11055
|
+
"import.meta.url": urlInfo.url,
|
|
11056
|
+
"context.meta.url": urlInfo.url,
|
|
11057
|
+
"document.currentScript.src": urlInfo.url
|
|
11058
|
+
}[externalReferenceInfo.baseUrlType],
|
|
11059
|
+
assert: externalReferenceInfo.assert,
|
|
11060
|
+
assertNode: externalReferenceInfo.assertNode,
|
|
11061
|
+
typePropertyNode: externalReferenceInfo.typePropertyNode
|
|
11062
|
+
});
|
|
11063
|
+
parallelActions.push(async () => {
|
|
11064
|
+
const replacement = await context.referenceUtils.readGeneratedSpecifier(reference);
|
|
11065
|
+
magicSource.replace({
|
|
11066
|
+
start: externalReferenceInfo.start,
|
|
11067
|
+
end: externalReferenceInfo.end,
|
|
11068
|
+
replacement
|
|
11069
|
+
});
|
|
11070
|
+
if (reference.mutation) {
|
|
11071
|
+
reference.mutation(magicSource);
|
|
11072
|
+
}
|
|
11073
|
+
});
|
|
11074
|
+
};
|
|
11075
|
+
const jsReferenceInfos = await parseJsUrls({
|
|
11076
|
+
js: urlInfo.content,
|
|
11077
|
+
url: urlInfo.originalUrl,
|
|
11078
|
+
isJsModule: urlInfo.type === "js_module",
|
|
11079
|
+
isWebWorker: isWebWorkerUrlInfo(urlInfo),
|
|
11080
|
+
inlineContent
|
|
11081
|
+
});
|
|
11082
|
+
for (const jsReferenceInfo of jsReferenceInfos) {
|
|
11083
|
+
if (jsReferenceInfo.isInline) {
|
|
11084
|
+
onInlineReference(jsReferenceInfo);
|
|
11085
|
+
} else {
|
|
11086
|
+
onExternalReference(jsReferenceInfo);
|
|
11087
|
+
}
|
|
11088
|
+
}
|
|
11089
|
+
if (parallelActions.length > 0) {
|
|
11090
|
+
await Promise.all(parallelActions.map(action => action()));
|
|
11091
|
+
}
|
|
11092
|
+
if (sequentialActions.length > 0) {
|
|
11093
|
+
await sequentialActions.reduce(async (previous, action) => {
|
|
11094
|
+
await previous;
|
|
11095
|
+
await action();
|
|
11096
|
+
}, Promise.resolve());
|
|
11097
|
+
}
|
|
11098
|
+
const {
|
|
11099
|
+
content,
|
|
11100
|
+
sourcemap
|
|
11101
|
+
} = magicSource.toContentAndSourcemap();
|
|
11102
|
+
return {
|
|
11103
|
+
content,
|
|
11104
|
+
sourcemap
|
|
11105
|
+
};
|
|
11106
|
+
};
|
|
11107
|
+
|
|
11108
|
+
const jsenvPluginReferenceAnalysis = ({
|
|
11109
|
+
include,
|
|
11110
|
+
supportedProtocols = ["file:", "data:", "virtual:", "http:", "https:"],
|
|
11111
|
+
inlineContent = true,
|
|
11112
|
+
inlineConvertedScript = false,
|
|
11113
|
+
fetchInlineUrls = true,
|
|
11114
|
+
allowEscapeForVersioning = false
|
|
11115
|
+
}) => {
|
|
11116
|
+
return [jsenvPluginReferenceAnalysisInclude({
|
|
11117
|
+
include,
|
|
11118
|
+
supportedProtocols
|
|
11119
|
+
}), jsenvPluginDirectoryReferenceAnalysis(), jsenvPluginHtmlReferenceAnalysis({
|
|
11120
|
+
inlineContent,
|
|
11121
|
+
inlineConvertedScript
|
|
11122
|
+
}), jsenvPluginWebmanifestReferenceAnalysis(), jsenvPluginCssReferenceAnalysis(), jsenvPluginJsReferenceAnalysis({
|
|
11123
|
+
inlineContent,
|
|
11124
|
+
allowEscapeForVersioning
|
|
11125
|
+
}), ...(inlineContent ? [jsenvPluginDataUrlsAnalysis()] : []), ...(inlineContent && fetchInlineUrls ? [jsenvPluginInlineContentFetcher()] : []), jsenvPluginReferenceExpectedTypes()];
|
|
11126
|
+
};
|
|
11127
|
+
const jsenvPluginReferenceAnalysisInclude = ({
|
|
11128
|
+
include,
|
|
11129
|
+
supportedProtocols
|
|
11130
|
+
}) => {
|
|
11131
|
+
// eslint-disable-next-line no-unused-vars
|
|
11132
|
+
let getIncludeInfo = url => undefined;
|
|
11133
|
+
return {
|
|
11134
|
+
name: "jsenv:reference_analysis_include",
|
|
11135
|
+
appliesDuring: "*",
|
|
11136
|
+
init: ({
|
|
11137
|
+
rootDirectoryUrl
|
|
11138
|
+
}) => {
|
|
11139
|
+
if (include) {
|
|
11140
|
+
const associations = URL_META.resolveAssociations({
|
|
11141
|
+
include
|
|
11142
|
+
}, rootDirectoryUrl);
|
|
11143
|
+
getIncludeInfo = url => {
|
|
11144
|
+
const {
|
|
11145
|
+
include
|
|
11146
|
+
} = URL_META.applyAssociations({
|
|
11147
|
+
url,
|
|
11148
|
+
associations
|
|
11149
|
+
});
|
|
11150
|
+
return include;
|
|
11151
|
+
};
|
|
11152
|
+
}
|
|
11153
|
+
},
|
|
11154
|
+
redirectReference: reference => {
|
|
11155
|
+
if (reference.shouldHandle !== undefined) {
|
|
11156
|
+
return;
|
|
11157
|
+
}
|
|
11158
|
+
if (reference.specifier[0] === "#" &&
|
|
11159
|
+
// For Html, css and in general "#" refer to a resource in the page
|
|
10750
11160
|
// so that urls must be kept intact
|
|
10751
11161
|
// However for js import specifiers they have a different meaning and we want
|
|
10752
11162
|
// to resolve them (https://nodejs.org/api/packages.html#imports for instance)
|
|
@@ -10770,57 +11180,32 @@ const jsenvPluginUrlAnalysis = ({
|
|
|
10770
11180
|
if (protocolIsSupported) {
|
|
10771
11181
|
reference.shouldHandle = true;
|
|
10772
11182
|
}
|
|
10773
|
-
},
|
|
10774
|
-
transformUrlContent: {
|
|
10775
|
-
html: parseAndTransformHtmlUrls,
|
|
10776
|
-
css: parseAndTransformCssUrls,
|
|
10777
|
-
js_classic: parseAndTransformJsUrls,
|
|
10778
|
-
js_module: parseAndTransformJsUrls,
|
|
10779
|
-
webmanifest: parseAndTransformWebmanifestUrls,
|
|
10780
|
-
directory: (urlInfo, context) => {
|
|
10781
|
-
const originalDirectoryReference = findOriginalDirectoryReference(urlInfo, context);
|
|
10782
|
-
const directoryRelativeUrl = urlToRelativeUrl(urlInfo.url, context.rootDirectoryUrl);
|
|
10783
|
-
JSON.parse(urlInfo.content).forEach(directoryEntryName => {
|
|
10784
|
-
context.referenceUtils.found({
|
|
10785
|
-
type: "filesystem",
|
|
10786
|
-
subtype: "directory_entry",
|
|
10787
|
-
specifier: directoryEntryName,
|
|
10788
|
-
trace: {
|
|
10789
|
-
message: `"${directoryRelativeUrl}${directoryEntryName}" entry in directory referenced by ${originalDirectoryReference.trace.message}`
|
|
10790
|
-
}
|
|
10791
|
-
});
|
|
10792
|
-
});
|
|
10793
|
-
}
|
|
10794
11183
|
}
|
|
10795
|
-
}
|
|
11184
|
+
};
|
|
10796
11185
|
};
|
|
10797
|
-
const
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10802
|
-
|
|
10803
|
-
|
|
10804
|
-
const found = findNonFileSystemAncestor(dependentUrlInfo);
|
|
10805
|
-
if (found) {
|
|
10806
|
-
return found;
|
|
11186
|
+
const jsenvPluginInlineContentFetcher = () => {
|
|
11187
|
+
return {
|
|
11188
|
+
name: "jsenv:inline_content_fetcher",
|
|
11189
|
+
appliesDuring: "*",
|
|
11190
|
+
fetchUrlContent: urlInfo => {
|
|
11191
|
+
if (!urlInfo.isInline) {
|
|
11192
|
+
return null;
|
|
10807
11193
|
}
|
|
11194
|
+
return {
|
|
11195
|
+
// we want to fetch the original content otherwise we might re-cook
|
|
11196
|
+
// content already cooked
|
|
11197
|
+
content: urlInfo.originalContent,
|
|
11198
|
+
contentType: urlInfo.contentType
|
|
11199
|
+
};
|
|
10808
11200
|
}
|
|
10809
|
-
return [];
|
|
10810
11201
|
};
|
|
10811
|
-
const [ancestor, child] = findNonFileSystemAncestor(urlInfo);
|
|
10812
|
-
if (!ancestor) {
|
|
10813
|
-
return null;
|
|
10814
|
-
}
|
|
10815
|
-
const ref = ancestor.references.find(ref => ref.url === child.url);
|
|
10816
|
-
return ref;
|
|
10817
11202
|
};
|
|
10818
11203
|
|
|
10819
11204
|
const jsenvPluginInliningAsDataUrl = () => {
|
|
10820
11205
|
return {
|
|
10821
11206
|
name: "jsenv:inlining_as_data_url",
|
|
10822
11207
|
appliesDuring: "*",
|
|
10823
|
-
|
|
11208
|
+
formatReference: {
|
|
10824
11209
|
// if the referenced url is a worker we could use
|
|
10825
11210
|
// https://www.oreilly.com/library/view/web-workers/9781449322120/ch04.html
|
|
10826
11211
|
// but maybe we should rather use ?object_url
|
|
@@ -10846,10 +11231,19 @@ const jsenvPluginInliningAsDataUrl = () => {
|
|
|
10846
11231
|
await context.cook(urlInfo, {
|
|
10847
11232
|
reference
|
|
10848
11233
|
});
|
|
11234
|
+
const contentAsBase64 = Buffer.from(urlInfo.content).toString("base64");
|
|
10849
11235
|
const specifier = DATA_URL.stringify({
|
|
10850
11236
|
mediaType: urlInfo.contentType,
|
|
10851
11237
|
base64Flag: true,
|
|
10852
|
-
data:
|
|
11238
|
+
data: contentAsBase64
|
|
11239
|
+
});
|
|
11240
|
+
context.referenceUtils.becomesInline(reference, {
|
|
11241
|
+
line: reference.line,
|
|
11242
|
+
column: reference.column,
|
|
11243
|
+
isOriginal: reference.isOriginal,
|
|
11244
|
+
specifier,
|
|
11245
|
+
content: contentAsBase64,
|
|
11246
|
+
contentType: urlInfo.contentType
|
|
10853
11247
|
});
|
|
10854
11248
|
return specifier;
|
|
10855
11249
|
})();
|
|
@@ -10938,789 +11332,81 @@ const jsenvPluginInliningIntoHtml = () => {
|
|
|
10938
11332
|
isOriginal,
|
|
10939
11333
|
specifier: scriptReference.generatedSpecifier,
|
|
10940
11334
|
content: scriptUrlInfo.content,
|
|
10941
|
-
contentType: scriptUrlInfo.contentType
|
|
10942
|
-
});
|
|
10943
|
-
mutations.push(() => {
|
|
10944
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
10945
|
-
"inlined-from-src": src,
|
|
10946
|
-
"src": undefined,
|
|
10947
|
-
"crossorigin": undefined,
|
|
10948
|
-
"integrity": undefined,
|
|
10949
|
-
"jsenv-inlined-by": "jsenv:inlining_into_html"
|
|
10950
|
-
});
|
|
10951
|
-
setHtmlNodeText(scriptNode, scriptUrlInfo.content, {
|
|
10952
|
-
indentation: "auto"
|
|
10953
|
-
});
|
|
10954
|
-
});
|
|
10955
|
-
});
|
|
10956
|
-
};
|
|
10957
|
-
visitHtmlNodes(htmlAst, {
|
|
10958
|
-
link: linkNode => {
|
|
10959
|
-
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
10960
|
-
if (rel !== "stylesheet") {
|
|
10961
|
-
return;
|
|
10962
|
-
}
|
|
10963
|
-
const href = getHtmlNodeAttribute(linkNode, "href");
|
|
10964
|
-
if (!href) {
|
|
10965
|
-
return;
|
|
10966
|
-
}
|
|
10967
|
-
onStyleSheet(linkNode, {
|
|
10968
|
-
href
|
|
10969
|
-
});
|
|
10970
|
-
},
|
|
10971
|
-
script: scriptNode => {
|
|
10972
|
-
const {
|
|
10973
|
-
type
|
|
10974
|
-
} = analyzeScriptNode(scriptNode);
|
|
10975
|
-
const scriptNodeText = getHtmlNodeText(scriptNode);
|
|
10976
|
-
if (scriptNodeText) {
|
|
10977
|
-
return;
|
|
10978
|
-
}
|
|
10979
|
-
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
10980
|
-
if (!src) {
|
|
10981
|
-
return;
|
|
10982
|
-
}
|
|
10983
|
-
onScriptWithSrc(scriptNode, {
|
|
10984
|
-
type,
|
|
10985
|
-
src
|
|
10986
|
-
});
|
|
10987
|
-
}
|
|
10988
|
-
});
|
|
10989
|
-
if (actions.length > 0) {
|
|
10990
|
-
await Promise.all(actions.map(action => action()));
|
|
10991
|
-
}
|
|
10992
|
-
mutations.forEach(mutation => mutation());
|
|
10993
|
-
const htmlModified = stringifyHtmlAst(htmlAst);
|
|
10994
|
-
return htmlModified;
|
|
10995
|
-
}
|
|
10996
|
-
}
|
|
10997
|
-
};
|
|
10998
|
-
};
|
|
10999
|
-
|
|
11000
|
-
const jsenvPluginInlining = () => {
|
|
11001
|
-
return [{
|
|
11002
|
-
name: "jsenv:inlining",
|
|
11003
|
-
appliesDuring: "*",
|
|
11004
|
-
redirectUrl: reference => {
|
|
11005
|
-
const {
|
|
11006
|
-
searchParams
|
|
11007
|
-
} = reference;
|
|
11008
|
-
if (searchParams.has("inline")) {
|
|
11009
|
-
const urlObject = new URL(reference.url);
|
|
11010
|
-
urlObject.searchParams.delete("inline");
|
|
11011
|
-
return urlObject.href;
|
|
11012
|
-
}
|
|
11013
|
-
return null;
|
|
11014
|
-
}
|
|
11015
|
-
}, jsenvPluginInliningAsDataUrl(), jsenvPluginInliningIntoHtml()];
|
|
11016
|
-
};
|
|
11017
|
-
|
|
11018
|
-
/*
|
|
11019
|
-
* This plugin ensure content inlined inside HTML is cooked (inline <script> for instance)
|
|
11020
|
-
* For <script hot-accept> the script content will be moved to a virtual file
|
|
11021
|
-
* to enable hot reloading
|
|
11022
|
-
*/
|
|
11023
|
-
const jsenvPluginHtmlInlineContentAnalysis = ({
|
|
11024
|
-
analyzeConvertedScripts
|
|
11025
|
-
}) => {
|
|
11026
|
-
const cookInlineContent = async ({
|
|
11027
|
-
context,
|
|
11028
|
-
inlineContentUrlInfo,
|
|
11029
|
-
inlineContentReference
|
|
11030
|
-
}) => {
|
|
11031
|
-
try {
|
|
11032
|
-
await context.cook(inlineContentUrlInfo, {
|
|
11033
|
-
reference: inlineContentReference
|
|
11034
|
-
});
|
|
11035
|
-
} catch (e) {
|
|
11036
|
-
if (e.code === "PARSE_ERROR") {
|
|
11037
|
-
// When something like <style> or <script> contains syntax error
|
|
11038
|
-
// the HTML in itself it still valid
|
|
11039
|
-
// keep the syntax error and continue with the HTML
|
|
11040
|
-
const messageStart = inlineContentUrlInfo.type === "css" ? `Syntax error on css declared inside <style>` : `Syntax error on js declared inside <script>`;
|
|
11041
|
-
context.logger.error(`${messageStart}: ${e.cause.reasonCode}
|
|
11042
|
-
${e.traceMessage}`);
|
|
11043
|
-
} else {
|
|
11044
|
-
throw e;
|
|
11045
|
-
}
|
|
11046
|
-
}
|
|
11047
|
-
};
|
|
11048
|
-
return {
|
|
11049
|
-
name: "jsenv:html_inline_content_analysis",
|
|
11050
|
-
appliesDuring: "*",
|
|
11051
|
-
transformUrlContent: {
|
|
11052
|
-
html: async (urlInfo, context) => {
|
|
11053
|
-
const htmlAst = parseHtmlString(urlInfo.content);
|
|
11054
|
-
const mutations = [];
|
|
11055
|
-
const actions = [];
|
|
11056
|
-
visitHtmlNodes(htmlAst, {
|
|
11057
|
-
style: styleNode => {
|
|
11058
|
-
const styleNodeText = getHtmlNodeText(styleNode);
|
|
11059
|
-
if (!styleNodeText) {
|
|
11060
|
-
return;
|
|
11061
|
-
}
|
|
11062
|
-
const {
|
|
11063
|
-
line,
|
|
11064
|
-
column,
|
|
11065
|
-
lineEnd,
|
|
11066
|
-
columnEnd,
|
|
11067
|
-
isOriginal
|
|
11068
|
-
} = getHtmlNodePosition(styleNode, {
|
|
11069
|
-
preferOriginal: true
|
|
11070
|
-
});
|
|
11071
|
-
const inlineStyleUrl = generateInlineContentUrl({
|
|
11072
|
-
url: urlInfo.url,
|
|
11073
|
-
extension: ".css",
|
|
11074
|
-
line,
|
|
11075
|
-
column,
|
|
11076
|
-
lineEnd,
|
|
11077
|
-
columnEnd
|
|
11078
|
-
});
|
|
11079
|
-
const debug = getHtmlNodeAttribute(styleNode, "jsenv-debug") !== undefined;
|
|
11080
|
-
const [inlineStyleReference, inlineStyleUrlInfo] = context.referenceUtils.foundInline({
|
|
11081
|
-
node: styleNode,
|
|
11082
|
-
type: "style",
|
|
11083
|
-
expectedType: "css",
|
|
11084
|
-
isOriginalPosition: isOriginal,
|
|
11085
|
-
// we remove 1 to the line because imagine the following html:
|
|
11086
|
-
// <style>body { color: red; }</style>
|
|
11087
|
-
// -> content starts same line as <style>
|
|
11088
|
-
specifierLine: line - 1,
|
|
11089
|
-
specifierColumn: column,
|
|
11090
|
-
specifier: inlineStyleUrl,
|
|
11091
|
-
contentType: "text/css",
|
|
11092
|
-
content: styleNodeText,
|
|
11093
|
-
debug
|
|
11094
|
-
});
|
|
11095
|
-
actions.push(async () => {
|
|
11096
|
-
await cookInlineContent({
|
|
11097
|
-
context,
|
|
11098
|
-
inlineContentUrlInfo: inlineStyleUrlInfo,
|
|
11099
|
-
inlineContentReference: inlineStyleReference
|
|
11100
|
-
});
|
|
11101
|
-
});
|
|
11102
|
-
mutations.push(() => {
|
|
11103
|
-
setHtmlNodeText(styleNode, inlineStyleUrlInfo.content, {
|
|
11104
|
-
indentation: false // indentation would decrease strack trace precision
|
|
11105
|
-
});
|
|
11106
|
-
|
|
11107
|
-
setHtmlNodeAttributes(styleNode, {
|
|
11108
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis"
|
|
11109
|
-
});
|
|
11110
|
-
});
|
|
11111
|
-
},
|
|
11112
|
-
script: scriptNode => {
|
|
11113
|
-
const scriptNodeText = getHtmlNodeText(scriptNode);
|
|
11114
|
-
if (!scriptNodeText) {
|
|
11115
|
-
return;
|
|
11116
|
-
}
|
|
11117
|
-
// If the inline script was already handled by an other plugin, ignore it
|
|
11118
|
-
// - we want to preserve inline scripts generated by html supervisor during dev
|
|
11119
|
-
// - we want to avoid cooking twice a script during build
|
|
11120
|
-
if (!analyzeConvertedScripts && getHtmlNodeAttribute(scriptNode, "jsenv-injected-by") === "jsenv:js_module_fallback") {
|
|
11121
|
-
return;
|
|
11122
|
-
}
|
|
11123
|
-
const hotAccept = getHtmlNodeAttribute(scriptNode, "hot-accept") !== undefined;
|
|
11124
|
-
const {
|
|
11125
|
-
type,
|
|
11126
|
-
contentType,
|
|
11127
|
-
extension
|
|
11128
|
-
} = analyzeScriptNode(scriptNode);
|
|
11129
|
-
const {
|
|
11130
|
-
line,
|
|
11131
|
-
column,
|
|
11132
|
-
lineEnd,
|
|
11133
|
-
columnEnd,
|
|
11134
|
-
isOriginal
|
|
11135
|
-
} = getHtmlNodePosition(scriptNode, {
|
|
11136
|
-
preferOriginal: true
|
|
11137
|
-
});
|
|
11138
|
-
let inlineScriptUrl = generateInlineContentUrl({
|
|
11139
|
-
url: urlInfo.url,
|
|
11140
|
-
extension: extension || CONTENT_TYPE.asFileExtension(contentType),
|
|
11141
|
-
line,
|
|
11142
|
-
column,
|
|
11143
|
-
lineEnd,
|
|
11144
|
-
columnEnd
|
|
11145
|
-
});
|
|
11146
|
-
const debug = getHtmlNodeAttribute(scriptNode, "jsenv-debug") !== undefined;
|
|
11147
|
-
const [inlineScriptReference, inlineScriptUrlInfo] = context.referenceUtils.foundInline({
|
|
11148
|
-
node: scriptNode,
|
|
11149
|
-
type: "script",
|
|
11150
|
-
expectedType: type,
|
|
11151
|
-
// we remove 1 to the line because imagine the following html:
|
|
11152
|
-
// <script>console.log('ok')</script>
|
|
11153
|
-
// -> content starts same line as <script>
|
|
11154
|
-
specifierLine: line - 1,
|
|
11155
|
-
specifierColumn: column,
|
|
11156
|
-
isOriginalPosition: isOriginal,
|
|
11157
|
-
specifier: inlineScriptUrl,
|
|
11158
|
-
contentType,
|
|
11159
|
-
content: scriptNodeText,
|
|
11160
|
-
debug
|
|
11161
|
-
});
|
|
11162
|
-
actions.push(async () => {
|
|
11163
|
-
await cookInlineContent({
|
|
11164
|
-
context,
|
|
11165
|
-
inlineContentUrlInfo: inlineScriptUrlInfo,
|
|
11166
|
-
inlineContentReference: inlineScriptReference
|
|
11167
|
-
});
|
|
11168
|
-
mutations.push(() => {
|
|
11169
|
-
const attributes = {
|
|
11170
|
-
"jsenv-cooked-by": "jsenv:html_inline_content_analysis",
|
|
11171
|
-
// 1. <script type="jsx"> becomes <script>
|
|
11172
|
-
// 2. <script type="module/jsx"> becomes <script type="module">
|
|
11173
|
-
...(extension ? {
|
|
11174
|
-
type: type === "js_module" ? "module" : undefined
|
|
11175
|
-
} : {})
|
|
11176
|
-
};
|
|
11177
|
-
if (hotAccept) {
|
|
11178
|
-
removeHtmlNodeText(scriptNode);
|
|
11179
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
11180
|
-
...attributes
|
|
11181
|
-
});
|
|
11182
|
-
} else {
|
|
11183
|
-
setHtmlNodeText(scriptNode, inlineScriptUrlInfo.content, {
|
|
11184
|
-
indentation: false // indentation would decrease stack trace precision
|
|
11185
|
-
});
|
|
11186
|
-
|
|
11187
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
11188
|
-
...attributes
|
|
11189
|
-
});
|
|
11190
|
-
}
|
|
11191
|
-
});
|
|
11192
|
-
});
|
|
11193
|
-
}
|
|
11194
|
-
});
|
|
11195
|
-
if (actions.length > 0) {
|
|
11196
|
-
await Promise.all(actions.map(action => action()));
|
|
11197
|
-
}
|
|
11198
|
-
if (mutations.length === 0) {
|
|
11199
|
-
return null;
|
|
11200
|
-
}
|
|
11201
|
-
mutations.forEach(mutation => mutation());
|
|
11202
|
-
const htmlModified = stringifyHtmlAst(htmlAst);
|
|
11203
|
-
return htmlModified;
|
|
11204
|
-
}
|
|
11205
|
-
}
|
|
11206
|
-
};
|
|
11207
|
-
};
|
|
11208
|
-
|
|
11209
|
-
const isEscaped = (i, string) => {
|
|
11210
|
-
let backslashBeforeCount = 0;
|
|
11211
|
-
while (i--) {
|
|
11212
|
-
const previousChar = string[i];
|
|
11213
|
-
if (previousChar === "\\") {
|
|
11214
|
-
backslashBeforeCount++;
|
|
11215
|
-
}
|
|
11216
|
-
break;
|
|
11217
|
-
}
|
|
11218
|
-
const isEven = backslashBeforeCount % 2 === 0;
|
|
11219
|
-
return !isEven;
|
|
11220
|
-
};
|
|
11221
|
-
|
|
11222
|
-
const JS_QUOTES = {
|
|
11223
|
-
pickBest: (string, {
|
|
11224
|
-
canUseTemplateString,
|
|
11225
|
-
defaultQuote = DOUBLE
|
|
11226
|
-
} = {}) => {
|
|
11227
|
-
// check default first, once tested do no re-test it
|
|
11228
|
-
if (!string.includes(defaultQuote)) {
|
|
11229
|
-
return defaultQuote;
|
|
11230
|
-
}
|
|
11231
|
-
if (defaultQuote !== DOUBLE && !string.includes(DOUBLE)) {
|
|
11232
|
-
return DOUBLE;
|
|
11233
|
-
}
|
|
11234
|
-
if (defaultQuote !== SINGLE && !string.includes(SINGLE)) {
|
|
11235
|
-
return SINGLE;
|
|
11236
|
-
}
|
|
11237
|
-
if (canUseTemplateString && defaultQuote !== BACKTICK && !string.includes(BACKTICK)) {
|
|
11238
|
-
return BACKTICK;
|
|
11239
|
-
}
|
|
11240
|
-
return defaultQuote;
|
|
11241
|
-
},
|
|
11242
|
-
escapeSpecialChars: (string, {
|
|
11243
|
-
quote = "pickBest",
|
|
11244
|
-
canUseTemplateString,
|
|
11245
|
-
defaultQuote,
|
|
11246
|
-
allowEscapeForVersioning = false
|
|
11247
|
-
}) => {
|
|
11248
|
-
quote = quote === "pickBest" ? JS_QUOTES.pickBest(string, {
|
|
11249
|
-
canUseTemplateString,
|
|
11250
|
-
defaultQuote
|
|
11251
|
-
}) : quote;
|
|
11252
|
-
const replacements = JS_QUOTE_REPLACEMENTS[quote];
|
|
11253
|
-
let result = "";
|
|
11254
|
-
let last = 0;
|
|
11255
|
-
let i = 0;
|
|
11256
|
-
while (i < string.length) {
|
|
11257
|
-
const char = string[i];
|
|
11258
|
-
i++;
|
|
11259
|
-
if (isEscaped(i - 1, string)) continue;
|
|
11260
|
-
const replacement = replacements[char];
|
|
11261
|
-
if (replacement) {
|
|
11262
|
-
if (allowEscapeForVersioning && char === quote && string.slice(i, i + 6) === "+__v__") {
|
|
11263
|
-
let isVersioningConcatenation = false;
|
|
11264
|
-
let j = i + 6; // start after the +
|
|
11265
|
-
while (j < string.length) {
|
|
11266
|
-
const lookAheadChar = string[j];
|
|
11267
|
-
j++;
|
|
11268
|
-
if (lookAheadChar === "+" && string[j] === quote && !isEscaped(j - 1, string)) {
|
|
11269
|
-
isVersioningConcatenation = true;
|
|
11270
|
-
break;
|
|
11271
|
-
}
|
|
11272
|
-
}
|
|
11273
|
-
if (isVersioningConcatenation) {
|
|
11274
|
-
// it's a concatenation
|
|
11275
|
-
// skip until the end of concatenation (the second +)
|
|
11276
|
-
// and resume from there
|
|
11277
|
-
i = j + 1;
|
|
11278
|
-
continue;
|
|
11279
|
-
}
|
|
11280
|
-
}
|
|
11281
|
-
if (last === i - 1) {
|
|
11282
|
-
result += replacement;
|
|
11283
|
-
} else {
|
|
11284
|
-
result += `${string.slice(last, i - 1)}${replacement}`;
|
|
11285
|
-
}
|
|
11286
|
-
last = i;
|
|
11287
|
-
}
|
|
11288
|
-
}
|
|
11289
|
-
if (last !== string.length) {
|
|
11290
|
-
result += string.slice(last);
|
|
11291
|
-
}
|
|
11292
|
-
return `${quote}${result}${quote}`;
|
|
11293
|
-
}
|
|
11294
|
-
};
|
|
11295
|
-
const DOUBLE = `"`;
|
|
11296
|
-
const SINGLE = `'`;
|
|
11297
|
-
const BACKTICK = "`";
|
|
11298
|
-
const lineEndingEscapes = {
|
|
11299
|
-
"\n": "\\n",
|
|
11300
|
-
"\r": "\\r",
|
|
11301
|
-
"\u2028": "\\u2028",
|
|
11302
|
-
"\u2029": "\\u2029"
|
|
11303
|
-
};
|
|
11304
|
-
const JS_QUOTE_REPLACEMENTS = {
|
|
11305
|
-
[DOUBLE]: {
|
|
11306
|
-
'"': '\\"',
|
|
11307
|
-
...lineEndingEscapes
|
|
11308
|
-
},
|
|
11309
|
-
[SINGLE]: {
|
|
11310
|
-
"'": "\\'",
|
|
11311
|
-
...lineEndingEscapes
|
|
11312
|
-
},
|
|
11313
|
-
[BACKTICK]: {
|
|
11314
|
-
"`": "\\`",
|
|
11315
|
-
"$": "\\$"
|
|
11316
|
-
}
|
|
11317
|
-
};
|
|
11318
|
-
|
|
11319
|
-
const jsenvPluginJsInlineContentAnalysis = ({
|
|
11320
|
-
allowEscapeForVersioning
|
|
11321
|
-
}) => {
|
|
11322
|
-
const parseAndTransformInlineContentCalls = async (urlInfo, context) => {
|
|
11323
|
-
const inlineContentInfos = await parseJsInlineContentInfos({
|
|
11324
|
-
js: urlInfo.content,
|
|
11325
|
-
url: urlInfo.originalUrl,
|
|
11326
|
-
isJsModule: urlInfo.type === "js_module"
|
|
11327
|
-
});
|
|
11328
|
-
if (inlineContentInfos.length === 0) {
|
|
11329
|
-
return null;
|
|
11330
|
-
}
|
|
11331
|
-
const magicSource = createMagicSource(urlInfo.content);
|
|
11332
|
-
await inlineContentInfos.reduce(async (previous, inlineContentInfo) => {
|
|
11333
|
-
await previous;
|
|
11334
|
-
const inlineUrl = generateInlineContentUrl({
|
|
11335
|
-
url: urlInfo.url,
|
|
11336
|
-
extension: CONTENT_TYPE.asFileExtension(inlineContentInfo.contentType),
|
|
11337
|
-
line: inlineContentInfo.line,
|
|
11338
|
-
column: inlineContentInfo.column,
|
|
11339
|
-
lineEnd: inlineContentInfo.lineEnd,
|
|
11340
|
-
columnEnd: inlineContentInfo.columnEnd
|
|
11341
|
-
});
|
|
11342
|
-
let {
|
|
11343
|
-
quote
|
|
11344
|
-
} = inlineContentInfo;
|
|
11345
|
-
if (quote === "`" && !context.isSupportedOnCurrentClients("template_literals")) {
|
|
11346
|
-
// if quote is "`" and template literals are not supported
|
|
11347
|
-
// we'll use a regular string (single or double quote)
|
|
11348
|
-
// when rendering the string
|
|
11349
|
-
quote = JS_QUOTES.pickBest(inlineContentInfo.content);
|
|
11350
|
-
}
|
|
11351
|
-
const [inlineReference, inlineUrlInfo] = context.referenceUtils.foundInline({
|
|
11352
|
-
type: "js_inline_content",
|
|
11353
|
-
subtype: inlineContentInfo.type,
|
|
11354
|
-
// "new_blob_first_arg", "new_inline_content_first_arg", "json_parse_first_arg"
|
|
11355
|
-
isOriginalPosition: urlInfo.content === urlInfo.originalContent,
|
|
11356
|
-
specifierLine: inlineContentInfo.line,
|
|
11357
|
-
specifierColumn: inlineContentInfo.column,
|
|
11358
|
-
specifier: inlineUrl,
|
|
11359
|
-
contentType: inlineContentInfo.contentType,
|
|
11360
|
-
content: inlineContentInfo.content
|
|
11361
|
-
});
|
|
11362
|
-
inlineUrlInfo.jsQuote = quote;
|
|
11363
|
-
inlineReference.escape = value => JS_QUOTES.escapeSpecialChars(value.slice(1, -1), {
|
|
11364
|
-
quote
|
|
11365
|
-
});
|
|
11366
|
-
await context.cook(inlineUrlInfo, {
|
|
11367
|
-
reference: inlineReference
|
|
11368
|
-
});
|
|
11369
|
-
magicSource.replace({
|
|
11370
|
-
start: inlineContentInfo.start,
|
|
11371
|
-
end: inlineContentInfo.end,
|
|
11372
|
-
replacement: JS_QUOTES.escapeSpecialChars(inlineUrlInfo.content, {
|
|
11373
|
-
quote,
|
|
11374
|
-
allowEscapeForVersioning
|
|
11375
|
-
})
|
|
11376
|
-
});
|
|
11377
|
-
}, Promise.resolve());
|
|
11378
|
-
return magicSource.toContentAndSourcemap();
|
|
11379
|
-
};
|
|
11380
|
-
return {
|
|
11381
|
-
name: "jsenv:js_inline_content_analysis",
|
|
11382
|
-
appliesDuring: "*",
|
|
11383
|
-
transformUrlContent: {
|
|
11384
|
-
js_classic: parseAndTransformInlineContentCalls,
|
|
11385
|
-
js_module: parseAndTransformInlineContentCalls
|
|
11386
|
-
}
|
|
11387
|
-
};
|
|
11388
|
-
};
|
|
11389
|
-
const parseJsInlineContentInfos = async ({
|
|
11390
|
-
js,
|
|
11391
|
-
url,
|
|
11392
|
-
isJsModule
|
|
11393
|
-
}) => {
|
|
11394
|
-
if (!js.includes("InlineContent") && !js.includes("new Blob(") && !js.includes("JSON.parse(")) {
|
|
11395
|
-
return [];
|
|
11396
|
-
}
|
|
11397
|
-
const {
|
|
11398
|
-
metadata
|
|
11399
|
-
} = await applyBabelPlugins({
|
|
11400
|
-
babelPlugins: [babelPluginMetadataInlineContents],
|
|
11401
|
-
urlInfo: {
|
|
11402
|
-
originalUrl: url,
|
|
11403
|
-
type: isJsModule ? "js_module" : "js_classic",
|
|
11404
|
-
content: js
|
|
11405
|
-
}
|
|
11406
|
-
});
|
|
11407
|
-
return metadata.inlineContentInfos;
|
|
11408
|
-
};
|
|
11409
|
-
const babelPluginMetadataInlineContents = () => {
|
|
11410
|
-
return {
|
|
11411
|
-
name: "metadata-inline-contents",
|
|
11412
|
-
visitor: {
|
|
11413
|
-
Program: (programPath, state) => {
|
|
11414
|
-
const inlineContentInfos = [];
|
|
11415
|
-
const onInlineContentInfo = inlineContentInfo => {
|
|
11416
|
-
inlineContentInfos.push(inlineContentInfo);
|
|
11417
|
-
};
|
|
11418
|
-
programPath.traverse({
|
|
11419
|
-
NewExpression: path => {
|
|
11420
|
-
if (isNewInlineContentCall(path)) {
|
|
11421
|
-
analyzeNewInlineContentCall(path.node, {
|
|
11422
|
-
onInlineContentInfo
|
|
11423
|
-
});
|
|
11424
|
-
return;
|
|
11425
|
-
}
|
|
11426
|
-
if (isNewBlobCall(path.node)) {
|
|
11427
|
-
analyzeNewBlobCall(path.node, {
|
|
11428
|
-
onInlineContentInfo
|
|
11429
|
-
});
|
|
11430
|
-
return;
|
|
11431
|
-
}
|
|
11432
|
-
},
|
|
11433
|
-
CallExpression: path => {
|
|
11434
|
-
const node = path.node;
|
|
11435
|
-
if (isJSONParseCall(node)) {
|
|
11436
|
-
analyzeJsonParseCall(node, {
|
|
11437
|
-
onInlineContentInfo
|
|
11438
|
-
});
|
|
11439
|
-
}
|
|
11440
|
-
}
|
|
11441
|
-
});
|
|
11442
|
-
state.file.metadata.inlineContentInfos = inlineContentInfos;
|
|
11443
|
-
}
|
|
11444
|
-
}
|
|
11445
|
-
};
|
|
11446
|
-
};
|
|
11447
|
-
const isNewInlineContentCall = path => {
|
|
11448
|
-
const node = path.node;
|
|
11449
|
-
if (node.callee.type === "Identifier") {
|
|
11450
|
-
// terser rename import to use a shorter name
|
|
11451
|
-
const name = getOriginalName(path, node.callee.name);
|
|
11452
|
-
return name === "InlineContent";
|
|
11453
|
-
}
|
|
11454
|
-
if (node.callee.id && node.callee.id.type === "Identifier") {
|
|
11455
|
-
const name = getOriginalName(path, node.callee.id.name);
|
|
11456
|
-
return name === "InlineContent";
|
|
11457
|
-
}
|
|
11458
|
-
return false;
|
|
11459
|
-
};
|
|
11460
|
-
const analyzeNewInlineContentCall = (node, {
|
|
11461
|
-
onInlineContentInfo
|
|
11462
|
-
}) => {
|
|
11463
|
-
analyzeArguments({
|
|
11464
|
-
node,
|
|
11465
|
-
onInlineContentInfo,
|
|
11466
|
-
nodeHoldingContent: node.arguments[0],
|
|
11467
|
-
type: "new_inline_content_first_arg"
|
|
11468
|
-
});
|
|
11469
|
-
};
|
|
11470
|
-
const isNewBlobCall = node => {
|
|
11471
|
-
return node.callee.type === "Identifier" && node.callee.name === "Blob";
|
|
11472
|
-
};
|
|
11473
|
-
const analyzeNewBlobCall = (node, {
|
|
11474
|
-
onInlineContentInfo
|
|
11475
|
-
}) => {
|
|
11476
|
-
const firstArg = node.arguments[0];
|
|
11477
|
-
if (!firstArg) {
|
|
11478
|
-
return;
|
|
11479
|
-
}
|
|
11480
|
-
if (firstArg.type !== "ArrayExpression") {
|
|
11481
|
-
return;
|
|
11482
|
-
}
|
|
11483
|
-
if (firstArg.elements.length !== 1) {
|
|
11484
|
-
return;
|
|
11485
|
-
}
|
|
11486
|
-
analyzeArguments({
|
|
11487
|
-
node,
|
|
11488
|
-
onInlineContentInfo,
|
|
11489
|
-
nodeHoldingContent: firstArg.elements[0],
|
|
11490
|
-
type: "new_blob_first_arg"
|
|
11491
|
-
});
|
|
11492
|
-
};
|
|
11493
|
-
const analyzeArguments = ({
|
|
11494
|
-
node,
|
|
11495
|
-
onInlineContentInfo,
|
|
11496
|
-
nodeHoldingContent,
|
|
11497
|
-
type
|
|
11498
|
-
}) => {
|
|
11499
|
-
if (node.arguments.length !== 2) {
|
|
11500
|
-
return;
|
|
11501
|
-
}
|
|
11502
|
-
const [, secondArg] = node.arguments;
|
|
11503
|
-
const typePropertyNode = getTypePropertyNode(secondArg);
|
|
11504
|
-
if (!typePropertyNode) {
|
|
11505
|
-
return;
|
|
11506
|
-
}
|
|
11507
|
-
const typePropertyValueNode = typePropertyNode.value;
|
|
11508
|
-
if (typePropertyValueNode.type !== "StringLiteral") {
|
|
11509
|
-
return;
|
|
11510
|
-
}
|
|
11511
|
-
const contentType = typePropertyValueNode.value;
|
|
11512
|
-
const contentDetails = extractContentDetails(nodeHoldingContent);
|
|
11513
|
-
if (contentDetails) {
|
|
11514
|
-
onInlineContentInfo({
|
|
11515
|
-
node: nodeHoldingContent,
|
|
11516
|
-
...getNodePosition(nodeHoldingContent),
|
|
11517
|
-
type,
|
|
11518
|
-
contentType,
|
|
11519
|
-
...contentDetails
|
|
11520
|
-
});
|
|
11521
|
-
}
|
|
11522
|
-
};
|
|
11523
|
-
const extractContentDetails = node => {
|
|
11524
|
-
if (node.type === "StringLiteral") {
|
|
11525
|
-
return {
|
|
11526
|
-
nodeType: "StringLiteral",
|
|
11527
|
-
quote: node.extra.raw[0],
|
|
11528
|
-
content: node.value
|
|
11529
|
-
};
|
|
11530
|
-
}
|
|
11531
|
-
if (node.type === "TemplateLiteral") {
|
|
11532
|
-
const quasis = node.quasis;
|
|
11533
|
-
if (quasis.length !== 1) {
|
|
11534
|
-
return null;
|
|
11535
|
-
}
|
|
11536
|
-
const templateElementNode = quasis[0];
|
|
11537
|
-
return {
|
|
11538
|
-
nodeType: "TemplateLiteral",
|
|
11539
|
-
quote: "`",
|
|
11540
|
-
content: templateElementNode.value.cooked
|
|
11541
|
-
};
|
|
11542
|
-
}
|
|
11543
|
-
return null;
|
|
11544
|
-
};
|
|
11545
|
-
const isJSONParseCall = node => {
|
|
11546
|
-
const callee = node.callee;
|
|
11547
|
-
return callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === "JSON" && callee.property.type === "Identifier" && callee.property.name === "parse";
|
|
11548
|
-
};
|
|
11549
|
-
const analyzeJsonParseCall = (node, {
|
|
11550
|
-
onInlineContentInfo
|
|
11551
|
-
}) => {
|
|
11552
|
-
const firstArgNode = node.arguments[0];
|
|
11553
|
-
const contentDetails = extractContentDetails(firstArgNode);
|
|
11554
|
-
if (contentDetails) {
|
|
11555
|
-
onInlineContentInfo({
|
|
11556
|
-
node: firstArgNode,
|
|
11557
|
-
...getNodePosition(firstArgNode),
|
|
11558
|
-
type: "json_parse_first_arg",
|
|
11559
|
-
contentType: "application/json",
|
|
11560
|
-
...contentDetails
|
|
11561
|
-
});
|
|
11562
|
-
}
|
|
11563
|
-
};
|
|
11564
|
-
const getNodePosition = node => {
|
|
11565
|
-
return {
|
|
11566
|
-
start: node.start,
|
|
11567
|
-
end: node.end,
|
|
11568
|
-
line: node.loc.start.line,
|
|
11569
|
-
column: node.loc.start.column,
|
|
11570
|
-
lineEnd: node.loc.end.line,
|
|
11571
|
-
columnEnd: node.loc.end.column
|
|
11572
|
-
};
|
|
11573
|
-
};
|
|
11574
|
-
const getOriginalName = (path, name) => {
|
|
11575
|
-
const binding = path.scope.getBinding(name);
|
|
11576
|
-
if (!binding) {
|
|
11577
|
-
return name;
|
|
11578
|
-
}
|
|
11579
|
-
if (binding.path.type === "ImportSpecifier") {
|
|
11580
|
-
const importedName = binding.path.node.imported.name;
|
|
11581
|
-
if (name === importedName) {
|
|
11582
|
-
return name;
|
|
11583
|
-
}
|
|
11584
|
-
return getOriginalName(path, importedName);
|
|
11585
|
-
}
|
|
11586
|
-
if (binding.path.type === "VariableDeclarator") {
|
|
11587
|
-
const {
|
|
11588
|
-
node
|
|
11589
|
-
} = binding.path;
|
|
11590
|
-
const {
|
|
11591
|
-
init
|
|
11592
|
-
} = node;
|
|
11593
|
-
if (init && init.type === "Identifier") {
|
|
11594
|
-
const previousName = init.name;
|
|
11595
|
-
return getOriginalName(path, previousName);
|
|
11596
|
-
}
|
|
11597
|
-
if (node.id && node.id.type === "Identifier") {
|
|
11598
|
-
const {
|
|
11599
|
-
constantViolations
|
|
11600
|
-
} = binding;
|
|
11601
|
-
if (constantViolations && constantViolations.length > 0) {
|
|
11602
|
-
const lastViolation = constantViolations[constantViolations.length - 1];
|
|
11603
|
-
if (lastViolation && lastViolation.node.type === "AssignmentExpression" && lastViolation.node.right.type === "MemberExpression" && lastViolation.node.right.property.type === "Identifier") {
|
|
11604
|
-
return lastViolation.node.right.property.name;
|
|
11605
|
-
}
|
|
11606
|
-
}
|
|
11607
|
-
}
|
|
11608
|
-
}
|
|
11609
|
-
return name;
|
|
11610
|
-
};
|
|
11611
|
-
const getTypePropertyNode = node => {
|
|
11612
|
-
if (node.type !== "ObjectExpression") {
|
|
11613
|
-
return null;
|
|
11614
|
-
}
|
|
11615
|
-
const {
|
|
11616
|
-
properties
|
|
11617
|
-
} = node;
|
|
11618
|
-
return properties.find(property => {
|
|
11619
|
-
return property.type === "ObjectProperty" && property.key.type === "Identifier" && property.key.name === "type";
|
|
11620
|
-
});
|
|
11621
|
-
};
|
|
11622
|
-
|
|
11623
|
-
const jsenvPluginDataUrls = () => {
|
|
11624
|
-
return {
|
|
11625
|
-
name: "jsenv:data_urls",
|
|
11626
|
-
appliesDuring: "*",
|
|
11627
|
-
resolveUrl: reference => {
|
|
11628
|
-
if (!reference.specifier.startsWith("data:")) {
|
|
11629
|
-
return null;
|
|
11630
|
-
}
|
|
11631
|
-
return reference.specifier;
|
|
11632
|
-
},
|
|
11633
|
-
fetchUrlContent: urlInfo => {
|
|
11634
|
-
if (!urlInfo.url.startsWith("data:")) {
|
|
11635
|
-
return null;
|
|
11636
|
-
}
|
|
11637
|
-
const {
|
|
11638
|
-
contentType,
|
|
11639
|
-
base64Flag,
|
|
11640
|
-
data: urlData
|
|
11641
|
-
} = DATA_URL.parse(urlInfo.url);
|
|
11642
|
-
urlInfo.data.base64Flag = base64Flag;
|
|
11643
|
-
return {
|
|
11644
|
-
content: contentFromUrlData({
|
|
11645
|
-
contentType,
|
|
11646
|
-
base64Flag,
|
|
11647
|
-
urlData
|
|
11648
|
-
}),
|
|
11649
|
-
contentType
|
|
11650
|
-
};
|
|
11651
|
-
},
|
|
11652
|
-
formatUrl: (reference, context) => {
|
|
11653
|
-
if (!reference.generatedUrl.startsWith("data:")) {
|
|
11654
|
-
return null;
|
|
11655
|
-
}
|
|
11656
|
-
if (reference.type === "sourcemap_comment") {
|
|
11657
|
-
return null;
|
|
11658
|
-
}
|
|
11659
|
-
return (async () => {
|
|
11660
|
-
const urlInfo = context.urlGraph.getUrlInfo(reference.url);
|
|
11661
|
-
await context.cook(urlInfo, {
|
|
11662
|
-
reference
|
|
11335
|
+
contentType: scriptUrlInfo.contentType
|
|
11336
|
+
});
|
|
11337
|
+
mutations.push(() => {
|
|
11338
|
+
setHtmlNodeAttributes(scriptNode, {
|
|
11339
|
+
"inlined-from-src": src,
|
|
11340
|
+
"src": undefined,
|
|
11341
|
+
"crossorigin": undefined,
|
|
11342
|
+
"integrity": undefined,
|
|
11343
|
+
"jsenv-inlined-by": "jsenv:inlining_into_html"
|
|
11344
|
+
});
|
|
11345
|
+
setHtmlNodeText(scriptNode, scriptUrlInfo.content, {
|
|
11346
|
+
indentation: "auto"
|
|
11347
|
+
});
|
|
11348
|
+
});
|
|
11349
|
+
});
|
|
11350
|
+
};
|
|
11351
|
+
visitHtmlNodes(htmlAst, {
|
|
11352
|
+
link: linkNode => {
|
|
11353
|
+
const rel = getHtmlNodeAttribute(linkNode, "rel");
|
|
11354
|
+
if (rel !== "stylesheet") {
|
|
11355
|
+
return;
|
|
11356
|
+
}
|
|
11357
|
+
const href = getHtmlNodeAttribute(linkNode, "href");
|
|
11358
|
+
if (!href) {
|
|
11359
|
+
return;
|
|
11360
|
+
}
|
|
11361
|
+
onStyleSheet(linkNode, {
|
|
11362
|
+
href
|
|
11363
|
+
});
|
|
11364
|
+
},
|
|
11365
|
+
script: scriptNode => {
|
|
11366
|
+
const {
|
|
11367
|
+
type
|
|
11368
|
+
} = analyzeScriptNode(scriptNode);
|
|
11369
|
+
const scriptNodeText = getHtmlNodeText(scriptNode);
|
|
11370
|
+
if (scriptNodeText) {
|
|
11371
|
+
return;
|
|
11372
|
+
}
|
|
11373
|
+
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
11374
|
+
if (!src) {
|
|
11375
|
+
return;
|
|
11376
|
+
}
|
|
11377
|
+
onScriptWithSrc(scriptNode, {
|
|
11378
|
+
type,
|
|
11379
|
+
src
|
|
11380
|
+
});
|
|
11381
|
+
}
|
|
11663
11382
|
});
|
|
11664
|
-
if (
|
|
11665
|
-
|
|
11383
|
+
if (actions.length > 0) {
|
|
11384
|
+
await Promise.all(actions.map(action => action()));
|
|
11666
11385
|
}
|
|
11667
|
-
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11671
|
-
});
|
|
11672
|
-
return specifier;
|
|
11673
|
-
})();
|
|
11386
|
+
mutations.forEach(mutation => mutation());
|
|
11387
|
+
const htmlModified = stringifyHtmlAst(htmlAst);
|
|
11388
|
+
return htmlModified;
|
|
11389
|
+
}
|
|
11674
11390
|
}
|
|
11675
11391
|
};
|
|
11676
11392
|
};
|
|
11677
|
-
const contentFromUrlData = ({
|
|
11678
|
-
contentType,
|
|
11679
|
-
base64Flag,
|
|
11680
|
-
urlData
|
|
11681
|
-
}) => {
|
|
11682
|
-
if (CONTENT_TYPE.isTextual(contentType)) {
|
|
11683
|
-
if (base64Flag) {
|
|
11684
|
-
return base64ToString(urlData);
|
|
11685
|
-
}
|
|
11686
|
-
return urlData;
|
|
11687
|
-
}
|
|
11688
|
-
if (base64Flag) {
|
|
11689
|
-
return base64ToBuffer(urlData);
|
|
11690
|
-
}
|
|
11691
|
-
return Buffer.from(urlData);
|
|
11692
|
-
};
|
|
11693
|
-
const base64ToBuffer = base64String => Buffer.from(base64String, "base64");
|
|
11694
|
-
const base64ToString = base64String => Buffer.from(base64String, "base64").toString("utf8");
|
|
11695
|
-
const dataToBase64 = data => Buffer.from(data).toString("base64");
|
|
11696
11393
|
|
|
11697
|
-
const
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
allowEscapeForVersioning = false
|
|
11701
|
-
} = {}) => {
|
|
11702
|
-
return [...(fetchInlineUrls ? [jsenvPluginInlineContentFetcher()] : []), jsenvPluginHtmlInlineContentAnalysis({
|
|
11703
|
-
analyzeConvertedScripts
|
|
11704
|
-
}), jsenvPluginJsInlineContentAnalysis({
|
|
11705
|
-
allowEscapeForVersioning
|
|
11706
|
-
}), jsenvPluginDataUrls()];
|
|
11707
|
-
};
|
|
11708
|
-
const jsenvPluginInlineContentFetcher = () => {
|
|
11709
|
-
return {
|
|
11710
|
-
name: "jsenv:inline_content_fetcher",
|
|
11394
|
+
const jsenvPluginInlining = () => {
|
|
11395
|
+
return [{
|
|
11396
|
+
name: "jsenv:inlining",
|
|
11711
11397
|
appliesDuring: "*",
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11398
|
+
redirectReference: reference => {
|
|
11399
|
+
const {
|
|
11400
|
+
searchParams
|
|
11401
|
+
} = reference;
|
|
11402
|
+
if (searchParams.has("inline")) {
|
|
11403
|
+
const urlObject = new URL(reference.url);
|
|
11404
|
+
urlObject.searchParams.delete("inline");
|
|
11405
|
+
return urlObject.href;
|
|
11715
11406
|
}
|
|
11716
|
-
return
|
|
11717
|
-
// we want to fetch the original content otherwise we might re-cook
|
|
11718
|
-
// content already cooked
|
|
11719
|
-
content: urlInfo.originalContent,
|
|
11720
|
-
contentType: urlInfo.contentType
|
|
11721
|
-
};
|
|
11407
|
+
return null;
|
|
11722
11408
|
}
|
|
11723
|
-
};
|
|
11409
|
+
}, jsenvPluginInliningAsDataUrl(), jsenvPluginInliningIntoHtml()];
|
|
11724
11410
|
};
|
|
11725
11411
|
|
|
11726
11412
|
const requireFromJsenv = createRequire(import.meta.url);
|
|
@@ -15460,6 +15146,7 @@ const babelPluginRelativeImports = babel => {
|
|
|
15460
15146
|
* - propagate "?js_module_fallback" query string param on urls
|
|
15461
15147
|
* - perform conversion from js module to js classic when url uses "?js_module_fallback"
|
|
15462
15148
|
*/
|
|
15149
|
+
|
|
15463
15150
|
const jsenvPluginJsModuleConversion = ({
|
|
15464
15151
|
systemJsInjection,
|
|
15465
15152
|
systemJsClientFileUrl,
|
|
@@ -15499,7 +15186,7 @@ const jsenvPluginJsModuleConversion = ({
|
|
|
15499
15186
|
return {
|
|
15500
15187
|
name: "jsenv:js_module_conversion",
|
|
15501
15188
|
appliesDuring: "*",
|
|
15502
|
-
|
|
15189
|
+
redirectReference: (reference, context) => {
|
|
15503
15190
|
if (reference.searchParams.has("js_module_fallback")) {
|
|
15504
15191
|
markAsJsClassicProxy(reference);
|
|
15505
15192
|
return null;
|
|
@@ -15570,6 +15257,7 @@ const jsenvPluginJsModuleConversion = ({
|
|
|
15570
15257
|
* - js inside <script type="module"> is transformed into classic js
|
|
15571
15258
|
* - <link rel="modulepreload"> are converted to <link rel="preload">
|
|
15572
15259
|
*/
|
|
15260
|
+
|
|
15573
15261
|
const jsenvPluginJsModuleFallbackInsideHtml = ({
|
|
15574
15262
|
systemJsInjection,
|
|
15575
15263
|
systemJsClientFileUrl
|
|
@@ -15582,7 +15270,7 @@ const jsenvPluginJsModuleFallbackInsideHtml = ({
|
|
|
15582
15270
|
return {
|
|
15583
15271
|
name: "jsenv:js_module_fallback_inside_html",
|
|
15584
15272
|
appliesDuring: "*",
|
|
15585
|
-
|
|
15273
|
+
redirectReference: {
|
|
15586
15274
|
link_href: (reference, context) => {
|
|
15587
15275
|
if (context.systemJsTranspilation && reference.subtype === "modulepreload") {
|
|
15588
15276
|
return turnIntoJsClassicProxy(reference);
|
|
@@ -15737,11 +15425,10 @@ const jsenvPluginJsModuleFallbackInsideHtml = ({
|
|
|
15737
15425
|
});
|
|
15738
15426
|
}
|
|
15739
15427
|
}
|
|
15740
|
-
if (mutations.length === 0) {
|
|
15741
|
-
return null;
|
|
15742
|
-
}
|
|
15743
15428
|
await Promise.all(mutations.map(mutation => mutation()));
|
|
15744
|
-
return stringifyHtmlAst(htmlAst
|
|
15429
|
+
return stringifyHtmlAst(htmlAst, {
|
|
15430
|
+
cleanupPositionAttributes: context.dev
|
|
15431
|
+
});
|
|
15745
15432
|
}
|
|
15746
15433
|
}
|
|
15747
15434
|
};
|
|
@@ -15771,6 +15458,7 @@ const isExpectingJsModule = reference => {
|
|
|
15771
15458
|
* transformed into
|
|
15772
15459
|
* new SharedWorker("shared_worker.js?js_module_fallback", { type: "classic" })
|
|
15773
15460
|
*/
|
|
15461
|
+
|
|
15774
15462
|
const jsenvPluginJsModuleFallbackOnWorkers = () => {
|
|
15775
15463
|
const turnIntoJsClassicProxy = reference => {
|
|
15776
15464
|
reference.mutation = magicSource => {
|
|
@@ -15787,7 +15475,7 @@ const jsenvPluginJsModuleFallbackOnWorkers = () => {
|
|
|
15787
15475
|
return {
|
|
15788
15476
|
name: "jsenv:js_module_fallback_on_workers",
|
|
15789
15477
|
appliesDuring: "*",
|
|
15790
|
-
|
|
15478
|
+
redirectReference: {
|
|
15791
15479
|
js_url: (reference, context) => {
|
|
15792
15480
|
if (reference.expectedType !== "js_module") {
|
|
15793
15481
|
return null;
|
|
@@ -15928,6 +15616,7 @@ const pathnameToParentPathname = pathname => {
|
|
|
15928
15616
|
};
|
|
15929
15617
|
|
|
15930
15618
|
// could be useful: https://url.spec.whatwg.org/#url-miscellaneous
|
|
15619
|
+
|
|
15931
15620
|
const resolveUrl = (specifier, baseUrl) => {
|
|
15932
15621
|
if (baseUrl) {
|
|
15933
15622
|
if (typeof baseUrl !== "string") {
|
|
@@ -16459,6 +16148,7 @@ const applyDefaultExtension = ({
|
|
|
16459
16148
|
* -> The importmap resolution implemented here takes a shortcut and does the following:
|
|
16460
16149
|
* - All importmap found are merged into a single one that is applied to every import specifiers
|
|
16461
16150
|
*/
|
|
16151
|
+
|
|
16462
16152
|
const jsenvPluginImportmap = () => {
|
|
16463
16153
|
let finalImportmap = null;
|
|
16464
16154
|
const importmaps = {};
|
|
@@ -16478,7 +16168,7 @@ const jsenvPluginImportmap = () => {
|
|
|
16478
16168
|
return {
|
|
16479
16169
|
name: "jsenv:importmap",
|
|
16480
16170
|
appliesDuring: "*",
|
|
16481
|
-
|
|
16171
|
+
resolveReference: {
|
|
16482
16172
|
js_import: reference => {
|
|
16483
16173
|
if (!finalImportmap) {
|
|
16484
16174
|
return null;
|
|
@@ -16636,6 +16326,20 @@ const jsenvPluginImportmap = () => {
|
|
|
16636
16326
|
};
|
|
16637
16327
|
};
|
|
16638
16328
|
|
|
16329
|
+
const urlTypeFromReference = (reference, context) => {
|
|
16330
|
+
if (reference.type === "sourcemap_comment") {
|
|
16331
|
+
return "sourcemap";
|
|
16332
|
+
}
|
|
16333
|
+
if (reference.injected) {
|
|
16334
|
+
return reference.expectedType;
|
|
16335
|
+
}
|
|
16336
|
+
const parentUrlInfo = context.urlGraph.getUrlInfo(reference.parentUrl);
|
|
16337
|
+
if (parentUrlInfo) {
|
|
16338
|
+
return parentUrlInfo.type;
|
|
16339
|
+
}
|
|
16340
|
+
return "entry_point";
|
|
16341
|
+
};
|
|
16342
|
+
|
|
16639
16343
|
const isSpecifierForNodeBuiltin = specifier => {
|
|
16640
16344
|
return specifier.startsWith("node:") || NODE_BUILTIN_MODULE_SPECIFIERS.includes(specifier);
|
|
16641
16345
|
};
|
|
@@ -17591,6 +17295,7 @@ const getExtensionsToTry = (magicExtensions, importer) => {
|
|
|
17591
17295
|
* if that comes from node resolution or anything else (not even magic resolution)
|
|
17592
17296
|
* it should likely be an other plugin happening after the others
|
|
17593
17297
|
*/
|
|
17298
|
+
|
|
17594
17299
|
const createNodeEsmResolver = ({
|
|
17595
17300
|
runtimeCompat,
|
|
17596
17301
|
packageConditions,
|
|
@@ -17603,6 +17308,16 @@ const createNodeEsmResolver = ({
|
|
|
17603
17308
|
if (reference.type === "package_json") {
|
|
17604
17309
|
return reference.specifier;
|
|
17605
17310
|
}
|
|
17311
|
+
if (reference.specifier === "/") {
|
|
17312
|
+
const {
|
|
17313
|
+
mainFilePath,
|
|
17314
|
+
rootDirectoryUrl
|
|
17315
|
+
} = context;
|
|
17316
|
+
return String(new URL(mainFilePath, rootDirectoryUrl));
|
|
17317
|
+
}
|
|
17318
|
+
if (reference.specifier[0] === "/") {
|
|
17319
|
+
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl).href;
|
|
17320
|
+
}
|
|
17606
17321
|
const parentUrl = reference.baseUrl || reference.parentUrl;
|
|
17607
17322
|
if (!parentUrl.startsWith("file:")) {
|
|
17608
17323
|
return new URL(reference.specifier, parentUrl).href;
|
|
@@ -17681,126 +17396,64 @@ const addRelationshipWithPackageJson = ({
|
|
|
17681
17396
|
}
|
|
17682
17397
|
};
|
|
17683
17398
|
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
* - A custom plugin implements a resolveUrl hook returning something
|
|
17687
|
-
* - The reference.type is "filesystem" -> it is handled by jsenv_plugin_file_urls.js
|
|
17688
|
-
*
|
|
17689
|
-
* By default node esm resolution applies inside js modules
|
|
17690
|
-
* and the rest uses the web standard url resolution (new URL):
|
|
17691
|
-
* - "http_request"
|
|
17692
|
-
* - "entry_point"
|
|
17693
|
-
* - "link_href"
|
|
17694
|
-
* - "style"
|
|
17695
|
-
* - "script"
|
|
17696
|
-
* - "a_href"
|
|
17697
|
-
* - "iframe_src
|
|
17698
|
-
* - "img_src"
|
|
17699
|
-
* - "img_srcset"
|
|
17700
|
-
* - "source_src"
|
|
17701
|
-
* - "source_srcset"
|
|
17702
|
-
* - "image_href"
|
|
17703
|
-
* - "use_href"
|
|
17704
|
-
* - "css_@import"
|
|
17705
|
-
* - "css_url"
|
|
17706
|
-
* - "js_import"
|
|
17707
|
-
* - "js_import_script"
|
|
17708
|
-
* - "js_url"
|
|
17709
|
-
* - "js_inline_content"
|
|
17710
|
-
* - "sourcemap_comment"
|
|
17711
|
-
* - "webmanifest_icon_src"
|
|
17712
|
-
* - "package_json"
|
|
17713
|
-
*/
|
|
17714
|
-
const jsenvPluginUrlResolution = ({
|
|
17715
|
-
runtimeCompat,
|
|
17716
|
-
defaultFileUrl,
|
|
17717
|
-
urlResolution
|
|
17718
|
-
}) => {
|
|
17719
|
-
const resolveUrlUsingWebResolution = reference => {
|
|
17720
|
-
return new URL(reference.specifier,
|
|
17721
|
-
// baseUrl happens second argument to new URL() is different from
|
|
17722
|
-
// import.meta.url or document.currentScript.src
|
|
17723
|
-
reference.baseUrl || reference.parentUrl).href;
|
|
17724
|
-
};
|
|
17399
|
+
const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
|
|
17400
|
+
let nodeEsmResolverDefault;
|
|
17725
17401
|
const resolvers = {};
|
|
17726
|
-
Object.keys(
|
|
17727
|
-
const
|
|
17728
|
-
if (
|
|
17729
|
-
|
|
17730
|
-
}
|
|
17731
|
-
|
|
17732
|
-
|
|
17733
|
-
node_esm,
|
|
17734
|
-
...rest
|
|
17735
|
-
} = resolver;
|
|
17736
|
-
const unexpectedKeys = Object.keys(rest);
|
|
17737
|
-
if (unexpectedKeys.length) {
|
|
17738
|
-
throw new TypeError(`${unexpectedKeys.join(",")}: there is no such configuration on "${urlType}"`);
|
|
17739
|
-
}
|
|
17740
|
-
if (node_esm === undefined) {
|
|
17741
|
-
node_esm = urlType === "js_import";
|
|
17742
|
-
}
|
|
17743
|
-
if (web === undefined) {
|
|
17744
|
-
web = true;
|
|
17745
|
-
}
|
|
17746
|
-
if (node_esm) {
|
|
17747
|
-
if (node_esm === true) node_esm = {};
|
|
17402
|
+
Object.keys(resolutionConfig).forEach(urlType => {
|
|
17403
|
+
const config = resolutionConfig[urlType];
|
|
17404
|
+
if (config === true) {
|
|
17405
|
+
resolvers[urlType] = (...args) => nodeEsmResolverDefault(...args);
|
|
17406
|
+
} else if (config === false) {
|
|
17407
|
+
resolvers[urlType] = () => null;
|
|
17408
|
+
} else if (typeof config === "object") {
|
|
17748
17409
|
const {
|
|
17410
|
+
runtimeCompat,
|
|
17749
17411
|
packageConditions,
|
|
17750
|
-
preservesSymlink
|
|
17751
|
-
|
|
17412
|
+
preservesSymlink,
|
|
17413
|
+
...rest
|
|
17414
|
+
} = config;
|
|
17415
|
+
const unexpectedKeys = Object.keys(rest);
|
|
17416
|
+
if (unexpectedKeys.length) {
|
|
17417
|
+
throw new TypeError(`${unexpectedKeys.join(",")}: there is no such configuration on "${urlType}"`);
|
|
17418
|
+
}
|
|
17752
17419
|
resolvers[urlType] = createNodeEsmResolver({
|
|
17753
17420
|
runtimeCompat,
|
|
17754
17421
|
packageConditions,
|
|
17755
17422
|
preservesSymlink
|
|
17756
17423
|
});
|
|
17757
|
-
} else
|
|
17758
|
-
|
|
17424
|
+
} else {
|
|
17425
|
+
throw new TypeError(`config must be true, false or an object, got ${config} on "${urlType}"`);
|
|
17759
17426
|
}
|
|
17760
17427
|
});
|
|
17761
|
-
const nodeEsmResolverDefault = createNodeEsmResolver({
|
|
17762
|
-
runtimeCompat,
|
|
17763
|
-
preservesSymlink: true
|
|
17764
|
-
});
|
|
17765
|
-
if (!resolvers.js_module) {
|
|
17766
|
-
resolvers.js_module = nodeEsmResolverDefault;
|
|
17767
|
-
}
|
|
17768
|
-
if (!resolvers.js_classic) {
|
|
17769
|
-
resolvers.js_classic = (reference, context) => {
|
|
17770
|
-
if (reference.subtype === "self_import_scripts_arg") {
|
|
17771
|
-
return nodeEsmResolverDefault(reference, context);
|
|
17772
|
-
}
|
|
17773
|
-
return resolveUrlUsingWebResolution(reference);
|
|
17774
|
-
};
|
|
17775
|
-
}
|
|
17776
|
-
if (!resolvers["*"]) {
|
|
17777
|
-
resolvers["*"] = resolveUrlUsingWebResolution;
|
|
17778
|
-
}
|
|
17779
17428
|
return {
|
|
17780
|
-
name: "jsenv:
|
|
17429
|
+
name: "jsenv:node_esm_resolution",
|
|
17781
17430
|
appliesDuring: "*",
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17788
|
-
}
|
|
17789
|
-
if (
|
|
17790
|
-
|
|
17431
|
+
init: ({
|
|
17432
|
+
runtimeCompat
|
|
17433
|
+
}) => {
|
|
17434
|
+
nodeEsmResolverDefault = createNodeEsmResolver({
|
|
17435
|
+
runtimeCompat,
|
|
17436
|
+
preservesSymlink: true
|
|
17437
|
+
});
|
|
17438
|
+
if (!resolvers.js_module) {
|
|
17439
|
+
resolvers.js_module = nodeEsmResolverDefault;
|
|
17791
17440
|
}
|
|
17792
|
-
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
17796
|
-
|
|
17797
|
-
|
|
17441
|
+
if (!resolvers.js_classic) {
|
|
17442
|
+
resolvers.js_classic = (reference, context) => {
|
|
17443
|
+
if (reference.subtype === "self_import_scripts_arg") {
|
|
17444
|
+
return nodeEsmResolverDefault(reference, context);
|
|
17445
|
+
}
|
|
17446
|
+
return null;
|
|
17447
|
+
};
|
|
17798
17448
|
}
|
|
17799
|
-
|
|
17800
|
-
|
|
17449
|
+
},
|
|
17450
|
+
resolveReference: (reference, context) => {
|
|
17451
|
+
const urlType = urlTypeFromReference(reference, context);
|
|
17452
|
+
const resolver = resolvers[urlType];
|
|
17453
|
+
return resolver ? resolver(reference, context) : null;
|
|
17801
17454
|
},
|
|
17802
17455
|
// when specifier is prefixed by "file:///@ignore/"
|
|
17803
|
-
// we return an empty js module
|
|
17456
|
+
// we return an empty js module
|
|
17804
17457
|
fetchUrlContent: urlInfo => {
|
|
17805
17458
|
if (urlInfo.url.startsWith("file:///@ignore/")) {
|
|
17806
17459
|
return {
|
|
@@ -17814,11 +17467,50 @@ const jsenvPluginUrlResolution = ({
|
|
|
17814
17467
|
};
|
|
17815
17468
|
};
|
|
17816
17469
|
|
|
17817
|
-
const
|
|
17470
|
+
const jsenvPluginWebResolution = (resolutionConfig = {}) => {
|
|
17471
|
+
const resolvers = {};
|
|
17472
|
+
const resolveUsingWebResolution = (reference, context) => {
|
|
17473
|
+
if (reference.specifier === "/") {
|
|
17474
|
+
const {
|
|
17475
|
+
mainFilePath,
|
|
17476
|
+
rootDirectoryUrl
|
|
17477
|
+
} = context;
|
|
17478
|
+
return String(new URL(mainFilePath, rootDirectoryUrl));
|
|
17479
|
+
}
|
|
17480
|
+
if (reference.specifier[0] === "/") {
|
|
17481
|
+
return new URL(reference.specifier.slice(1), context.rootDirectoryUrl).href;
|
|
17482
|
+
}
|
|
17483
|
+
return new URL(reference.specifier,
|
|
17484
|
+
// baseUrl happens second argument to new URL() is different from
|
|
17485
|
+
// import.meta.url or document.currentScript.src
|
|
17486
|
+
reference.baseUrl || reference.parentUrl).href;
|
|
17487
|
+
};
|
|
17488
|
+
Object.keys(resolutionConfig).forEach(urlType => {
|
|
17489
|
+
const config = resolutionConfig[urlType];
|
|
17490
|
+
if (config === true) {
|
|
17491
|
+
resolvers[urlType] = resolveUsingWebResolution;
|
|
17492
|
+
} else if (config === false) {
|
|
17493
|
+
resolvers[urlType] = () => null;
|
|
17494
|
+
} else {
|
|
17495
|
+
throw new TypeError(`config must be true or false, got ${config} on "${urlType}"`);
|
|
17496
|
+
}
|
|
17497
|
+
});
|
|
17498
|
+
return {
|
|
17499
|
+
name: "jsenv:web_resolution",
|
|
17500
|
+
appliesDuring: "*",
|
|
17501
|
+
resolveReference: (reference, context) => {
|
|
17502
|
+
const urlType = urlTypeFromReference(reference, context);
|
|
17503
|
+
const resolver = resolvers[urlType];
|
|
17504
|
+
return resolver ? resolver(reference, context) : resolveUsingWebResolution(reference, context);
|
|
17505
|
+
}
|
|
17506
|
+
};
|
|
17507
|
+
};
|
|
17508
|
+
|
|
17509
|
+
const jsenvPluginVersionSearchParam = () => {
|
|
17818
17510
|
return {
|
|
17819
|
-
name: "jsenv:
|
|
17511
|
+
name: "jsenv:version_search_param",
|
|
17820
17512
|
appliesDuring: "dev",
|
|
17821
|
-
|
|
17513
|
+
redirectReference: reference => {
|
|
17822
17514
|
// "v" search param goal is to enable long-term cache
|
|
17823
17515
|
// for server response headers
|
|
17824
17516
|
// it is also used by hmr to bypass browser cache
|
|
@@ -17834,7 +17526,7 @@ const jsenvPluginUrlVersion = () => {
|
|
|
17834
17526
|
}
|
|
17835
17527
|
return null;
|
|
17836
17528
|
},
|
|
17837
|
-
|
|
17529
|
+
transformReferenceSearchParams: reference => {
|
|
17838
17530
|
if (!reference.version) {
|
|
17839
17531
|
return null;
|
|
17840
17532
|
}
|
|
@@ -17857,7 +17549,7 @@ const jsenvPluginFileUrls = ({
|
|
|
17857
17549
|
return [{
|
|
17858
17550
|
name: "jsenv:file_url_resolution",
|
|
17859
17551
|
appliesDuring: "*",
|
|
17860
|
-
|
|
17552
|
+
redirectReference: reference => {
|
|
17861
17553
|
// http, https, data, about, ...
|
|
17862
17554
|
if (!reference.url.startsWith("file:")) {
|
|
17863
17555
|
return null;
|
|
@@ -17936,7 +17628,7 @@ const jsenvPluginFileUrls = ({
|
|
|
17936
17628
|
}, {
|
|
17937
17629
|
name: "jsenv:filesystem_resolution",
|
|
17938
17630
|
appliesDuring: "*",
|
|
17939
|
-
|
|
17631
|
+
resolveReference: {
|
|
17940
17632
|
filesystem: (reference, context) => {
|
|
17941
17633
|
const {
|
|
17942
17634
|
parentUrl
|
|
@@ -17952,14 +17644,14 @@ const jsenvPluginFileUrls = ({
|
|
|
17952
17644
|
// so absolute file urls needs to be relativized
|
|
17953
17645
|
// during build it's fine to use file:// urls
|
|
17954
17646
|
appliesDuring: "dev",
|
|
17955
|
-
|
|
17647
|
+
resolveReference: reference => {
|
|
17956
17648
|
if (reference.specifier.startsWith("/@fs/")) {
|
|
17957
17649
|
const fsRootRelativeUrl = reference.specifier.slice("/@fs/".length);
|
|
17958
17650
|
return `file:///${fsRootRelativeUrl}`;
|
|
17959
17651
|
}
|
|
17960
17652
|
return null;
|
|
17961
17653
|
},
|
|
17962
|
-
|
|
17654
|
+
formatReference: (reference, context) => {
|
|
17963
17655
|
if (!reference.generatedUrl.startsWith("file:")) {
|
|
17964
17656
|
return null;
|
|
17965
17657
|
}
|
|
@@ -18009,7 +17701,7 @@ const jsenvPluginHttpUrls = () => {
|
|
|
18009
17701
|
return {
|
|
18010
17702
|
name: "jsenv:http_urls",
|
|
18011
17703
|
appliesDuring: "*",
|
|
18012
|
-
|
|
17704
|
+
redirectReference: reference => {
|
|
18013
17705
|
if (reference.url.startsWith("http:") || reference.url.startsWith("https:")) {
|
|
18014
17706
|
reference.shouldHandle = false;
|
|
18015
17707
|
}
|
|
@@ -18056,6 +17748,7 @@ const jsenvPluginHttpUrls = () => {
|
|
|
18056
17748
|
* While dynamic import will work just fine
|
|
18057
17749
|
* and create a variable named "undefined"
|
|
18058
17750
|
*/
|
|
17751
|
+
|
|
18059
17752
|
const injectSupervisorIntoJs = async ({
|
|
18060
17753
|
webServer,
|
|
18061
17754
|
content,
|
|
@@ -18284,6 +17977,7 @@ const createSupervisionCall = ({
|
|
|
18284
17977
|
* -> No changes required on js source code, it's only the HTML that is modified
|
|
18285
17978
|
* - Also allow to catch syntax errors and export missing
|
|
18286
17979
|
*/
|
|
17980
|
+
|
|
18287
17981
|
const supervisorFileUrl$1 = new URL("./js/supervisor.js", import.meta.url).href;
|
|
18288
17982
|
const injectSupervisorIntoHTML = async ({
|
|
18289
17983
|
content,
|
|
@@ -18517,6 +18211,7 @@ const generateCodeToSuperviseScriptWithSrc = ({
|
|
|
18517
18211
|
/*
|
|
18518
18212
|
* This plugin provides a way for jsenv to know when js execution is done
|
|
18519
18213
|
*/
|
|
18214
|
+
|
|
18520
18215
|
const supervisorFileUrl = new URL("./js/supervisor.js", import.meta.url).href;
|
|
18521
18216
|
const jsenvPluginSupervisor = ({
|
|
18522
18217
|
logs = false,
|
|
@@ -18723,6 +18418,7 @@ const jsenvPluginSupervisor = ({
|
|
|
18723
18418
|
* - __dirname
|
|
18724
18419
|
* - global
|
|
18725
18420
|
*/
|
|
18421
|
+
|
|
18726
18422
|
const jsenvPluginCommonJsGlobals = () => {
|
|
18727
18423
|
const transformCommonJsGlobals = async (urlInfo, context) => {
|
|
18728
18424
|
if (!urlInfo.content.includes("process.env.NODE_ENV") && !urlInfo.content.includes("__filename") && !urlInfo.content.includes("__dirname")) {
|
|
@@ -18874,6 +18570,7 @@ const babelPluginMetadataExpressionPaths = (babel, {
|
|
|
18874
18570
|
* - left as is to be evaluated to undefined (import.meta.build but it's the dev server)
|
|
18875
18571
|
* - replaced by undefined (import.meta.dev but it's build; the goal is to ensure it's tree-shaked)
|
|
18876
18572
|
*/
|
|
18573
|
+
|
|
18877
18574
|
const jsenvPluginImportMetaScenarios = () => {
|
|
18878
18575
|
return {
|
|
18879
18576
|
name: "jsenv:import_meta_scenario",
|
|
@@ -19004,6 +18701,7 @@ const replacePlaceholders = (urlInfo, replacements) => {
|
|
|
19004
18701
|
* - __build__
|
|
19005
18702
|
* A global will be injected with true/false when needed
|
|
19006
18703
|
*/
|
|
18704
|
+
|
|
19007
18705
|
const jsenvPluginGlobalScenarios = () => {
|
|
19008
18706
|
const transformIfNeeded = (urlInfo, context) => {
|
|
19009
18707
|
return replacePlaceholders(urlInfo, {
|
|
@@ -19090,6 +18788,7 @@ const versionToBits = version => {
|
|
|
19090
18788
|
* do not support import assertions
|
|
19091
18789
|
* But for now (as it is simpler) we let the browser throw the error
|
|
19092
18790
|
*/
|
|
18791
|
+
|
|
19093
18792
|
const jsenvPluginImportAssertions = ({
|
|
19094
18793
|
json = "auto",
|
|
19095
18794
|
css = "auto",
|
|
@@ -19155,7 +18854,7 @@ const jsenvPluginImportAssertions = ({
|
|
|
19155
18854
|
transpilations.text = true;
|
|
19156
18855
|
}
|
|
19157
18856
|
},
|
|
19158
|
-
|
|
18857
|
+
redirectReference: (reference, context) => {
|
|
19159
18858
|
if (!reference.assert) {
|
|
19160
18859
|
return null;
|
|
19161
18860
|
}
|
|
@@ -19250,9 +18949,9 @@ const jsenvPluginAsModules = () => {
|
|
|
19250
18949
|
canUseTemplateString: true
|
|
19251
18950
|
});
|
|
19252
18951
|
return {
|
|
19253
|
-
content: `import
|
|
18952
|
+
content: `import ${JSON.stringify(inlineContentClientFileUrl)}
|
|
19254
18953
|
|
|
19255
|
-
const inlineContent = new
|
|
18954
|
+
const inlineContent = new __InlineContent__(${cssText}, { type: "text/css" })
|
|
19256
18955
|
const stylesheet = new CSSStyleSheet()
|
|
19257
18956
|
stylesheet.replaceSync(inlineContent.text)
|
|
19258
18957
|
export default stylesheet`,
|
|
@@ -19362,11 +19061,12 @@ const babelPluginReplaceTopLevelThis = () => {
|
|
|
19362
19061
|
* This plugin fix this issue by rewriting top level this into window
|
|
19363
19062
|
* and can be used like this for instance import("hls?as_js_module")
|
|
19364
19063
|
*/
|
|
19064
|
+
|
|
19365
19065
|
const jsenvPluginAsJsModule = () => {
|
|
19366
19066
|
return {
|
|
19367
19067
|
name: "jsenv:as_js_module",
|
|
19368
19068
|
appliesDuring: "*",
|
|
19369
|
-
|
|
19069
|
+
redirectReference: reference => {
|
|
19370
19070
|
if (reference.searchParams.has("as_js_module")) {
|
|
19371
19071
|
reference.expectedType = "js_module";
|
|
19372
19072
|
const filename = urlToFilename$1(reference.url);
|
|
@@ -20285,7 +19985,7 @@ const jsenvPluginBabel = ({
|
|
|
20285
19985
|
return {
|
|
20286
19986
|
name: "jsenv:babel",
|
|
20287
19987
|
appliesDuring: "*",
|
|
20288
|
-
|
|
19988
|
+
transformUrlContent: {
|
|
20289
19989
|
js_classic: transformWithBabel,
|
|
20290
19990
|
js_module: transformWithBabel
|
|
20291
19991
|
}
|
|
@@ -20427,6 +20127,7 @@ const jsenvPluginImportMetaResolve = () => {
|
|
|
20427
20127
|
* Anything that is not standard (import.meta.dev for instance) is outside the scope
|
|
20428
20128
|
* of this plugin
|
|
20429
20129
|
*/
|
|
20130
|
+
|
|
20430
20131
|
const jsenvPluginTranspilation = ({
|
|
20431
20132
|
importAssertions = true,
|
|
20432
20133
|
css = true,
|
|
@@ -20819,7 +20520,7 @@ const jsenvPluginHmr = () => {
|
|
|
20819
20520
|
return {
|
|
20820
20521
|
name: "jsenv:hmr",
|
|
20821
20522
|
appliesDuring: "dev",
|
|
20822
|
-
|
|
20523
|
+
redirectReference: reference => {
|
|
20823
20524
|
if (!reference.searchParams.has("hmr")) {
|
|
20824
20525
|
reference.data.hmr = false;
|
|
20825
20526
|
return null;
|
|
@@ -20834,7 +20535,7 @@ const jsenvPluginHmr = () => {
|
|
|
20834
20535
|
urlObject.searchParams.delete("v");
|
|
20835
20536
|
return urlObject.href;
|
|
20836
20537
|
},
|
|
20837
|
-
|
|
20538
|
+
transformReferenceSearchParams: (reference, context) => {
|
|
20838
20539
|
if (reference.type === "package_json") {
|
|
20839
20540
|
// maybe the if above shoulb be .isImplicit but it's just a detail anyway
|
|
20840
20541
|
return null;
|
|
@@ -21137,72 +20838,6 @@ const jsenvPluginCacheControl = ({
|
|
|
21137
20838
|
};
|
|
21138
20839
|
const SECONDS_IN_30_DAYS$1 = 60 * 60 * 24 * 30;
|
|
21139
20840
|
|
|
21140
|
-
const explorerHtmlFileUrl = String(new URL("./html/explorer.html", import.meta.url));
|
|
21141
|
-
const jsenvPluginExplorer = ({
|
|
21142
|
-
groups = {
|
|
21143
|
-
src: {
|
|
21144
|
-
"./**/*.html": true,
|
|
21145
|
-
"./**/*.test.html": false
|
|
21146
|
-
},
|
|
21147
|
-
tests: {
|
|
21148
|
-
"./**/*.test.html": true
|
|
21149
|
-
}
|
|
21150
|
-
}
|
|
21151
|
-
}) => {
|
|
21152
|
-
const faviconClientFileUrl = new URL("./other/jsenv.png", import.meta.url);
|
|
21153
|
-
return {
|
|
21154
|
-
name: "jsenv:explorer",
|
|
21155
|
-
appliesDuring: "dev",
|
|
21156
|
-
transformUrlContent: {
|
|
21157
|
-
html: async (urlInfo, context) => {
|
|
21158
|
-
if (urlInfo.url !== explorerHtmlFileUrl) {
|
|
21159
|
-
return null;
|
|
21160
|
-
}
|
|
21161
|
-
let html = urlInfo.content;
|
|
21162
|
-
if (html.includes("ignore:FAVICON_HREF")) {
|
|
21163
|
-
html = html.replace("ignore:FAVICON_HREF", DATA_URL.stringify({
|
|
21164
|
-
contentType: CONTENT_TYPE.fromUrlExtension(faviconClientFileUrl),
|
|
21165
|
-
base64Flag: true,
|
|
21166
|
-
data: readFileSync$1(new URL(faviconClientFileUrl)).toString("base64")
|
|
21167
|
-
}));
|
|
21168
|
-
}
|
|
21169
|
-
if (html.includes("SERVER_PARAMS")) {
|
|
21170
|
-
const associationsForExplorable = {};
|
|
21171
|
-
Object.keys(groups).forEach(groupName => {
|
|
21172
|
-
const groupConfig = groups[groupName];
|
|
21173
|
-
associationsForExplorable[groupName] = {
|
|
21174
|
-
"**/.jsenv/": false,
|
|
21175
|
-
// avoid visting .jsenv directory in jsenv itself
|
|
21176
|
-
...groupConfig
|
|
21177
|
-
};
|
|
21178
|
-
});
|
|
21179
|
-
const matchingFileResultArray = await collectFiles({
|
|
21180
|
-
directoryUrl: context.rootDirectoryUrl,
|
|
21181
|
-
associations: associationsForExplorable,
|
|
21182
|
-
predicate: meta => Object.keys(meta).some(group => Boolean(meta[group]))
|
|
21183
|
-
});
|
|
21184
|
-
const files = matchingFileResultArray.map(({
|
|
21185
|
-
relativeUrl,
|
|
21186
|
-
meta
|
|
21187
|
-
}) => ({
|
|
21188
|
-
relativeUrl,
|
|
21189
|
-
meta
|
|
21190
|
-
}));
|
|
21191
|
-
html = html.replace("SERVER_PARAMS", JSON.stringify({
|
|
21192
|
-
rootDirectoryUrl: context.rootDirectoryUrl,
|
|
21193
|
-
groups,
|
|
21194
|
-
files
|
|
21195
|
-
}, null, " "));
|
|
21196
|
-
Object.assign(urlInfo.headers, {
|
|
21197
|
-
"cache-control": "no-store"
|
|
21198
|
-
});
|
|
21199
|
-
}
|
|
21200
|
-
return html;
|
|
21201
|
-
}
|
|
21202
|
-
}
|
|
21203
|
-
};
|
|
21204
|
-
};
|
|
21205
|
-
|
|
21206
20841
|
const jsenvPluginRibbon = ({
|
|
21207
20842
|
rootDirectoryUrl,
|
|
21208
20843
|
htmlInclude = "/**/*.html"
|
|
@@ -21255,10 +20890,10 @@ injectRibbon(${paramsJson});`
|
|
|
21255
20890
|
|
|
21256
20891
|
const getCorePlugins = ({
|
|
21257
20892
|
rootDirectoryUrl,
|
|
21258
|
-
defaultFileUrl,
|
|
21259
20893
|
runtimeCompat,
|
|
21260
|
-
|
|
21261
|
-
|
|
20894
|
+
referenceAnalysis = {},
|
|
20895
|
+
nodeEsmResolution = {},
|
|
20896
|
+
webResolution = {},
|
|
21262
20897
|
fileSystemMagicRedirection,
|
|
21263
20898
|
directoryReferenceAllowed,
|
|
21264
20899
|
supervisor,
|
|
@@ -21267,14 +20902,10 @@ const getCorePlugins = ({
|
|
|
21267
20902
|
clientAutoreload = false,
|
|
21268
20903
|
clientFileChangeCallbackList,
|
|
21269
20904
|
clientFilesPruneCallbackList,
|
|
21270
|
-
explorer,
|
|
21271
20905
|
cacheControl,
|
|
21272
20906
|
scenarioPlaceholders = true,
|
|
21273
20907
|
ribbon = true
|
|
21274
20908
|
} = {}) => {
|
|
21275
|
-
if (explorer === true) {
|
|
21276
|
-
explorer = {};
|
|
21277
|
-
}
|
|
21278
20909
|
if (cacheControl === true) {
|
|
21279
20910
|
cacheControl = {};
|
|
21280
20911
|
}
|
|
@@ -21290,30 +20921,25 @@ const getCorePlugins = ({
|
|
|
21290
20921
|
if (ribbon === true) {
|
|
21291
20922
|
ribbon = {};
|
|
21292
20923
|
}
|
|
21293
|
-
return [
|
|
21294
|
-
rootDirectoryUrl,
|
|
21295
|
-
...urlAnalysis
|
|
21296
|
-
}), jsenvPluginTranspilation(transpilation), jsenvPluginImportmap(),
|
|
21297
|
-
// before node esm to handle bare specifiers
|
|
21298
|
-
// + before node esm to handle importmap before inline content
|
|
21299
|
-
jsenvPluginInlineContentAnalysis(),
|
|
21300
|
-
// before "file urls" to resolve and load inline urls
|
|
21301
|
-
...(inlining ? [jsenvPluginInlining()] : []), ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []),
|
|
20924
|
+
return [jsenvPluginReferenceAnalysis(referenceAnalysis), jsenvPluginTranspilation(transpilation), jsenvPluginImportmap(), ...(inlining ? [jsenvPluginInlining()] : []), ...(supervisor ? [jsenvPluginSupervisor(supervisor)] : []),
|
|
21302
20925
|
// after inline as it needs inline script to be cooked
|
|
20926
|
+
|
|
20927
|
+
/* When resolving references the following applies by default:
|
|
20928
|
+
- http urls are resolved by jsenvPluginHttpUrls
|
|
20929
|
+
- reference.type === "filesystem" -> resolved by jsenv_plugin_file_urls.js
|
|
20930
|
+
- reference inside a js module -> resolved by node esm
|
|
20931
|
+
- All the rest uses web standard url resolution
|
|
20932
|
+
*/
|
|
21303
20933
|
jsenvPluginFileUrls({
|
|
21304
20934
|
directoryReferenceAllowed,
|
|
21305
20935
|
...fileSystemMagicRedirection
|
|
21306
|
-
}), jsenvPluginHttpUrls(),
|
|
21307
|
-
runtimeCompat,
|
|
21308
|
-
defaultFileUrl,
|
|
21309
|
-
urlResolution
|
|
21310
|
-
}), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []), jsenvPluginNodeRuntime({
|
|
20936
|
+
}), jsenvPluginHttpUrls(), ...(nodeEsmResolution ? [jsenvPluginNodeEsmResolution(nodeEsmResolution)] : []), jsenvPluginWebResolution(webResolution), jsenvPluginVersionSearchParam(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), ...(scenarioPlaceholders ? [jsenvPluginGlobalScenarios()] : []), jsenvPluginNodeRuntime({
|
|
21311
20937
|
runtimeCompat
|
|
21312
20938
|
}), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({
|
|
21313
20939
|
...clientAutoreload,
|
|
21314
20940
|
clientFileChangeCallbackList,
|
|
21315
20941
|
clientFilesPruneCallbackList
|
|
21316
|
-
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(
|
|
20942
|
+
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(ribbon ? [jsenvPluginRibbon({
|
|
21317
20943
|
rootDirectoryUrl,
|
|
21318
20944
|
...ribbon
|
|
21319
20945
|
})] : [])];
|
|
@@ -21522,6 +21148,7 @@ const determineDirectoryPath = ({
|
|
|
21522
21148
|
};
|
|
21523
21149
|
|
|
21524
21150
|
// https://bundlers.tooling.report/hashing/avoid-cascade/
|
|
21151
|
+
|
|
21525
21152
|
const injectVersionMappingsAsGlobal = async ({
|
|
21526
21153
|
urlInfo,
|
|
21527
21154
|
kitchen,
|
|
@@ -21650,6 +21277,7 @@ const createVersionGenerator = () => {
|
|
|
21650
21277
|
* - injecting urls into service workers
|
|
21651
21278
|
*/
|
|
21652
21279
|
|
|
21280
|
+
|
|
21653
21281
|
// default runtimeCompat corresponds to
|
|
21654
21282
|
// "we can keep <script type="module"> intact":
|
|
21655
21283
|
// so script_type_module + dynamic_import + import_meta
|
|
@@ -21669,11 +21297,11 @@ const defaultRuntimeCompat = {
|
|
|
21669
21297
|
* @param {Object} buildParameters
|
|
21670
21298
|
* @param {string|url} buildParameters.sourceDirectoryUrl
|
|
21671
21299
|
* Directory containing source files
|
|
21300
|
+
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
21301
|
+
* Directory where optimized files will be written
|
|
21672
21302
|
* @param {object} buildParameters.entryPoints
|
|
21673
21303
|
* Object where keys are paths to source files and values are their future name in the build directory.
|
|
21674
21304
|
* Keys are relative to sourceDirectoryUrl
|
|
21675
|
-
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
21676
|
-
* Directory where optimized files will be written
|
|
21677
21305
|
* @param {object} buildParameters.runtimeCompat
|
|
21678
21306
|
* Code generated will be compatible with these runtimes
|
|
21679
21307
|
* @param {string} [buildParameters.assetsDirectory=""]
|
|
@@ -21699,16 +21327,15 @@ const build = async ({
|
|
|
21699
21327
|
handleSIGINT = true,
|
|
21700
21328
|
logLevel = "info",
|
|
21701
21329
|
sourceDirectoryUrl,
|
|
21702
|
-
entryPoints = {},
|
|
21703
21330
|
buildDirectoryUrl,
|
|
21331
|
+
entryPoints = {},
|
|
21704
21332
|
assetsDirectory = "",
|
|
21705
21333
|
runtimeCompat = defaultRuntimeCompat,
|
|
21706
21334
|
base = runtimeCompat.node ? "./" : "/",
|
|
21707
21335
|
plugins = [],
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
urlResolution,
|
|
21336
|
+
referenceAnalysis = {},
|
|
21337
|
+
nodeEsmResolution,
|
|
21338
|
+
webResolution,
|
|
21712
21339
|
fileSystemMagicRedirection,
|
|
21713
21340
|
directoryReferenceAllowed,
|
|
21714
21341
|
scenarioPlaceholders,
|
|
@@ -21722,6 +21349,8 @@ const build = async ({
|
|
|
21722
21349
|
cooldownBetweenFileEvents,
|
|
21723
21350
|
watch = false,
|
|
21724
21351
|
directoryToClean,
|
|
21352
|
+
sourcemaps = "none",
|
|
21353
|
+
sourcemapsSourcesContent,
|
|
21725
21354
|
writeOnFileSystem = true,
|
|
21726
21355
|
outDirectoryUrl,
|
|
21727
21356
|
assetManifest = versioningMethod === "filename",
|
|
@@ -21844,23 +21473,24 @@ build ${entryPointKeys.length} entry points`);
|
|
|
21844
21473
|
...contextSharedDuringBuild,
|
|
21845
21474
|
plugins: [...plugins, {
|
|
21846
21475
|
appliesDuring: "build",
|
|
21847
|
-
|
|
21848
|
-
if (context.reference.original) {
|
|
21849
|
-
rawRedirections.set(context.reference.original.url, context.reference.url);
|
|
21850
|
-
}
|
|
21851
|
-
},
|
|
21852
|
-
formatUrl: reference => {
|
|
21476
|
+
formatReference: reference => {
|
|
21853
21477
|
if (!reference.shouldHandle) {
|
|
21854
21478
|
return `ignore:${reference.specifier}`;
|
|
21855
21479
|
}
|
|
21856
21480
|
return null;
|
|
21481
|
+
},
|
|
21482
|
+
fetchUrlContent: (urlInfo, context) => {
|
|
21483
|
+
if (context.reference.original) {
|
|
21484
|
+
rawRedirections.set(context.reference.original.url, context.reference.url);
|
|
21485
|
+
}
|
|
21857
21486
|
}
|
|
21858
21487
|
}, ...getCorePlugins({
|
|
21859
21488
|
rootDirectoryUrl: sourceDirectoryUrl,
|
|
21860
21489
|
urlGraph: rawGraph,
|
|
21861
21490
|
runtimeCompat,
|
|
21862
|
-
|
|
21863
|
-
|
|
21491
|
+
referenceAnalysis,
|
|
21492
|
+
nodeEsmResolution,
|
|
21493
|
+
webResolution,
|
|
21864
21494
|
fileSystemMagicRedirection,
|
|
21865
21495
|
directoryReferenceAllowed,
|
|
21866
21496
|
transpilation: {
|
|
@@ -21894,10 +21524,6 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21894
21524
|
const bundleUrlInfos = {};
|
|
21895
21525
|
const bundlers = {};
|
|
21896
21526
|
const finalGraph = createUrlGraph();
|
|
21897
|
-
const urlAnalysisPlugin = jsenvPluginUrlAnalysis({
|
|
21898
|
-
rootDirectoryUrl: sourceDirectoryUrl,
|
|
21899
|
-
...urlAnalysis
|
|
21900
|
-
});
|
|
21901
21527
|
const finalGraphKitchen = createKitchen({
|
|
21902
21528
|
logLevel,
|
|
21903
21529
|
rootDirectoryUrl: buildDirectoryUrl,
|
|
@@ -21905,14 +21531,15 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21905
21531
|
build: true,
|
|
21906
21532
|
runtimeCompat,
|
|
21907
21533
|
...contextSharedDuringBuild,
|
|
21908
|
-
plugins: [
|
|
21909
|
-
|
|
21910
|
-
}), jsenvPluginInlineContentAnalysis({
|
|
21534
|
+
plugins: [jsenvPluginReferenceAnalysis({
|
|
21535
|
+
...referenceAnalysis,
|
|
21911
21536
|
fetchInlineUrls: false
|
|
21537
|
+
}), ...(lineBreakNormalization ? [jsenvPluginLineBreakNormalization()] : []), jsenvPluginJsModuleFallback({
|
|
21538
|
+
systemJsInjection: true
|
|
21912
21539
|
}), jsenvPluginInlining(), {
|
|
21913
21540
|
name: "jsenv:build",
|
|
21914
21541
|
appliesDuring: "build",
|
|
21915
|
-
|
|
21542
|
+
resolveReference: reference => {
|
|
21916
21543
|
const getUrl = () => {
|
|
21917
21544
|
if (reference.type === "filesystem") {
|
|
21918
21545
|
const parentRawUrl = buildDirectoryRedirections.get(reference.parentUrl);
|
|
@@ -21930,8 +21557,8 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21930
21557
|
url = bundleInternalRedirections.get(url) || url;
|
|
21931
21558
|
return url;
|
|
21932
21559
|
},
|
|
21933
|
-
// redirecting
|
|
21934
|
-
|
|
21560
|
+
// redirecting references into the build directory
|
|
21561
|
+
redirectReference: reference => {
|
|
21935
21562
|
if (!reference.url.startsWith("file:")) {
|
|
21936
21563
|
return null;
|
|
21937
21564
|
}
|
|
@@ -21985,7 +21612,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21985
21612
|
const urlBeforeRedirect = reference.original.url;
|
|
21986
21613
|
const urlAfterRedirect = reference.url;
|
|
21987
21614
|
const isEntryPoint = reference.isEntryPoint || isWebWorkerEntryPointReference(reference);
|
|
21988
|
-
// the url info do not exists yet (it will be created after this "
|
|
21615
|
+
// the url info do not exists yet (it will be created after this "redirectReference" hook)
|
|
21989
21616
|
// And the content will be generated when url is cooked by url graph loader.
|
|
21990
21617
|
// Here we just want to reserve an url for that file
|
|
21991
21618
|
const urlInfo = {
|
|
@@ -22056,7 +21683,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22056
21683
|
});
|
|
22057
21684
|
return buildUrl;
|
|
22058
21685
|
},
|
|
22059
|
-
|
|
21686
|
+
formatReference: reference => {
|
|
22060
21687
|
if (!reference.generatedUrl.startsWith("file:")) {
|
|
22061
21688
|
if (!versioning && reference.generatedUrl.startsWith("ignore:")) {
|
|
22062
21689
|
return reference.generatedUrl.slice("ignore:".length);
|
|
@@ -22148,7 +21775,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22148
21775
|
}, {
|
|
22149
21776
|
name: "jsenv:optimize",
|
|
22150
21777
|
appliesDuring: "build",
|
|
22151
|
-
|
|
21778
|
+
transformUrlContent: async (urlInfo, context) => {
|
|
22152
21779
|
await rawGraphKitchen.pluginController.callAsyncHooks("optimizeUrlContent", urlInfo, context, async optimizeReturnValue => {
|
|
22153
21780
|
await finalGraphKitchen.urlInfoTransformer.applyFinalTransformations(urlInfo, optimizeReturnValue);
|
|
22154
21781
|
});
|
|
@@ -22412,6 +22039,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22412
22039
|
if (!versioning) {
|
|
22413
22040
|
break inject_version_in_urls;
|
|
22414
22041
|
}
|
|
22042
|
+
logger.debug("versioning start");
|
|
22415
22043
|
const versioningTask = createTaskLog("inject version in urls", {
|
|
22416
22044
|
disabled: logger.levels.debug || !logger.levels.info
|
|
22417
22045
|
});
|
|
@@ -22584,20 +22212,26 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22584
22212
|
build: true,
|
|
22585
22213
|
runtimeCompat,
|
|
22586
22214
|
...contextSharedDuringBuild,
|
|
22587
|
-
plugins: [
|
|
22215
|
+
plugins: [jsenvPluginReferenceAnalysis({
|
|
22216
|
+
...referenceAnalysis,
|
|
22588
22217
|
fetchInlineUrls: false,
|
|
22589
|
-
|
|
22218
|
+
inlineConvertedScript: true,
|
|
22590
22219
|
// to be able to version their urls
|
|
22591
22220
|
allowEscapeForVersioning: true
|
|
22592
22221
|
}), {
|
|
22593
22222
|
name: "jsenv:versioning",
|
|
22594
22223
|
appliesDuring: "build",
|
|
22595
|
-
|
|
22224
|
+
resolveReference: reference => {
|
|
22596
22225
|
const buildUrl = buildUrls.get(reference.specifier);
|
|
22597
22226
|
if (buildUrl) {
|
|
22598
22227
|
return buildUrl;
|
|
22599
22228
|
}
|
|
22600
|
-
|
|
22229
|
+
let urlObject;
|
|
22230
|
+
if (reference.specifier[0] === "/") {
|
|
22231
|
+
urlObject = new URL(reference.specifier.slice(1), buildDirectoryUrl);
|
|
22232
|
+
} else {
|
|
22233
|
+
urlObject = new URL(reference.specifier, reference.baseUrl || reference.parentUrl);
|
|
22234
|
+
}
|
|
22601
22235
|
const url = urlObject.href;
|
|
22602
22236
|
// during versioning we revisit the deps
|
|
22603
22237
|
// but the code used to enforce trailing slash on directories
|
|
@@ -22612,7 +22246,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
22612
22246
|
}
|
|
22613
22247
|
return url;
|
|
22614
22248
|
},
|
|
22615
|
-
|
|
22249
|
+
formatReference: reference => {
|
|
22616
22250
|
if (!reference.shouldHandle) {
|
|
22617
22251
|
if (reference.generatedUrl.startsWith("ignore:")) {
|
|
22618
22252
|
return reference.generatedUrl.slice("ignore:".length);
|
|
@@ -23154,6 +22788,7 @@ const WEB_URL_CONVERTER = {
|
|
|
23154
22788
|
* This plugin is very special because it is here
|
|
23155
22789
|
* to provide "serverEvents" used by other plugins
|
|
23156
22790
|
*/
|
|
22791
|
+
|
|
23157
22792
|
const serverEventsClientFileUrl = new URL("./js/server_events_client.js", import.meta.url).href;
|
|
23158
22793
|
const jsenvPluginServerEventsClientInjection = () => {
|
|
23159
22794
|
return {
|
|
@@ -23218,14 +22853,14 @@ const createFileService = ({
|
|
|
23218
22853
|
sourceFilesConfig,
|
|
23219
22854
|
runtimeCompat,
|
|
23220
22855
|
plugins,
|
|
23221
|
-
|
|
23222
|
-
|
|
22856
|
+
referenceAnalysis,
|
|
22857
|
+
nodeEsmResolution,
|
|
22858
|
+
webResolution,
|
|
23223
22859
|
fileSystemMagicRedirection,
|
|
23224
22860
|
supervisor,
|
|
23225
22861
|
transpilation,
|
|
23226
22862
|
clientAutoreload,
|
|
23227
22863
|
cooldownBetweenFileEvents,
|
|
23228
|
-
explorer,
|
|
23229
22864
|
cacheControl,
|
|
23230
22865
|
ribbon,
|
|
23231
22866
|
sourcemaps,
|
|
@@ -23282,18 +22917,11 @@ const createFileService = ({
|
|
|
23282
22917
|
const clientRuntimeCompat = {
|
|
23283
22918
|
[runtimeName]: runtimeVersion
|
|
23284
22919
|
};
|
|
23285
|
-
let defaultFileUrl;
|
|
23286
|
-
if (explorer) {
|
|
23287
|
-
defaultFileUrl = String(explorerHtmlFileUrl);
|
|
23288
|
-
} else if (sourceMainFilePath) {
|
|
23289
|
-
defaultFileUrl = String(new URL(sourceMainFilePath, sourceDirectoryUrl));
|
|
23290
|
-
} else {
|
|
23291
|
-
defaultFileUrl = String(new URL("./index.html", sourceDirectoryUrl));
|
|
23292
|
-
}
|
|
23293
22920
|
const kitchen = createKitchen({
|
|
23294
22921
|
signal,
|
|
23295
22922
|
logLevel,
|
|
23296
22923
|
rootDirectoryUrl: sourceDirectoryUrl,
|
|
22924
|
+
mainFilePath: sourceMainFilePath,
|
|
23297
22925
|
urlGraph,
|
|
23298
22926
|
dev: true,
|
|
23299
22927
|
runtimeCompat,
|
|
@@ -23301,17 +22929,16 @@ const createFileService = ({
|
|
|
23301
22929
|
systemJsTranspilation: !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "script_type_module") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_dynamic") || !RUNTIME_COMPAT.isSupported(clientRuntimeCompat, "import_meta"),
|
|
23302
22930
|
plugins: [...plugins, ...getCorePlugins({
|
|
23303
22931
|
rootDirectoryUrl: sourceDirectoryUrl,
|
|
23304
|
-
defaultFileUrl,
|
|
23305
22932
|
runtimeCompat,
|
|
23306
|
-
|
|
23307
|
-
|
|
22933
|
+
referenceAnalysis,
|
|
22934
|
+
nodeEsmResolution,
|
|
22935
|
+
webResolution,
|
|
23308
22936
|
fileSystemMagicRedirection,
|
|
23309
22937
|
supervisor,
|
|
23310
22938
|
transpilation,
|
|
23311
22939
|
clientAutoreload,
|
|
23312
22940
|
clientFileChangeCallbackList,
|
|
23313
22941
|
clientFilesPruneCallbackList,
|
|
23314
|
-
explorer,
|
|
23315
22942
|
cacheControl,
|
|
23316
22943
|
ribbon
|
|
23317
22944
|
})],
|
|
@@ -23619,7 +23246,7 @@ const inferParentFromRequest = (request, sourceDirectoryUrl) => {
|
|
|
23619
23246
|
*/
|
|
23620
23247
|
const startDevServer = async ({
|
|
23621
23248
|
sourceDirectoryUrl,
|
|
23622
|
-
sourceMainFilePath,
|
|
23249
|
+
sourceMainFilePath = "./index.html",
|
|
23623
23250
|
port = 3456,
|
|
23624
23251
|
hostname,
|
|
23625
23252
|
acceptAnyIp,
|
|
@@ -23642,13 +23269,12 @@ const startDevServer = async ({
|
|
|
23642
23269
|
// code would be supported during dev but not after build
|
|
23643
23270
|
runtimeCompat = defaultRuntimeCompat,
|
|
23644
23271
|
plugins = [],
|
|
23645
|
-
|
|
23646
|
-
|
|
23272
|
+
referenceAnalysis = {},
|
|
23273
|
+
nodeEsmResolution,
|
|
23274
|
+
webResolution,
|
|
23647
23275
|
supervisor = true,
|
|
23648
23276
|
fileSystemMagicRedirection,
|
|
23649
23277
|
transpilation,
|
|
23650
|
-
explorer = true,
|
|
23651
|
-
// see jsenv_plugin_explorer.js
|
|
23652
23278
|
cacheControl = true,
|
|
23653
23279
|
ribbon = true,
|
|
23654
23280
|
// toolbar = false,
|
|
@@ -23666,6 +23292,9 @@ const startDevServer = async ({
|
|
|
23666
23292
|
throw new TypeError(`${unexpectedParamNames.join(",")}: there is no such param`);
|
|
23667
23293
|
}
|
|
23668
23294
|
sourceDirectoryUrl = assertAndNormalizeDirectoryUrl(sourceDirectoryUrl, "sourceDirectoryUrl");
|
|
23295
|
+
if (typeof sourceMainFilePath !== "string") {
|
|
23296
|
+
throw new TypeError(`sourceMainFilePath must be a string, got ${sourceMainFilePath}`);
|
|
23297
|
+
}
|
|
23669
23298
|
if (outDirectoryUrl === undefined) {
|
|
23670
23299
|
if (!process.env.CI) {
|
|
23671
23300
|
const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
|
|
@@ -23759,14 +23388,14 @@ const startDevServer = async ({
|
|
|
23759
23388
|
sourceFilesConfig,
|
|
23760
23389
|
runtimeCompat,
|
|
23761
23390
|
plugins,
|
|
23762
|
-
|
|
23763
|
-
|
|
23391
|
+
referenceAnalysis,
|
|
23392
|
+
nodeEsmResolution,
|
|
23393
|
+
webResolution,
|
|
23764
23394
|
fileSystemMagicRedirection,
|
|
23765
23395
|
supervisor,
|
|
23766
23396
|
transpilation,
|
|
23767
23397
|
clientAutoreload,
|
|
23768
23398
|
cooldownBetweenFileEvents,
|
|
23769
|
-
explorer,
|
|
23770
23399
|
cacheControl,
|
|
23771
23400
|
ribbon,
|
|
23772
23401
|
sourcemaps,
|
|
@@ -23861,6 +23490,7 @@ const startDevServer = async ({
|
|
|
23861
23490
|
* we want to be in the user shoes and we should not alter build files.
|
|
23862
23491
|
*/
|
|
23863
23492
|
|
|
23493
|
+
|
|
23864
23494
|
/**
|
|
23865
23495
|
* Start a server for build files.
|
|
23866
23496
|
* @param {Object} buildServerParameters
|