@jsenv/core 29.8.6 → 29.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/dist/js/autoreload.js +1 -1
  3. package/dist/main.js +50 -2085
  4. package/package.json +2 -2
  5. package/src/build/build.js +33 -33
  6. package/src/plugins/plugins.js +1 -1
  7. package/src/plugins/ribbon/jsenv_plugin_ribbon.js +6 -1
  8. package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +6 -2
  9. package/src/plugins/url_resolution/node_esm_resolver.js +6 -1
  10. package/dist/js/html_src_set.js +0 -20
  11. package/src/plugins/toolbar/client/animation/toolbar_animation.js +0 -39
  12. package/src/plugins/toolbar/client/eventsource/eventsource.css +0 -83
  13. package/src/plugins/toolbar/client/eventsource/toolbar_eventsource.js +0 -57
  14. package/src/plugins/toolbar/client/execution/execution.css +0 -79
  15. package/src/plugins/toolbar/client/execution/toolbar_execution.js +0 -88
  16. package/src/plugins/toolbar/client/focus/focus.css +0 -61
  17. package/src/plugins/toolbar/client/focus/toolbar_focus.js +0 -19
  18. package/src/plugins/toolbar/client/jsenv_logo.svg +0 -140
  19. package/src/plugins/toolbar/client/notification/toolbar_notification.js +0 -181
  20. package/src/plugins/toolbar/client/responsive/overflow_menu.css +0 -61
  21. package/src/plugins/toolbar/client/responsive/toolbar_responsive.js +0 -103
  22. package/src/plugins/toolbar/client/settings/settings.css +0 -201
  23. package/src/plugins/toolbar/client/settings/toolbar_settings.js +0 -47
  24. package/src/plugins/toolbar/client/theme/jsenv_theme.css +0 -77
  25. package/src/plugins/toolbar/client/theme/light_theme.css +0 -106
  26. package/src/plugins/toolbar/client/theme/toolbar_theme.js +0 -34
  27. package/src/plugins/toolbar/client/toolbar.html +0 -457
  28. package/src/plugins/toolbar/client/toolbar_injector.js +0 -218
  29. package/src/plugins/toolbar/client/toolbar_main.css +0 -172
  30. package/src/plugins/toolbar/client/toolbar_main.js +0 -197
  31. package/src/plugins/toolbar/client/tooltip/tooltip.css +0 -61
  32. package/src/plugins/toolbar/client/tooltip/tooltip.js +0 -39
  33. package/src/plugins/toolbar/client/util/animation.js +0 -305
  34. package/src/plugins/toolbar/client/util/dom.js +0 -108
  35. package/src/plugins/toolbar/client/util/fetch_using_xhr.js +0 -400
  36. package/src/plugins/toolbar/client/util/fetching.js +0 -14
  37. package/src/plugins/toolbar/client/util/iframe_to_parent_href.js +0 -10
  38. package/src/plugins/toolbar/client/util/jsenv_logger.js +0 -28
  39. package/src/plugins/toolbar/client/util/preferences.js +0 -10
  40. package/src/plugins/toolbar/client/util/responsive.js +0 -112
  41. package/src/plugins/toolbar/client/util/util.js +0 -19
  42. package/src/plugins/toolbar/client/variant/variant.js +0 -74
  43. package/src/plugins/toolbar/jsenv_plugin_toolbar.js +0 -62
package/dist/main.js CHANGED
@@ -15,11 +15,9 @@ import { performance as performance$1 } from "node:perf_hooks";
15
15
  import { Readable, Stream, Writable } from "node:stream";
16
16
  import { Http2ServerResponse } from "node:http2";
17
17
  import { lookup } from "node:dns";
18
- import MagicString from "magic-string";
18
+ import { SOURCEMAP, generateSourcemapFileUrl, composeTwoSourcemaps, generateSourcemapDataUrl, createMagicSource, sourcemapConverter, getOriginalPosition } from "@jsenv/sourcemap";
19
+ import { parseHtmlString, stringifyHtmlAst, getHtmlNodeAttribute, visitHtmlNodes, analyzeScriptNode, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, getHtmlNodeText, setHtmlNodeText, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, findHtmlNode, removeHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode, injectHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
19
20
  import { createRequire } from "node:module";
20
- import { parse, serialize, parseFragment } from "parse5";
21
- import { ancestor } from "acorn-walk";
22
- import { p as parseSrcSet } from "./js/html_src_set.js";
23
21
  import babelParser from "@babel/parser";
24
22
  import v8, { takeCoverage } from "node:v8";
25
23
  import wrapAnsi from "wrap-ansi";
@@ -6969,2051 +6967,6 @@ const createServerEventsDispatcher = () => {
6969
6967
  };
6970
6968
  };
6971
6969
 
6972
- const createMagicSource = content => {
6973
- if (content === undefined) {
6974
- throw new Error("content missing");
6975
- }
6976
- const mutations = [];
6977
- return {
6978
- prepend: string => {
6979
- mutations.push(magicString => {
6980
- magicString.prepend(string);
6981
- });
6982
- },
6983
- append: string => {
6984
- mutations.push(magicString => {
6985
- magicString.append(string);
6986
- });
6987
- },
6988
- replace: ({
6989
- start,
6990
- end,
6991
- replacement
6992
- }) => {
6993
- mutations.push(magicString => {
6994
- magicString.overwrite(start, end, replacement);
6995
- });
6996
- },
6997
- remove: ({
6998
- start,
6999
- end
7000
- }) => {
7001
- mutations.push(magicString => {
7002
- magicString.remove(start, end);
7003
- });
7004
- },
7005
- toContentAndSourcemap: ({
7006
- source
7007
- } = {}) => {
7008
- if (mutations.length === 0) {
7009
- return {
7010
- content,
7011
- sourcemap: null
7012
- };
7013
- }
7014
- const magicString = new MagicString(content);
7015
- mutations.forEach(mutation => {
7016
- mutation(magicString);
7017
- });
7018
- const code = magicString.toString();
7019
- const map = magicString.generateMap({
7020
- hires: true,
7021
- includeContent: true,
7022
- source
7023
- });
7024
- return {
7025
- content: code,
7026
- sourcemap: map
7027
- };
7028
- }
7029
- };
7030
- };
7031
-
7032
- const require$3 = createRequire(import.meta.url);
7033
- // consider using https://github.com/7rulnik/source-map-js
7034
-
7035
- const requireSourcemap = () => {
7036
- const namespace = require$3("source-map-js");
7037
- return namespace;
7038
- };
7039
-
7040
- /*
7041
- * https://github.com/mozilla/source-map#sourcemapgenerator
7042
- */
7043
- const {
7044
- SourceMapConsumer,
7045
- SourceMapGenerator
7046
- } = requireSourcemap();
7047
- const composeTwoSourcemaps = (firstSourcemap, secondSourcemap) => {
7048
- if (!firstSourcemap && !secondSourcemap) {
7049
- return null;
7050
- }
7051
- if (!firstSourcemap) {
7052
- return secondSourcemap;
7053
- }
7054
- if (!secondSourcemap) {
7055
- return firstSourcemap;
7056
- }
7057
- const sourcemapGenerator = new SourceMapGenerator();
7058
- const firstSourcemapConsumer = new SourceMapConsumer(firstSourcemap);
7059
- const secondSourcemapConsumer = new SourceMapConsumer(secondSourcemap);
7060
- const firstMappings = readMappings(firstSourcemapConsumer);
7061
- firstMappings.forEach(mapping => {
7062
- sourcemapGenerator.addMapping(mapping);
7063
- });
7064
- const secondMappings = readMappings(secondSourcemapConsumer);
7065
- secondMappings.forEach(mapping => {
7066
- sourcemapGenerator.addMapping(mapping);
7067
- });
7068
- const sourcemap = sourcemapGenerator.toJSON();
7069
- const sources = [];
7070
- const sourcesContent = [];
7071
- const firstSourcesContent = firstSourcemap.sourcesContent;
7072
- const secondSourcesContent = secondSourcemap.sourcesContent;
7073
- sourcemap.sources.forEach(source => {
7074
- sources.push(source);
7075
- if (secondSourcesContent) {
7076
- const secondSourceIndex = secondSourcemap.sources.indexOf(source);
7077
- if (secondSourceIndex > -1) {
7078
- sourcesContent.push(secondSourcesContent[secondSourceIndex]);
7079
- return;
7080
- }
7081
- }
7082
- if (firstSourcesContent) {
7083
- const firstSourceIndex = firstSourcemap.sources.indexOf(source);
7084
- if (firstSourceIndex > -1) {
7085
- sourcesContent.push(firstSourcesContent[firstSourceIndex]);
7086
- return;
7087
- }
7088
- }
7089
- sourcesContent.push(null);
7090
- });
7091
- sourcemap.sources = sources;
7092
- sourcemap.sourcesContent = sourcesContent;
7093
- return sourcemap;
7094
- };
7095
- const readMappings = consumer => {
7096
- const mappings = [];
7097
- consumer.eachMapping(({
7098
- originalColumn,
7099
- originalLine,
7100
- generatedColumn,
7101
- generatedLine,
7102
- source,
7103
- name
7104
- }) => {
7105
- mappings.push({
7106
- original: typeof originalColumn === "number" ? {
7107
- column: originalColumn,
7108
- line: originalLine
7109
- } : undefined,
7110
- generated: {
7111
- column: generatedColumn,
7112
- line: generatedLine
7113
- },
7114
- source: typeof originalColumn === "number" ? source : undefined,
7115
- name
7116
- });
7117
- });
7118
- return mappings;
7119
- };
7120
-
7121
- // https://github.com/mozilla/source-map#sourcemapconsumerprototypeoriginalpositionforgeneratedposition
7122
- const getOriginalPosition = ({
7123
- sourcemap,
7124
- line,
7125
- column,
7126
- bias
7127
- }) => {
7128
- const {
7129
- SourceMapConsumer
7130
- } = requireSourcemap();
7131
- const sourceMapConsumer = new SourceMapConsumer(sourcemap);
7132
- const originalPosition = sourceMapConsumer.originalPositionFor({
7133
- line,
7134
- column,
7135
- bias
7136
- });
7137
- return originalPosition;
7138
- };
7139
-
7140
- const sourcemapConverter = {
7141
- toFileUrls: sourcemap => {
7142
- return {
7143
- ...sourcemap,
7144
- sources: sourcemap.sources.map(source => {
7145
- return isFileSystemPath$1(source) ? fileSystemPathToUrl$1(source) : source;
7146
- })
7147
- };
7148
- },
7149
- toFilePaths: sourcemap => {
7150
- return {
7151
- ...sourcemap,
7152
- sources: sourcemap.sources.map(source => {
7153
- return urlToFileSystemPath(source);
7154
- })
7155
- };
7156
- }
7157
- };
7158
-
7159
- const generateSourcemapFileUrl = url => {
7160
- const urlObject = new URL(url);
7161
- let {
7162
- origin,
7163
- pathname,
7164
- search,
7165
- hash
7166
- } = urlObject;
7167
- // origin is "null" for "file://" urls with Node.js
7168
- if (origin === "null" && urlObject.href.startsWith("file:")) {
7169
- origin = "file://";
7170
- }
7171
- const sourcemapUrl = `${origin}${pathname}.map${search}${hash}`;
7172
- return sourcemapUrl;
7173
- };
7174
- const generateSourcemapDataUrl = sourcemap => {
7175
- const asBase64 = Buffer.from(JSON.stringify(sourcemap)).toString("base64");
7176
- return `data:application/json;charset=utf-8;base64,${asBase64}`;
7177
- };
7178
-
7179
- const SOURCEMAP = {
7180
- enabledOnContentType: contentType => {
7181
- return ["text/javascript", "text/css"].includes(contentType);
7182
- },
7183
- readComment: ({
7184
- contentType,
7185
- content
7186
- }) => {
7187
- const read = {
7188
- "text/javascript": parseJavaScriptSourcemapComment,
7189
- "text/css": parseCssSourcemapComment
7190
- }[contentType];
7191
- return read ? read(content) : null;
7192
- },
7193
- writeComment: ({
7194
- contentType,
7195
- content,
7196
- specifier
7197
- }) => {
7198
- const write = {
7199
- "text/javascript": setJavaScriptSourceMappingUrl,
7200
- "text/css": setCssSourceMappingUrl
7201
- }[contentType];
7202
- return write ? write(content, specifier) : content;
7203
- }
7204
- };
7205
- const parseJavaScriptSourcemapComment = javaScriptSource => {
7206
- let sourceMappingUrl;
7207
- replaceSourceMappingUrl(javaScriptSource, javascriptSourceMappingUrlCommentRegexp, value => {
7208
- sourceMappingUrl = value;
7209
- });
7210
- if (!sourceMappingUrl) {
7211
- return null;
7212
- }
7213
- return {
7214
- type: "sourcemap_comment",
7215
- subtype: "js",
7216
- // we assume it's on last line
7217
- line: javaScriptSource.split(/\r?\n/).length,
7218
- // ${"//#"} is to avoid static analysis to think there is a sourceMappingUrl for this file
7219
- column: `${"//#"} sourceMappingURL=`.length + 1,
7220
- specifier: sourceMappingUrl
7221
- };
7222
- };
7223
- const setJavaScriptSourceMappingUrl = (javaScriptSource, sourceMappingFileUrl) => {
7224
- let replaced;
7225
- const sourceAfterReplace = replaceSourceMappingUrl(javaScriptSource, javascriptSourceMappingUrlCommentRegexp, () => {
7226
- replaced = true;
7227
- return sourceMappingFileUrl ? writeJavaScriptSourceMappingURL(sourceMappingFileUrl) : "";
7228
- });
7229
- if (replaced) {
7230
- return sourceAfterReplace;
7231
- }
7232
- return sourceMappingFileUrl ? `${javaScriptSource}
7233
- ${writeJavaScriptSourceMappingURL(sourceMappingFileUrl)}
7234
- ` : javaScriptSource;
7235
- };
7236
- const parseCssSourcemapComment = cssSource => {
7237
- let sourceMappingUrl;
7238
- replaceSourceMappingUrl(cssSource, cssSourceMappingUrlCommentRegExp, value => {
7239
- sourceMappingUrl = value;
7240
- });
7241
- if (!sourceMappingUrl) {
7242
- return null;
7243
- }
7244
- return {
7245
- type: "sourcemap_comment",
7246
- subtype: "css",
7247
- // we assume it's on last line
7248
- line: cssSource.split(/\r?\n/).length - 1,
7249
- // ${"//*#"} is to avoid static analysis to think there is a sourceMappingUrl for this file
7250
- column: `${"//*#"} sourceMappingURL=`.length + 1,
7251
- specifier: sourceMappingUrl
7252
- };
7253
- };
7254
- const setCssSourceMappingUrl = (cssSource, sourceMappingFileUrl) => {
7255
- let replaced;
7256
- const sourceAfterReplace = replaceSourceMappingUrl(cssSource, cssSourceMappingUrlCommentRegExp, () => {
7257
- replaced = true;
7258
- return sourceMappingFileUrl ? writeCssSourceMappingUrl(sourceMappingFileUrl) : "";
7259
- });
7260
- if (replaced) {
7261
- return sourceAfterReplace;
7262
- }
7263
- return sourceMappingFileUrl ? `${cssSource}
7264
- ${writeCssSourceMappingUrl(sourceMappingFileUrl)}
7265
- ` : cssSource;
7266
- };
7267
- const javascriptSourceMappingUrlCommentRegexp = /\/\/ ?# ?sourceMappingURL=([^\s'"]+)/g;
7268
- const cssSourceMappingUrlCommentRegExp = /\/\*# ?sourceMappingURL=([^\s'"]+) \*\//g;
7269
-
7270
- // ${"//#"} is to avoid a parser thinking there is a sourceMappingUrl for this file
7271
- const writeJavaScriptSourceMappingURL = value => `${"//#"} sourceMappingURL=${value}`;
7272
- const writeCssSourceMappingUrl = value => `/*# sourceMappingURL=${value} */`;
7273
- const replaceSourceMappingUrl = (source, regexp, callback) => {
7274
- let lastSourceMappingUrl;
7275
- let matchSourceMappingUrl;
7276
- while (matchSourceMappingUrl = regexp.exec(source)) {
7277
- lastSourceMappingUrl = matchSourceMappingUrl;
7278
- }
7279
- if (lastSourceMappingUrl) {
7280
- const index = lastSourceMappingUrl.index;
7281
- const before = source.slice(0, index);
7282
- const after = source.slice(index);
7283
- const mappedAfter = after.replace(regexp, (match, firstGroup) => {
7284
- return callback(firstGroup);
7285
- });
7286
- return `${before}${mappedAfter}`;
7287
- }
7288
- return source;
7289
- };
7290
-
7291
- const getHtmlNodeAttribute = (htmlNode, attributeName) => {
7292
- const attribute = getHtmlAttributeByName(htmlNode, attributeName);
7293
- return attribute ? attribute.value || "" : undefined;
7294
- };
7295
- const setHtmlNodeAttributes = (htmlNode, attributesToAssign) => {
7296
- if (typeof attributesToAssign !== "object") {
7297
- throw new TypeError(`attributesToAssign must be an object`);
7298
- }
7299
- const {
7300
- attrs
7301
- } = htmlNode;
7302
- if (!attrs) return;
7303
- Object.keys(attributesToAssign).forEach(key => {
7304
- const existingAttributeIndex = attrs.findIndex(({
7305
- name
7306
- }) => name === key);
7307
- const value = attributesToAssign[key];
7308
- // remove no-op
7309
- if (existingAttributeIndex === -1 && value === undefined) {
7310
- return;
7311
- }
7312
- // add
7313
- if (existingAttributeIndex === -1 && value !== undefined) {
7314
- attrs.push({
7315
- name: key,
7316
- value
7317
- });
7318
- return;
7319
- }
7320
- // remove
7321
- if (value === undefined) {
7322
- attrs.splice(existingAttributeIndex, 1);
7323
- return;
7324
- }
7325
- // update
7326
- attrs[existingAttributeIndex].value = value;
7327
- });
7328
- };
7329
- const getHtmlAttributeByName = (htmlNode, attributeName) => {
7330
- const attrs = htmlNode.attrs;
7331
- const attribute = attrs ? attrs.find(attr => attr.name === attributeName) : null;
7332
- return attribute;
7333
- };
7334
-
7335
- const storeHtmlNodePosition = node => {
7336
- const originalPositionAttributeName = `original-position`;
7337
- const originalPosition = getHtmlNodeAttribute(node, originalPositionAttributeName);
7338
- if (originalPosition !== undefined) {
7339
- return true;
7340
- }
7341
- const {
7342
- sourceCodeLocation
7343
- } = node;
7344
- if (!sourceCodeLocation) {
7345
- return false;
7346
- }
7347
- const {
7348
- startLine,
7349
- startCol,
7350
- endLine,
7351
- endCol
7352
- } = sourceCodeLocation;
7353
- setHtmlNodeAttributes(node, {
7354
- [originalPositionAttributeName]: `${startLine}:${startCol};${endLine}:${endCol}`
7355
- });
7356
- return true;
7357
- };
7358
- const storeHtmlNodeAttributePosition = (node, attributeName) => {
7359
- const {
7360
- sourceCodeLocation
7361
- } = node;
7362
- if (!sourceCodeLocation) {
7363
- return false;
7364
- }
7365
- const attributeValue = getHtmlNodeAttribute(node, attributeName);
7366
- if (attributeValue === undefined) {
7367
- return false;
7368
- }
7369
- const attributeLocation = sourceCodeLocation.attrs[attributeName];
7370
- if (!attributeLocation) {
7371
- return false;
7372
- }
7373
- const originalPositionAttributeName = `original-${attributeName}-position`;
7374
- const originalPosition = getHtmlNodeAttribute(node, originalPositionAttributeName);
7375
- if (originalPosition !== undefined) {
7376
- return true;
7377
- }
7378
- const {
7379
- startLine,
7380
- startCol,
7381
- endLine,
7382
- endCol
7383
- } = attributeLocation;
7384
- setHtmlNodeAttributes(node, {
7385
- [originalPositionAttributeName]: `${startLine}:${startCol};${endLine}:${endCol}`
7386
- });
7387
- return true;
7388
- };
7389
- const getHtmlNodePosition = (node, {
7390
- preferOriginal = false
7391
- } = {}) => {
7392
- const position = {};
7393
- const {
7394
- sourceCodeLocation
7395
- } = node;
7396
- if (sourceCodeLocation) {
7397
- const {
7398
- startLine,
7399
- startCol,
7400
- endLine,
7401
- endCol
7402
- } = sourceCodeLocation;
7403
- Object.assign(position, {
7404
- line: startLine,
7405
- lineEnd: endLine,
7406
- column: startCol,
7407
- columnEnd: endCol
7408
- });
7409
- }
7410
- const originalPosition = getHtmlNodeAttribute(node, "original-position");
7411
- if (originalPosition === undefined) {
7412
- return position;
7413
- }
7414
- const [start, end] = originalPosition.split(";");
7415
- const [originalLine, originalColumn] = start.split(":");
7416
- const [originalLineEnd, originalColumnEnd] = end.split(":");
7417
- Object.assign(position, {
7418
- originalLine: parseInt(originalLine),
7419
- originalColumn: parseInt(originalColumn),
7420
- originalLineEnd: parseInt(originalLineEnd),
7421
- originalColumnEnd: parseInt(originalColumnEnd)
7422
- });
7423
- if (preferOriginal) {
7424
- position.line = position.originalLine;
7425
- position.column = position.originalColumn;
7426
- position.lineEnd = position.originalLineEnd;
7427
- position.columnEnd = position.originalColumnEnd;
7428
- position.isOriginal = true;
7429
- }
7430
- return position;
7431
- };
7432
- const getHtmlNodeAttributePosition = (node, attributeName) => {
7433
- const position = {};
7434
- const {
7435
- sourceCodeLocation
7436
- } = node;
7437
- if (sourceCodeLocation) {
7438
- const attributeLocation = sourceCodeLocation.attrs[attributeName];
7439
- if (attributeLocation) {
7440
- Object.assign(position, {
7441
- line: attributeLocation.startLine,
7442
- column: attributeLocation.startCol
7443
- });
7444
- }
7445
- }
7446
- const originalPositionAttributeName = attributeName === "inlined-from-src" ? "original-src-position" : attributeName === "inlined-from-href" ? "original-href-position" : `original-${attributeName}-position`;
7447
- const originalPosition = getHtmlNodeAttribute(node, originalPositionAttributeName);
7448
- if (originalPosition === undefined) {
7449
- return position;
7450
- }
7451
- const [start, end] = originalPosition.split(";");
7452
- const [originalLine, originalColumn] = start.split(":");
7453
- const [originalLineEnd, originalColumnEnd] = end.split(":");
7454
- Object.assign(position, {
7455
- originalLine: parseInt(originalLine),
7456
- originalColumn: parseInt(originalColumn),
7457
- originalLineEnd: parseInt(originalLineEnd),
7458
- originalColumnEnd: parseInt(originalColumnEnd)
7459
- });
7460
- return position;
7461
- };
7462
-
7463
- const visitHtmlNodes = (htmlAst, visitors) => {
7464
- const visitNode = node => {
7465
- const visitor = visitors[node.nodeName] || visitors["*"];
7466
- if (visitor) {
7467
- const callbackReturnValue = visitor(node);
7468
- if (callbackReturnValue === "stop") {
7469
- return;
7470
- }
7471
- }
7472
- const {
7473
- childNodes
7474
- } = node;
7475
- if (childNodes) {
7476
- let i = 0;
7477
- while (i < childNodes.length) {
7478
- visitNode(childNodes[i++]);
7479
- }
7480
- }
7481
- };
7482
- visitNode(htmlAst);
7483
- };
7484
- const findHtmlNode = (htmlAst, predicate) => {
7485
- let nodeMatching = null;
7486
- visitHtmlNodes(htmlAst, {
7487
- "*": node => {
7488
- if (predicate(node)) {
7489
- nodeMatching = node;
7490
- return "stop";
7491
- }
7492
- return null;
7493
- }
7494
- });
7495
- return nodeMatching;
7496
- };
7497
- const findHtmlChildNode = (htmlNode, predicate) => {
7498
- const {
7499
- childNodes = []
7500
- } = htmlNode;
7501
- return childNodes.find(predicate);
7502
- };
7503
-
7504
- const getHtmlNodeText = htmlNode => {
7505
- const textNode = getTextNode(htmlNode);
7506
- return textNode ? textNode.value : undefined;
7507
- };
7508
- const getTextNode = htmlNode => {
7509
- const firstChild = htmlNode.childNodes[0];
7510
- const textNode = firstChild && firstChild.nodeName === "#text" ? firstChild : null;
7511
- return textNode;
7512
- };
7513
- const removeHtmlNodeText = htmlNode => {
7514
- const textNode = getTextNode(htmlNode);
7515
- if (textNode) {
7516
- htmlNode.childNodes = [];
7517
- }
7518
- };
7519
- const setHtmlNodeText = (htmlNode, textContent) => {
7520
- const textNode = getTextNode(htmlNode);
7521
- if (textNode) {
7522
- textNode.value = textContent;
7523
- } else {
7524
- const newTextNode = {
7525
- nodeName: "#text",
7526
- value: textContent,
7527
- parentNode: htmlNode
7528
- };
7529
- htmlNode.childNodes.splice(0, 0, newTextNode);
7530
- }
7531
- };
7532
-
7533
- const parseHtmlString = (htmlString, {
7534
- storeOriginalPositions = true
7535
- } = {}) => {
7536
- const htmlAst = parse(htmlString, {
7537
- sourceCodeLocationInfo: true
7538
- });
7539
- if (storeOriginalPositions) {
7540
- const htmlNode = findHtmlChildNode(htmlAst, node => node.nodeName === "html");
7541
- const stored = getHtmlNodeAttribute(htmlNode, "original-position-stored");
7542
- if (stored === undefined) {
7543
- visitHtmlNodes(htmlAst, {
7544
- "*": node => {
7545
- if (node.nodeName === "script" || node.nodeName === "style") {
7546
- const htmlNodeText = getHtmlNodeText(node);
7547
- if (htmlNodeText !== undefined) {
7548
- storeHtmlNodePosition(node);
7549
- }
7550
- }
7551
- storeHtmlNodeAttributePosition(node, "src");
7552
- storeHtmlNodeAttributePosition(node, "href");
7553
- }
7554
- });
7555
- setHtmlNodeAttributes(htmlNode, {
7556
- "original-position-stored": ""
7557
- });
7558
- }
7559
- }
7560
- return htmlAst;
7561
- };
7562
- const stringifyHtmlAst = (htmlAst, {
7563
- cleanupJsenvAttributes = false
7564
- } = {}) => {
7565
- if (cleanupJsenvAttributes) {
7566
- const htmlNode = findHtmlChildNode(htmlAst, node => node.nodeName === "html");
7567
- const storedAttribute = getHtmlNodeAttribute(htmlNode, "original-position-stored");
7568
- if (storedAttribute !== undefined) {
7569
- setHtmlNodeAttributes(htmlNode, {
7570
- "original-position-stored": undefined
7571
- });
7572
- visitHtmlNodes(htmlAst, {
7573
- "*": node => {
7574
- setHtmlNodeAttributes(node, {
7575
- "original-position": undefined,
7576
- "original-src-position": undefined,
7577
- "original-href-position": undefined,
7578
- "inlined-from-src": undefined,
7579
- "inlined-from-href": undefined,
7580
- "jsenv-cooked-by": undefined,
7581
- "jsenv-inlined-by": undefined,
7582
- "jsenv-injected-by": undefined,
7583
- "jsenv-debug": undefined
7584
- });
7585
- }
7586
- });
7587
- }
7588
- }
7589
- const htmlString = serialize(htmlAst);
7590
- return htmlString;
7591
- };
7592
-
7593
- const analyzeScriptNode = scriptNode => {
7594
- const typeAttribute = getHtmlNodeAttribute(scriptNode, "type");
7595
- if (typeAttribute === undefined || typeAttribute === "text/javascript") {
7596
- return {
7597
- type: "js_classic",
7598
- contentType: "text/javascript"
7599
- };
7600
- }
7601
- if (typeAttribute === "module") {
7602
- return {
7603
- type: "js_module",
7604
- contentType: "text/javascript"
7605
- };
7606
- }
7607
- if (typeAttribute === "importmap") {
7608
- return {
7609
- type: "importmap",
7610
- contentType: "application/importmap+json"
7611
- };
7612
- }
7613
- // jsx
7614
- if (typeAttribute === "text/jsx") {
7615
- return {
7616
- type: "js_classic",
7617
- contentType: "text/javascript",
7618
- extension: ".jsx"
7619
- };
7620
- }
7621
- if (typeAttribute === "module/jsx") {
7622
- return {
7623
- type: "js_module",
7624
- contentType: "text/javascript",
7625
- extension: ".jsx"
7626
- };
7627
- }
7628
- // typescript
7629
- if (typeAttribute === "text/ts") {
7630
- return {
7631
- type: "js_classic",
7632
- contentType: "text/javascript",
7633
- extension: ".ts"
7634
- };
7635
- }
7636
- if (typeAttribute === "module/ts") {
7637
- return {
7638
- type: "js_module",
7639
- contentType: "text/javascript",
7640
- extension: ".ts"
7641
- };
7642
- }
7643
- // typescript and jsx
7644
- if (typeAttribute === "text/tsx") {
7645
- return {
7646
- type: "js_classic",
7647
- contentType: "text/javascript",
7648
- extension: ".tsx"
7649
- };
7650
- }
7651
- if (typeAttribute === "module/tsx") {
7652
- return {
7653
- type: "js_module",
7654
- contentType: "text/javascript",
7655
- extension: ".tsx"
7656
- };
7657
- }
7658
- // from MDN about [type] attribute:
7659
- // "Any other value: The embedded content is treated as a data block
7660
- // which won't be processed by the browser. Developers must use a valid MIME type
7661
- // that is not a JavaScript MIME type to denote data blocks.
7662
- // The src attribute will be ignored."
7663
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-type
7664
- return {
7665
- type: "text",
7666
- contentType: "text/plain"
7667
- };
7668
- };
7669
- const analyzeLinkNode = linkNode => {
7670
- const rel = getHtmlNodeAttribute(linkNode, "rel");
7671
- if (rel === "stylesheet") {
7672
- return {
7673
- isStylesheet: true
7674
- };
7675
- }
7676
- const isResourceHint = ["preconnect", "dns-prefetch", "prefetch", "preload", "modulepreload"].includes(rel);
7677
- return {
7678
- isResourceHint,
7679
- rel
7680
- };
7681
- };
7682
-
7683
- const removeHtmlNode = htmlNode => {
7684
- const {
7685
- childNodes
7686
- } = htmlNode.parentNode;
7687
- childNodes.splice(childNodes.indexOf(htmlNode), 1);
7688
- };
7689
- const createHtmlNode = ({
7690
- tagName,
7691
- textContent = "",
7692
- ...rest
7693
- }) => {
7694
- const html = `<${tagName} ${stringifyAttributes(rest)}>${textContent}</${tagName}>`;
7695
- const fragment = parseFragment(html);
7696
- return fragment.childNodes[0];
7697
- };
7698
- const injectHtmlNode = (htmlAst, node, jsenvPluginName = "jsenv") => {
7699
- setHtmlNodeAttributes(node, {
7700
- "jsenv-injected-by": jsenvPluginName
7701
- });
7702
- const htmlHtmlNode = findChild(htmlAst, node => node.nodeName === "html");
7703
- const bodyNode = findChild(htmlHtmlNode, node => node.nodeName === "body");
7704
- return insertHtmlNodeAfter(node, bodyNode);
7705
- };
7706
- const injectScriptNodeAsEarlyAsPossible = (htmlAst, scriptNode, jsenvPluginName = "jsenv") => {
7707
- setHtmlNodeAttributes(scriptNode, {
7708
- "jsenv-injected-by": jsenvPluginName
7709
- });
7710
- const isJsModule = analyzeScriptNode(scriptNode).type === "js_module";
7711
- if (isJsModule) {
7712
- const firstImportmapScript = findHtmlNode(htmlAst, node => {
7713
- return node.nodeName === "script" && analyzeScriptNode(node).type === "importmap";
7714
- });
7715
- if (firstImportmapScript) {
7716
- const importmapParent = firstImportmapScript.parentNode;
7717
- const importmapSiblings = importmapParent.childNodes;
7718
- const nextSiblings = importmapSiblings.slice(importmapSiblings.indexOf(firstImportmapScript) + 1);
7719
- let after = firstImportmapScript;
7720
- for (const nextSibling of nextSiblings) {
7721
- if (nextSibling.nodeName === "script") {
7722
- return insertHtmlNodeBefore(scriptNode, importmapParent, nextSibling);
7723
- }
7724
- if (nextSibling.nodeName === "link") {
7725
- after = nextSibling;
7726
- }
7727
- }
7728
- return insertHtmlNodeAfter(scriptNode, importmapParent, after);
7729
- }
7730
- }
7731
- const headNode = findChild(htmlAst, node => node.nodeName === "html").childNodes[0];
7732
- let after = headNode.childNodes[0];
7733
- for (const child of headNode.childNodes) {
7734
- if (child.nodeName === "script") {
7735
- return insertHtmlNodeBefore(scriptNode, headNode, child);
7736
- }
7737
- if (child.nodeName === "link") {
7738
- after = child;
7739
- }
7740
- }
7741
- return insertHtmlNodeAfter(scriptNode, headNode, after);
7742
- };
7743
- const insertHtmlNodeBefore = (nodeToInsert, futureParentNode, futureNextSibling) => {
7744
- const {
7745
- childNodes = []
7746
- } = futureParentNode;
7747
- const futureIndex = futureNextSibling ? childNodes.indexOf(futureNextSibling) : 0;
7748
- injectWithWhitespaces(nodeToInsert, futureParentNode, futureIndex);
7749
- };
7750
- const insertHtmlNodeAfter = (nodeToInsert, futureParentNode, futurePrevSibling) => {
7751
- const {
7752
- childNodes = []
7753
- } = futureParentNode;
7754
- const futureIndex = futurePrevSibling ? childNodes.indexOf(futurePrevSibling) + 1 : childNodes.length;
7755
- injectWithWhitespaces(nodeToInsert, futureParentNode, futureIndex);
7756
- };
7757
- const injectWithWhitespaces = (nodeToInsert, futureParentNode, futureIndex) => {
7758
- const {
7759
- childNodes = []
7760
- } = futureParentNode;
7761
- const previousSiblings = childNodes.slice(0, futureIndex);
7762
- const nextSiblings = childNodes.slice(futureIndex);
7763
- const futureChildNodes = [];
7764
- const previousSibling = previousSiblings[0];
7765
- if (previousSibling) {
7766
- futureChildNodes.push(...previousSiblings);
7767
- }
7768
- if (!previousSibling || previousSibling.nodeName !== "#text") {
7769
- futureChildNodes.push({
7770
- nodeName: "#text",
7771
- value: "\n ",
7772
- parentNode: futureParentNode
7773
- });
7774
- }
7775
- futureChildNodes.push(nodeToInsert);
7776
- const nextSibling = nextSiblings[0];
7777
- if (!nextSibling || nextSibling.nodeName !== "#text") {
7778
- futureChildNodes.push({
7779
- nodeName: "#text",
7780
- value: "\n ",
7781
- parentNode: futureParentNode
7782
- });
7783
- }
7784
- if (nextSibling) {
7785
- futureChildNodes.push(...nextSiblings);
7786
- }
7787
- futureParentNode.childNodes = futureChildNodes;
7788
- };
7789
- const findChild = ({
7790
- childNodes = []
7791
- }, predicate) => childNodes.find(predicate);
7792
- const stringifyAttributes = object => {
7793
- let string = "";
7794
- Object.keys(object).forEach(key => {
7795
- const value = object[key];
7796
- if (value === undefined) return;
7797
- if (string !== "") string += " ";
7798
- string += `${key}=${valueToHtmlAttributeValue(value)}`;
7799
- });
7800
- return string;
7801
- };
7802
- const valueToHtmlAttributeValue = value => {
7803
- if (typeof value === "string") {
7804
- return JSON.stringify(value);
7805
- }
7806
- return `"${JSON.stringify(value)}"`;
7807
- };
7808
-
7809
- const applyPostCss = async ({
7810
- sourcemaps = "comment",
7811
- plugins,
7812
- // https://github.com/postcss/postcss#options
7813
- options = {},
7814
- url,
7815
- map,
7816
- content
7817
- }) => {
7818
- const {
7819
- default: postcss
7820
- } = await import("postcss");
7821
- try {
7822
- const cssFileUrl = urlToFileUrl(url);
7823
- const result = await postcss(plugins).process(content, {
7824
- collectUrls: true,
7825
- from: fileURLToPath(cssFileUrl),
7826
- to: fileURLToPath(cssFileUrl),
7827
- map: {
7828
- annotation: sourcemaps === "file",
7829
- inline: sourcemaps === "inline",
7830
- // https://postcss.org/api/#sourcemapoptions
7831
- ...(map ? {
7832
- prev: JSON.stringify(map)
7833
- } : {})
7834
- },
7835
- ...options
7836
- });
7837
- return {
7838
- postCssMessages: result.messages,
7839
- map: result.map.toJSON(),
7840
- content: result.css
7841
- };
7842
- } catch (error) {
7843
- if (error.name === "CssSyntaxError") {
7844
- console.error(String(error));
7845
- throw error;
7846
- }
7847
- throw error;
7848
- }
7849
- };
7850
-
7851
- // the goal of this function is to take an url that is likely an http url
7852
- // info a file:// url
7853
- // for instance http://example.com/dir/file.js
7854
- // must becomes file:///dir/file.js
7855
- // but in windows it must be file://C:/dir/file.js
7856
- const filesystemRootUrl = process.platform === "win32" ? `file:///${process.cwd()[0]}:/` : "file:///";
7857
- const urlToFileUrl = url => {
7858
- const urlString = String(url);
7859
- if (urlString.startsWith("file:")) {
7860
- return urlString;
7861
- }
7862
- const origin = new URL(url).origin;
7863
- const afterOrigin = urlString.slice(origin.length);
7864
- return new URL(afterOrigin, filesystemRootUrl).href;
7865
- };
7866
-
7867
- const require$2 = createRequire(import.meta.url);
7868
- const transpileWithParcel = (urlInfo, context) => {
7869
- const css = require$2("@parcel/css");
7870
- const targets = runtimeCompatToTargets(context.runtimeCompat);
7871
- const {
7872
- code,
7873
- map
7874
- } = css.transform({
7875
- filename: fileURLToPath(urlInfo.originalUrl),
7876
- code: Buffer.from(urlInfo.content),
7877
- targets,
7878
- minify: false
7879
- });
7880
- return {
7881
- code,
7882
- map
7883
- };
7884
- };
7885
- const minifyWithParcel = (urlInfo, context) => {
7886
- const css = require$2("@parcel/css");
7887
- const targets = runtimeCompatToTargets(context.runtimeCompat);
7888
- const {
7889
- code,
7890
- map
7891
- } = css.transform({
7892
- filename: fileURLToPath(urlInfo.originalUrl),
7893
- code: Buffer.from(urlInfo.content),
7894
- targets,
7895
- minify: true
7896
- });
7897
- return {
7898
- code,
7899
- map
7900
- };
7901
- };
7902
- const runtimeCompatToTargets = runtimeCompat => {
7903
- const targets = {};
7904
- ["chrome", "firefox", "ie", "opera", "safari"].forEach(runtimeName => {
7905
- const version = runtimeCompat[runtimeName];
7906
- if (version) {
7907
- targets[runtimeName] = versionToBits(version);
7908
- }
7909
- });
7910
- return targets;
7911
- };
7912
- const versionToBits = version => {
7913
- const [major, minor = 0, patch = 0] = version.split("-")[0].split(".").map(v => parseInt(v, 10));
7914
- return major << 16 | minor << 8 | patch;
7915
- };
7916
-
7917
- const require$1 = createRequire(import.meta.url);
7918
-
7919
- /**
7920
-
7921
- https://github.com/postcss/postcss/blob/master/docs/writing-a-plugin.md
7922
- https://github.com/postcss/postcss/blob/master/docs/guidelines/plugin.md
7923
- https://github.com/postcss/postcss/blob/master/docs/guidelines/runner.md#31-dont-show-js-stack-for-csssyntaxerror
7924
-
7925
- In case css sourcemap contains no%20source
7926
- This is because of https://github.com/postcss/postcss/blob/fd30d3df5abc0954a0ec642a3cdc644ab2aacf9c/lib/map-generator.js#L231
7927
- and it indicates a node has been replaced without passing source
7928
- hence sourcemap cannot point the original source location
7929
-
7930
- */
7931
- const postCssPluginUrlVisitor = ({
7932
- urlVisitor = () => null
7933
- }) => {
7934
- const parseCssValue = require$1("postcss-value-parser");
7935
- const stringifyCssNodes = parseCssValue.stringify;
7936
- return {
7937
- postcssPlugin: "url_visitor",
7938
- prepare: result => {
7939
- const {
7940
- from
7941
- } = result.opts;
7942
- const fromUrl = String(pathToFileURL(from));
7943
- const mutations = [];
7944
- return {
7945
- AtRule: {
7946
- import: (atImportNode, {
7947
- AtRule
7948
- }) => {
7949
- if (atImportNode.parent.type !== "root") {
7950
- atImportNode.warn(result, "`@import` should be top level");
7951
- return;
7952
- }
7953
- if (atImportNode.nodes) {
7954
- atImportNode.warn(result, "`@import` was not terminated correctly");
7955
- return;
7956
- }
7957
- const parsed = parseCssValue(atImportNode.params);
7958
- let [urlNode] = parsed.nodes;
7959
- if (!urlNode || urlNode.type !== "string" && urlNode.type !== "function") {
7960
- atImportNode.warn(result, `No URL in \`${atImportNode.toString()}\``);
7961
- return;
7962
- }
7963
- let url = "";
7964
- if (urlNode.type === "string") {
7965
- url = urlNode.value;
7966
- } else if (urlNode.type === "function") {
7967
- // Invalid function
7968
- if (!/^url$/i.test(urlNode.value)) {
7969
- atImportNode.warn(result, `Invalid \`url\` function in \`${atImportNode.toString()}\``);
7970
- return;
7971
- }
7972
- const firstNode = urlNode.nodes[0];
7973
- if (firstNode && firstNode.type === "string") {
7974
- urlNode = firstNode;
7975
- url = urlNode.value;
7976
- } else {
7977
- urlNode = urlNode.nodes;
7978
- url = stringifyCssNodes(urlNode.nodes);
7979
- }
7980
- }
7981
- url = url.trim();
7982
- if (url.length === 0) {
7983
- atImportNode.warn(result, `Empty URL in \`${atImportNode.toString()}\``);
7984
- return;
7985
- }
7986
- const specifier = url;
7987
- url = new URL(specifier, fromUrl).href;
7988
- if (url === fromUrl) {
7989
- atImportNode.warn(result, `\`@import\` loop in \`${atImportNode.toString()}\``);
7990
- return;
7991
- }
7992
- const atRuleStart = atImportNode.source.start.offset;
7993
- const atRuleEnd = atImportNode.source.end.offset + 1; // for the ";"
7994
- const atRuleRaw = atImportNode.source.input.css.slice(atRuleStart, atRuleEnd);
7995
- const specifierIndex = atRuleRaw.indexOf(atImportNode.params);
7996
- const specifierStart = atRuleStart + specifierIndex;
7997
- const specifierEnd = specifierStart + atImportNode.params.length;
7998
- const specifierLine = atImportNode.source.start.line;
7999
- const specifierColumn = atImportNode.source.start.column + specifierIndex;
8000
- urlVisitor({
8001
- declarationNode: atImportNode,
8002
- type: "@import",
8003
- atRuleStart,
8004
- atRuleEnd,
8005
- specifier,
8006
- specifierLine,
8007
- specifierColumn,
8008
- specifierStart,
8009
- specifierEnd,
8010
- replace: newUrlSpecifier => {
8011
- if (newUrlSpecifier === urlNode.value) {
8012
- return;
8013
- }
8014
- urlNode.value = newUrlSpecifier;
8015
- const newParams = parsed.toString();
8016
- const newAtImportRule = new AtRule({
8017
- name: "import",
8018
- params: newParams,
8019
- source: atImportNode.source
8020
- });
8021
- atImportNode.replaceWith(newAtImportRule);
8022
- }
8023
- });
8024
- }
8025
- },
8026
- Declaration: declarationNode => {
8027
- const parsed = parseCssValue(declarationNode.value);
8028
- const urlMutations = [];
8029
- walkUrls(parsed, {
8030
- stringifyCssNodes,
8031
- visitor: ({
8032
- url,
8033
- urlNode
8034
- }) => {
8035
- // Empty URL
8036
- if (!urlNode || url.length === 0) {
8037
- declarationNode.warn(result, `Empty URL in \`${declarationNode.toString()}\``);
8038
- return;
8039
- }
8040
- // Skip Data URI
8041
- if (isDataUrl(url)) {
8042
- return;
8043
- }
8044
- const specifier = url;
8045
- url = new URL(specifier, pathToFileURL(from));
8046
- const declarationNodeStart = declarationNode.source.start.offset;
8047
- const afterDeclarationNode = declarationNode.source.input.css.slice(declarationNodeStart);
8048
- const valueIndex = afterDeclarationNode.indexOf(declarationNode.value);
8049
- const valueStart = declarationNodeStart + valueIndex;
8050
- const specifierStart = valueStart + urlNode.sourceIndex;
8051
- const specifierEnd = specifierStart + (urlNode.type === "word" ? urlNode.value.length : urlNode.value.length + 2); // the quotes
8052
- // value raw
8053
- // declarationNode.source.input.css.slice(valueStart)
8054
- // specifier raw
8055
- // declarationNode.source.input.css.slice(specifierStart, specifierEnd)
8056
- const specifierLine = declarationNode.source.start.line;
8057
- const specifierColumn = declarationNode.source.start.column + (specifierStart - declarationNodeStart);
8058
- urlVisitor({
8059
- declarationNode,
8060
- type: "url",
8061
- specifier,
8062
- specifierLine,
8063
- specifierColumn,
8064
- specifierStart,
8065
- specifierEnd,
8066
- replace: newUrlSpecifier => {
8067
- urlMutations.push(() => {
8068
- // the specifier desires to be inside double quotes
8069
- if (newUrlSpecifier[0] === `"`) {
8070
- urlNode.type = "word";
8071
- urlNode.value = newUrlSpecifier;
8072
- return;
8073
- }
8074
- // the specifier desires to be inside simple quotes
8075
- if (newUrlSpecifier[0] === `'`) {
8076
- urlNode.type = "word";
8077
- urlNode.value = newUrlSpecifier;
8078
- return;
8079
- }
8080
- // the specifier desired to be just a word
8081
- // for the "word" type so that newUrlSpecifier can opt-out of being between quotes
8082
- // useful to inject __v__ calls for css inside js
8083
- urlNode.type = "word";
8084
- urlNode.value = newUrlSpecifier;
8085
- });
8086
- }
8087
- });
8088
- }
8089
- });
8090
- if (urlMutations.length) {
8091
- mutations.push(() => {
8092
- urlMutations.forEach(urlMutation => {
8093
- urlMutation();
8094
- });
8095
- declarationNode.value = parsed.toString();
8096
- });
8097
- }
8098
- },
8099
- OnceExit: () => {
8100
- mutations.forEach(mutation => {
8101
- mutation();
8102
- });
8103
- }
8104
- };
8105
- }
8106
- };
8107
- };
8108
- postCssPluginUrlVisitor.postcss = true;
8109
- const walkUrls = (parsed, {
8110
- stringifyCssNodes,
8111
- visitor
8112
- }) => {
8113
- parsed.walk(node => {
8114
- // https://github.com/andyjansson/postcss-functions
8115
- if (isUrlFunctionNode(node)) {
8116
- const {
8117
- nodes
8118
- } = node;
8119
- const [urlNode] = nodes;
8120
- const url = urlNode && urlNode.type === "string" ? urlNode.value : stringifyCssNodes(nodes);
8121
- visitor({
8122
- url: url.trim(),
8123
- urlNode
8124
- });
8125
- return;
8126
- }
8127
- if (isImageSetFunctionNode(node)) {
8128
- Array.from(node.nodes).forEach(childNode => {
8129
- if (childNode.type === "string") {
8130
- visitor({
8131
- url: childNode.value.trim(),
8132
- urlNode: childNode
8133
- });
8134
- return;
8135
- }
8136
- if (isUrlFunctionNode(node)) {
8137
- const {
8138
- nodes
8139
- } = childNode;
8140
- const [urlNode] = nodes;
8141
- const url = urlNode && urlNode.type === "string" ? urlNode.value : stringifyCssNodes(nodes);
8142
- visitor({
8143
- url: url.trim(),
8144
- urlNode
8145
- });
8146
- return;
8147
- }
8148
- });
8149
- }
8150
- });
8151
- };
8152
- const isUrlFunctionNode = node => {
8153
- return node.type === "function" && /^url$/i.test(node.value);
8154
- };
8155
- const isImageSetFunctionNode = node => {
8156
- return node.type === "function" && /^(?:-webkit-)?image-set$/i.test(node.value);
8157
- };
8158
- const isDataUrl = url => {
8159
- return /data:[^\n\r;]+?(?:;charset=[^\n\r;]+?)?;base64,([\d+/A-Za-z]+={0,2})/.test(url);
8160
- };
8161
-
8162
- const createJsParseError = ({
8163
- message,
8164
- reasonCode,
8165
- url,
8166
- line,
8167
- column
8168
- }) => {
8169
- const parseError = new Error(message);
8170
- parseError.reasonCode = reasonCode;
8171
- parseError.code = "PARSE_ERROR";
8172
- parseError.url = url;
8173
- parseError.line = line;
8174
- parseError.column = column;
8175
- return parseError;
8176
- };
8177
-
8178
- /*
8179
- * Useful when writin a babel plugin:
8180
- * - https://astexplorer.net/
8181
- * - https://bvaughn.github.io/babel-repl
8182
- */
8183
- const applyBabelPlugins = async ({
8184
- babelPlugins,
8185
- urlInfo,
8186
- ast,
8187
- options = {}
8188
- }) => {
8189
- const sourceType = {
8190
- js_module: "module",
8191
- js_classic: "classic",
8192
- [urlInfo.type]: undefined
8193
- }[urlInfo.type];
8194
- const url = urlInfo.originalUrl;
8195
- const generatedUrl = urlInfo.generatedUrl;
8196
- const content = urlInfo.content;
8197
- if (babelPlugins.length === 0) {
8198
- return {
8199
- code: content
8200
- };
8201
- }
8202
- const {
8203
- transformAsync,
8204
- transformFromAstAsync
8205
- } = await import("@babel/core");
8206
- const sourceFileName = url.startsWith("file:") ? fileURLToPath(url) : undefined;
8207
- options = {
8208
- ast: false,
8209
- // https://babeljs.io/docs/en/options#source-map-options
8210
- sourceMaps: true,
8211
- sourceFileName,
8212
- filename: generatedUrl ? generatedUrl.startsWith("file:") ? fileURLToPath(url) : undefined : sourceFileName,
8213
- configFile: false,
8214
- babelrc: false,
8215
- highlightCode: false,
8216
- // consider using startColumn and startLine for inline scripts?
8217
- // see https://github.com/babel/babel/blob/3ee9db7afe741f4d2f7933c519d8e7672fccb08d/packages/babel-parser/src/options.js#L36-L39
8218
- parserOpts: {
8219
- sourceType,
8220
- // allowAwaitOutsideFunction: true,
8221
- plugins: [
8222
- // "importMeta",
8223
- // "topLevelAwait",
8224
- "dynamicImport", "importAssertions", "jsx", "classProperties", "classPrivateProperties", "classPrivateMethods", ...(useTypeScriptExtension(url) ? ["typescript"] : []), ...(options.parserPlugins || [])].filter(Boolean)
8225
- },
8226
- generatorOpts: {
8227
- compact: false
8228
- },
8229
- plugins: babelPlugins,
8230
- ...options
8231
- };
8232
- try {
8233
- if (ast) {
8234
- const result = await transformFromAstAsync(ast, content, options);
8235
- return result;
8236
- }
8237
- const result = await transformAsync(content, options);
8238
- return result;
8239
- } catch (error) {
8240
- if (error && error.code === "BABEL_PARSE_ERROR") {
8241
- throw createJsParseError({
8242
- message: error.message,
8243
- reasonCode: error.reasonCode,
8244
- content,
8245
- url,
8246
- line: error.loc.line,
8247
- column: error.loc.column
8248
- });
8249
- }
8250
- throw error;
8251
- }
8252
- };
8253
- const useTypeScriptExtension = url => {
8254
- const {
8255
- pathname
8256
- } = new URL(url);
8257
- return pathname.endsWith(".ts") || pathname.endsWith(".tsx");
8258
- };
8259
-
8260
- // const pattern = [
8261
- // "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
8262
- // "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
8263
- // ].join("|")
8264
- // const ansiRegex = new RegExp(pattern, "g")
8265
-
8266
- // https://github.com/babel/babel/tree/master/packages/babel-helper-module-imports
8267
- const injectJsImport = ({
8268
- programPath,
8269
- namespace,
8270
- name,
8271
- from,
8272
- nameHint,
8273
- sideEffect
8274
- }) => {
8275
- const {
8276
- addNamespace,
8277
- addDefault,
8278
- addNamed,
8279
- addSideEffect
8280
- } = require$1("@babel/helper-module-imports");
8281
- if (namespace) {
8282
- return addNamespace(programPath, from, {
8283
- nameHint
8284
- });
8285
- }
8286
- if (name) {
8287
- return addNamed(programPath, name, from);
8288
- }
8289
- if (sideEffect) {
8290
- return addSideEffect(programPath, from);
8291
- }
8292
- return addDefault(programPath, from, {
8293
- nameHint
8294
- });
8295
- };
8296
-
8297
- let AcornParser;
8298
- let _getLineInfo;
8299
- const parseJsWithAcorn = async ({
8300
- js,
8301
- url,
8302
- isJsModule
8303
- }) => {
8304
- await initAcornParser();
8305
- try {
8306
- // https://github.com/acornjs/acorn/tree/master/acorn#interface
8307
- const jsAst = AcornParser.parse(js, {
8308
- locations: true,
8309
- allowAwaitOutsideFunction: true,
8310
- sourceType: isJsModule ? "module" : "script",
8311
- ecmaVersion: 2022
8312
- });
8313
- return jsAst;
8314
- } catch (e) {
8315
- if (e && e.name === "SyntaxError") {
8316
- const {
8317
- line,
8318
- column
8319
- } = _getLineInfo(js, e.raisedAt);
8320
- throw createJsParseError({
8321
- message: e.message,
8322
- url,
8323
- line,
8324
- column
8325
- });
8326
- }
8327
- throw e;
8328
- }
8329
- };
8330
- const initAcornParser = async () => {
8331
- if (AcornParser) {
8332
- return;
8333
- }
8334
- const {
8335
- Parser,
8336
- getLineInfo
8337
- } = await import("acorn");
8338
- const {
8339
- importAssertions
8340
- } = await import("acorn-import-assertions");
8341
- AcornParser = Parser.extend(importAssertions);
8342
- _getLineInfo = getLineInfo;
8343
- };
8344
-
8345
- const getTypePropertyNode$1 = node => {
8346
- if (node.type !== "ObjectExpression") {
8347
- return null;
8348
- }
8349
- const {
8350
- properties
8351
- } = node;
8352
- return properties.find(property => {
8353
- return property.type === "Property" && property.key.type === "Identifier" && property.key.name === "type";
8354
- });
8355
- };
8356
- const isStringLiteralNode = node => {
8357
- return node.type === "Literal" && typeof node.value === "string";
8358
- };
8359
-
8360
- const analyzeImportDeclaration = (node, {
8361
- onUrl
8362
- }) => {
8363
- const specifierNode = node.source;
8364
- const assertionInfo = extractImportAssertionsInfo(node);
8365
- onUrl({
8366
- type: "js_import",
8367
- subtype: "import_static",
8368
- specifier: specifierNode.value,
8369
- specifierStart: specifierNode.start,
8370
- specifierEnd: specifierNode.end,
8371
- specifierLine: specifierNode.loc.start.line,
8372
- specifierColumn: specifierNode.loc.start.column,
8373
- expectedType: assertionInfo ? assertionInfo.assert.type : "js_module",
8374
- ...assertionInfo
8375
- });
8376
- };
8377
- const analyzeImportExpression = (node, {
8378
- onUrl
8379
- }) => {
8380
- const specifierNode = node.source;
8381
- if (!isStringLiteralNode(specifierNode)) {
8382
- return;
8383
- }
8384
- const assertionInfo = extractImportAssertionsInfo(node);
8385
- onUrl({
8386
- type: "js_import",
8387
- subtype: "import_dynamic",
8388
- specifier: specifierNode.value,
8389
- specifierStart: specifierNode.start,
8390
- specifierEnd: specifierNode.end,
8391
- specifierLine: specifierNode.loc.start.line,
8392
- specifierColumn: specifierNode.loc.start.column,
8393
- expectedType: assertionInfo ? assertionInfo.assert.type : "js_module",
8394
- ...assertionInfo
8395
- });
8396
- };
8397
- const analyzeExportNamedDeclaration = (node, {
8398
- onUrl
8399
- }) => {
8400
- const specifierNode = node.source;
8401
- if (!specifierNode) {
8402
- // This export has no "source", so it's probably
8403
- // a local variable or function, e.g.
8404
- // export { varName }
8405
- // export const constName = ...
8406
- // export function funcName() {}
8407
- return;
8408
- }
8409
- onUrl({
8410
- type: "js_import",
8411
- subtype: "export_named",
8412
- specifier: specifierNode.value,
8413
- specifierStart: specifierNode.start,
8414
- specifierEnd: specifierNode.end,
8415
- specifierLine: specifierNode.loc.start.line,
8416
- specifierColumn: specifierNode.loc.start.column
8417
- });
8418
- };
8419
- const analyzeExportAllDeclaration = (node, {
8420
- onUrl
8421
- }) => {
8422
- const specifierNode = node.source;
8423
- onUrl({
8424
- type: "js_import",
8425
- subtype: "export_all",
8426
- specifier: specifierNode.value,
8427
- specifierStart: specifierNode.start,
8428
- specifierEnd: specifierNode.end,
8429
- specifierLine: specifierNode.loc.start.line,
8430
- specifierColumn: specifierNode.loc.start.column
8431
- });
8432
- };
8433
- const extractImportAssertionsInfo = node => {
8434
- if (node.type === "ImportDeclaration") {
8435
- // static import
8436
- const {
8437
- assertions
8438
- } = node;
8439
- if (!assertions) {
8440
- return null;
8441
- }
8442
- if (assertions.length === 0) {
8443
- return null;
8444
- }
8445
- const typeAssertionNode = assertions.find(assertion => assertion.key.name === "type");
8446
- if (!typeAssertionNode) {
8447
- return null;
8448
- }
8449
- const typeNode = typeAssertionNode.value;
8450
- if (!isStringLiteralNode(typeNode)) {
8451
- return null;
8452
- }
8453
- return {
8454
- assertNode: typeAssertionNode,
8455
- assert: {
8456
- type: typeNode.value
8457
- }
8458
- };
8459
- }
8460
- // dynamic import
8461
- const args = node.arguments;
8462
- if (!args) {
8463
- // acorn keeps node.arguments undefined for dynamic import without a second argument
8464
- return null;
8465
- }
8466
- const firstArgNode = args[0];
8467
- if (!firstArgNode) {
8468
- return null;
8469
- }
8470
- const {
8471
- properties
8472
- } = firstArgNode;
8473
- const assertProperty = properties.find(property => {
8474
- return property.key.name === "assert";
8475
- });
8476
- if (!assertProperty) {
8477
- return null;
8478
- }
8479
- const assertValueNode = assertProperty.value;
8480
- if (assertValueNode.type !== "ObjectExpression") {
8481
- return null;
8482
- }
8483
- const assertValueProperties = assertValueNode.properties;
8484
- const typePropertyNode = assertValueProperties.find(property => {
8485
- return property.key.name === "type";
8486
- });
8487
- if (!typePropertyNode) {
8488
- return null;
8489
- }
8490
- const typePropertyValue = typePropertyNode.value;
8491
- if (!isStringLiteralNode(typePropertyValue)) {
8492
- return null;
8493
- }
8494
- return {
8495
- assertNode: firstArgNode,
8496
- assert: {
8497
- type: typePropertyValue.value
8498
- }
8499
- };
8500
- };
8501
-
8502
- const isImportMetaResolveCall = node => {
8503
- return node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "MetaProperty" && node.callee.property.type === "Identifier" && node.callee.property.name === "resolve";
8504
- };
8505
- const analyzeImportMetaResolveCall = (node, {
8506
- onUrl
8507
- }) => {
8508
- const firstArg = node.arguments[0];
8509
- if (firstArg && isStringLiteralNode(firstArg)) {
8510
- onUrl({
8511
- node,
8512
- type: "js_import",
8513
- subtype: "import_meta_resolve",
8514
- specifier: firstArg.value,
8515
- specifierStart: firstArg.start,
8516
- specifierEnd: firstArg.end,
8517
- specifierLine: firstArg.loc.start.line,
8518
- specifierColumn: firstArg.loc.start.column
8519
- });
8520
- }
8521
- };
8522
-
8523
- const isNewUrlCall = node => {
8524
- return node.type === "NewExpression" && node.callee.type === "Identifier" && node.callee.name === "URL";
8525
- };
8526
- const analyzeNewUrlCall = (node, {
8527
- isJsModule,
8528
- onUrl
8529
- }) => {
8530
- if (node.arguments.length === 1) {
8531
- const firstArgNode = node.arguments[0];
8532
- const urlType = analyzeUrlNodeType(firstArgNode, {
8533
- isJsModule
8534
- });
8535
- if (urlType === "StringLiteral") {
8536
- const specifierNode = firstArgNode;
8537
- onUrl({
8538
- type: "js_url",
8539
- subtype: "new_url_first_arg",
8540
- specifier: specifierNode.value,
8541
- specifierStart: specifierNode.start,
8542
- specifierEnd: specifierNode.end,
8543
- specifierLine: specifierNode.loc.start.line,
8544
- specifierColumn: specifierNode.loc.start.column
8545
- });
8546
- }
8547
- return;
8548
- }
8549
- if (node.arguments.length === 2) {
8550
- const firstArgNode = node.arguments[0];
8551
- const secondArgNode = node.arguments[1];
8552
- const baseUrlType = analyzeUrlNodeType(secondArgNode, {
8553
- isJsModule
8554
- });
8555
- if (baseUrlType) {
8556
- // we can understand the second argument
8557
- if (baseUrlType === "StringLiteral" && secondArgNode.value === "file:///") {
8558
- // ignore new URL(specifier, "file:///")
8559
- return;
8560
- }
8561
- const urlType = analyzeUrlNodeType(firstArgNode, {
8562
- isJsModule
8563
- });
8564
- if (urlType === "StringLiteral") {
8565
- // we can understand the first argument
8566
- const specifierNode = firstArgNode;
8567
- onUrl({
8568
- type: "js_url",
8569
- subtype: "new_url_first_arg",
8570
- specifier: specifierNode.value,
8571
- specifierStart: specifierNode.start,
8572
- specifierEnd: specifierNode.end,
8573
- specifierLine: specifierNode.loc.start.line,
8574
- specifierColumn: specifierNode.loc.start.column,
8575
- baseUrlType,
8576
- baseUrl: baseUrlType === "StringLiteral" ? secondArgNode.value : undefined
8577
- });
8578
- }
8579
- if (baseUrlType === "StringLiteral") {
8580
- const specifierNode = secondArgNode;
8581
- onUrl({
8582
- type: "js_url",
8583
- subtype: "new_url_second_arg",
8584
- specifier: specifierNode.value,
8585
- specifierStart: specifierNode.start,
8586
- specifierEnd: specifierNode.end,
8587
- specifierLine: specifierNode.loc.start.line,
8588
- specifierColumn: specifierNode.loc.start.column
8589
- });
8590
- }
8591
- }
8592
- }
8593
- };
8594
- const analyzeUrlNodeType = (secondArgNode, {
8595
- isJsModule
8596
- }) => {
8597
- if (isStringLiteralNode(secondArgNode)) {
8598
- return "StringLiteral";
8599
- }
8600
- if (isImportMetaUrl(secondArgNode)) {
8601
- return "import.meta.url";
8602
- }
8603
- if (isWindowLocation(secondArgNode)) {
8604
- return "window.location";
8605
- }
8606
- if (isWindowOrigin(secondArgNode)) {
8607
- return "window.origin";
8608
- }
8609
- if (!isJsModule && isContextMetaUrlFromSystemJs(secondArgNode)) {
8610
- return "context.meta.url";
8611
- }
8612
- if (!isJsModule) {
8613
- if (isDocumentCurrentScriptSrc(secondArgNode)) {
8614
- return "document.currentScript.src";
8615
- }
8616
- // new URL('specifier', document.currentScript.src)
8617
- // becomes
8618
- // var _currentUrl = document.currentScript.src
8619
- // new URL('specifier', currentUrl)
8620
- // (search for scope.generateUidIdentifier("currentUrl")
8621
- if (secondArgNode.type === "Identifier") {
8622
- return "document.currentScript.src";
8623
- }
8624
- }
8625
- return null;
8626
- };
8627
- const isImportMetaUrl = node => {
8628
- return node.type === "MemberExpression" && node.object.type === "MetaProperty" && node.property.type === "Identifier" && node.property.name === "url";
8629
- };
8630
- const isWindowLocation = node => {
8631
- return node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === "window" && node.property.type === "Identifier" && node.property.name === "location";
8632
- };
8633
- const isWindowOrigin = node => {
8634
- return node.type === "MemberExpression" && node.object.type === "Identifier" && node.object.name === "window" && node.property.type === "Identifier" && node.property.name === "origin";
8635
- };
8636
- const isContextMetaUrlFromSystemJs = node => {
8637
- return node.type === "MemberExpression" && node.object.type === "MemberExpression" && node.object.object.type === "Identifier" &&
8638
- // because of minification we can't assume _context.
8639
- // so anything matching "*.meta.url" (in the context of new URL())
8640
- // will be assumed to be the equivalent to "import.meta.url"
8641
- // node.object.object.name === "_context" &&
8642
- node.object.property.type === "Identifier" && node.object.property.name === "meta" && node.property.type === "Identifier" && node.property.name === "url";
8643
- };
8644
- const isDocumentCurrentScriptSrc = node => {
8645
- return node.type === "MemberExpression" && node.object.type === "MemberExpression" && node.object.object.type === "Identifier" && node.object.object.name === "document" && node.object.property.type === "Identifier" && node.object.property.name === "currentScript" && node.property.type === "Identifier" && node.property.name === "src";
8646
- };
8647
-
8648
- const isNewWorkerCall = node => {
8649
- return node.type === "NewExpression" && node.callee.type === "Identifier" && node.callee.name === "Worker";
8650
- };
8651
- const analyzeNewWorkerCall = (node, {
8652
- isJsModule,
8653
- onUrl
8654
- }) => {
8655
- analyzeWorkerCallArguments(node, {
8656
- isJsModule,
8657
- onUrl,
8658
- referenceSubtype: "new_worker_first_arg",
8659
- expectedSubtype: "worker"
8660
- });
8661
- };
8662
- const isNewSharedWorkerCall = node => {
8663
- return node.type === "NewExpression" && node.callee.type === "Identifier" && node.callee.name === "SharedWorker";
8664
- };
8665
- const analyzeNewSharedWorkerCall = (node, {
8666
- isJsModule,
8667
- onUrl
8668
- }) => {
8669
- analyzeWorkerCallArguments(node, {
8670
- isJsModule,
8671
- onUrl,
8672
- referenceSubtype: "new_shared_worker_first_arg",
8673
- expectedSubtype: "shared_worker"
8674
- });
8675
- };
8676
- const isServiceWorkerRegisterCall = node => {
8677
- if (node.type !== "CallExpression") {
8678
- return false;
8679
- }
8680
- const callee = node.callee;
8681
- if (callee.type === "MemberExpression" && callee.property.type === "Identifier" && callee.property.name === "register") {
8682
- const parentObject = callee.object;
8683
- if (parentObject.type === "MemberExpression") {
8684
- const parentProperty = parentObject.property;
8685
- if (parentProperty.type === "Identifier" && parentProperty.name === "serviceWorker") {
8686
- const grandParentObject = parentObject.object;
8687
- if (grandParentObject.type === "MemberExpression") {
8688
- // window.navigator.serviceWorker.register
8689
- const grandParentProperty = grandParentObject.property;
8690
- if (grandParentProperty.type === "Identifier" && grandParentProperty.name === "navigator") {
8691
- const ancestorObject = grandParentObject.object;
8692
- if (ancestorObject.type === "Identifier" && ancestorObject.name === "window") {
8693
- return true;
8694
- }
8695
- }
8696
- }
8697
- if (grandParentObject.type === "Identifier") {
8698
- // navigator.serviceWorker.register
8699
- if (grandParentObject.name === "navigator") {
8700
- return true;
8701
- }
8702
- }
8703
- }
8704
- }
8705
- }
8706
- return false;
8707
- };
8708
- const analyzeServiceWorkerRegisterCall = (node, {
8709
- isJsModule,
8710
- onUrl
8711
- }) => {
8712
- analyzeWorkerCallArguments(node, {
8713
- isJsModule,
8714
- onUrl,
8715
- referenceSubtype: "service_worker_register_first_arg",
8716
- expectedSubtype: "service_worker"
8717
- });
8718
- };
8719
- const analyzeWorkerCallArguments = (node, {
8720
- isJsModule,
8721
- onUrl,
8722
- referenceSubtype,
8723
- expectedSubtype
8724
- }) => {
8725
- let expectedType = "js_classic";
8726
- let typePropertyNode;
8727
- const secondArgNode = node.arguments[1];
8728
- if (secondArgNode) {
8729
- typePropertyNode = getTypePropertyNode$1(secondArgNode);
8730
- if (typePropertyNode) {
8731
- const typePropertyValueNode = typePropertyNode.value;
8732
- if (isStringLiteralNode(typePropertyValueNode)) {
8733
- const typePropertyValue = typePropertyValueNode.value;
8734
- if (typePropertyValue === "module") {
8735
- expectedType = "js_module";
8736
- }
8737
- }
8738
- }
8739
- }
8740
- const firstArgNode = node.arguments[0];
8741
- if (isStringLiteralNode(firstArgNode)) {
8742
- const specifierNode = firstArgNode;
8743
- onUrl({
8744
- type: "js_url",
8745
- subtype: referenceSubtype,
8746
- expectedType,
8747
- expectedSubtype,
8748
- typePropertyNode,
8749
- specifier: specifierNode.value,
8750
- specifierStart: specifierNode.start,
8751
- specifierEnd: specifierNode.end,
8752
- specifierLine: specifierNode.loc.start.line,
8753
- specifierColumn: specifierNode.loc.start.column
8754
- });
8755
- return;
8756
- }
8757
- if (isNewUrlCall(firstArgNode)) {
8758
- analyzeNewUrlCall(firstArgNode, {
8759
- isJsModule,
8760
- onUrl: mention => {
8761
- Object.assign(mention, {
8762
- expectedType,
8763
- expectedSubtype,
8764
- typePropertyNode
8765
- });
8766
- onUrl(mention);
8767
- }
8768
- });
8769
- return;
8770
- }
8771
- if (isJsModule && isImportMetaResolveCall(firstArgNode)) {
8772
- analyzeImportMetaResolveCall(firstArgNode, {
8773
- onUrl: mention => {
8774
- Object.assign(mention, {
8775
- expectedType,
8776
- expectedSubtype,
8777
- typePropertyNode
8778
- });
8779
- onUrl(mention);
8780
- }
8781
- });
8782
- return;
8783
- }
8784
- };
8785
-
8786
- const isImportScriptsCall = node => {
8787
- const callee = node.callee;
8788
- if (callee.type === "Identifier" && callee.name === "importScripts") {
8789
- return true;
8790
- }
8791
- return callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === "self" && callee.property.type === "Identifier" && callee.property.name === "importScripts";
8792
- };
8793
- const analyzeImportScriptCalls = (node, {
8794
- onUrl
8795
- }) => {
8796
- node.arguments.forEach(arg => {
8797
- if (isStringLiteralNode(arg)) {
8798
- const specifierNode = arg;
8799
- onUrl({
8800
- type: "js_url",
8801
- subtype: "self_import_scripts_arg",
8802
- expectedType: "js_classic",
8803
- specifier: specifierNode.value,
8804
- specifierStart: specifierNode.start,
8805
- specifierEnd: specifierNode.end,
8806
- specifierLine: specifierNode.loc.start.line,
8807
- specifierColumn: specifierNode.loc.start.column
8808
- });
8809
- }
8810
- });
8811
- };
8812
-
8813
- const isSystemRegisterCall = node => {
8814
- const callee = node.callee;
8815
- return callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === "System" && callee.property.type === "Identifier" && callee.property.name === "register";
8816
- };
8817
- const analyzeSystemRegisterCall = (node, {
8818
- onUrl
8819
- }) => {
8820
- const firstArgNode = node.arguments[0];
8821
- if (firstArgNode.type === "ArrayExpression") {
8822
- analyzeSystemRegisterDeps(firstArgNode, {
8823
- onUrl
8824
- });
8825
- return;
8826
- }
8827
- if (isStringLiteralNode(firstArgNode)) {
8828
- const secondArgNode = node.arguments[1];
8829
- if (secondArgNode.type === "ArrayExpression") {
8830
- analyzeSystemRegisterDeps(secondArgNode, {
8831
- onUrl
8832
- });
8833
- return;
8834
- }
8835
- }
8836
- };
8837
- const analyzeSystemRegisterDeps = (node, {
8838
- onUrl
8839
- }) => {
8840
- const elements = node.elements;
8841
- elements.forEach(element => {
8842
- if (isStringLiteralNode(element)) {
8843
- const specifierNode = element;
8844
- onUrl({
8845
- type: "js_url",
8846
- subtype: "system_register_arg",
8847
- expectedType: "js_classic",
8848
- specifier: specifierNode.value,
8849
- specifierStart: specifierNode.start,
8850
- specifierEnd: specifierNode.end,
8851
- specifierLine: specifierNode.loc.start.line,
8852
- specifierColumn: specifierNode.loc.start.column
8853
- });
8854
- }
8855
- });
8856
- };
8857
- const isSystemImportCall = node => {
8858
- const callee = node.callee;
8859
- return callee.type === "MemberExpression" && callee.object.type === "Identifier" &&
8860
- // because of minification we can't assume _context.
8861
- // so anything matching "*.import()"
8862
- // will be assumed to be the equivalent to "import()"
8863
- // callee.object.name === "_context" &&
8864
- callee.property.type === "Identifier" && callee.property.name === "import";
8865
- };
8866
- const analyzeSystemImportCall = (node, {
8867
- onUrl
8868
- }) => {
8869
- const firstArgNode = node.arguments[0];
8870
- if (isStringLiteralNode(firstArgNode)) {
8871
- const specifierNode = firstArgNode;
8872
- onUrl({
8873
- type: "js_url",
8874
- subtype: "system_import_arg",
8875
- expectedType: "js_classic",
8876
- specifier: specifierNode.value,
8877
- specifierStart: specifierNode.start,
8878
- specifierEnd: specifierNode.end,
8879
- specifierLine: specifierNode.loc.start.line,
8880
- specifierColumn: specifierNode.loc.start.column
8881
- });
8882
- }
8883
- };
8884
- const isSystemResolveCall = node => {
8885
- const callee = node.callee;
8886
- return callee.type === "MemberExpression" && callee.object.type === "MemberExpression" && callee.object.object.type === "Identifier" &&
8887
- // because of minification we can't assume _context.
8888
- // so anything matching "*.meta.resolve()"
8889
- // will be assumed to be the equivalent to "meta.resolve()"
8890
- // callee.object.object.name === "_context" &&
8891
- callee.object.property.type === "Identifier" && callee.object.property.name === "meta" && callee.property.type === "Identifier" && callee.property.name === "resolve";
8892
- };
8893
- const analyzeSystemResolveCall = (node, {
8894
- onUrl
8895
- }) => {
8896
- const firstArgNode = node.arguments[0];
8897
- if (isStringLiteralNode(firstArgNode)) {
8898
- const specifierNode = firstArgNode;
8899
- onUrl({
8900
- type: "js_url",
8901
- subtype: "system_resolve_arg",
8902
- specifier: specifierNode.value,
8903
- specifierStart: specifierNode.start,
8904
- specifierEnd: specifierNode.end,
8905
- specifierLine: specifierNode.loc.start.line,
8906
- specifierColumn: specifierNode.loc.start.column
8907
- });
8908
- }
8909
- };
8910
-
8911
- const parseJsUrls = async ({
8912
- js,
8913
- url,
8914
- isJsModule = false,
8915
- isWebWorker = false
8916
- } = {}) => {
8917
- const jsUrls = [];
8918
- const jsAst = await parseJsWithAcorn({
8919
- js,
8920
- url,
8921
- isJsModule
8922
- });
8923
- const onUrl = jsUrl => {
8924
- jsUrls.push(jsUrl);
8925
- };
8926
- ancestor(jsAst, {
8927
- ImportDeclaration: node => {
8928
- analyzeImportDeclaration(node, {
8929
- onUrl
8930
- });
8931
- },
8932
- ImportExpression: node => {
8933
- analyzeImportExpression(node, {
8934
- onUrl
8935
- });
8936
- },
8937
- ExportNamedDeclaration: node => {
8938
- analyzeExportNamedDeclaration(node, {
8939
- onUrl
8940
- });
8941
- },
8942
- ExportAllDeclaration: node => {
8943
- analyzeExportAllDeclaration(node, {
8944
- onUrl
8945
- });
8946
- },
8947
- CallExpression: node => {
8948
- if (isJsModule && isImportMetaResolveCall(node)) {
8949
- analyzeImportMetaResolveCall(node, {
8950
- onUrl
8951
- });
8952
- return;
8953
- }
8954
- if (isServiceWorkerRegisterCall(node)) {
8955
- analyzeServiceWorkerRegisterCall(node, {
8956
- isJsModule,
8957
- onUrl
8958
- });
8959
- return;
8960
- }
8961
- if (isWebWorker && isImportScriptsCall(node)) {
8962
- analyzeImportScriptCalls(node, {
8963
- onUrl
8964
- });
8965
- return;
8966
- }
8967
- if (!isJsModule && isSystemRegisterCall(node)) {
8968
- analyzeSystemRegisterCall(node, {
8969
- onUrl
8970
- });
8971
- return;
8972
- }
8973
- if (!isJsModule && isSystemImportCall(node)) {
8974
- analyzeSystemImportCall(node, {
8975
- onUrl
8976
- });
8977
- return;
8978
- }
8979
- if (!isJsModule && isSystemResolveCall(node)) {
8980
- analyzeSystemResolveCall(node, {
8981
- onUrl
8982
- });
8983
- return;
8984
- }
8985
- },
8986
- NewExpression: (node, ancestors) => {
8987
- if (isNewWorkerCall(node)) {
8988
- analyzeNewWorkerCall(node, {
8989
- isJsModule,
8990
- onUrl
8991
- });
8992
- return;
8993
- }
8994
- if (isNewSharedWorkerCall(node)) {
8995
- analyzeNewSharedWorkerCall(node, {
8996
- isJsModule,
8997
- onUrl
8998
- });
8999
- return;
9000
- }
9001
- if (isNewUrlCall(node)) {
9002
- const parent = ancestors[ancestors.length - 2];
9003
- if (parent && (isNewWorkerCall(parent) || isNewSharedWorkerCall(parent) || isServiceWorkerRegisterCall(parent))) {
9004
- return;
9005
- }
9006
- analyzeNewUrlCall(node, {
9007
- isJsModule,
9008
- onUrl
9009
- });
9010
- return;
9011
- }
9012
- }
9013
- });
9014
- return jsUrls;
9015
- };
9016
-
9017
6970
  const urlSpecifierEncoding = {
9018
6971
  encode: reference => {
9019
6972
  const {
@@ -18567,7 +16520,7 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
18567
16520
  url: `node:${packageSpecifier}`
18568
16521
  };
18569
16522
  }
18570
- const {
16523
+ let {
18571
16524
  packageName,
18572
16525
  packageSubpath
18573
16526
  } = parsePackageSpecifier(packageSpecifier);
@@ -18577,6 +16530,10 @@ const applyPackageResolve = (packageSpecifier, resolutionContext) => {
18577
16530
  if (packageSubpath.endsWith("/")) {
18578
16531
  throw new Error("invalid module specifier");
18579
16532
  }
16533
+ const questionCharIndex = packageName.indexOf("?");
16534
+ if (questionCharIndex > -1) {
16535
+ packageName = packageName.slice(0, questionCharIndex);
16536
+ }
18580
16537
  const selfResolution = applyPackageSelfResolution(packageSubpath, {
18581
16538
  ...resolutionContext,
18582
16539
  packageName
@@ -19164,7 +17121,8 @@ const getExtensionsToTry = (magicExtensions, importer) => {
19164
17121
  */
19165
17122
  const createNodeEsmResolver = ({
19166
17123
  runtimeCompat,
19167
- packageConditions
17124
+ packageConditions,
17125
+ preservesSymlink
19168
17126
  }) => {
19169
17127
  const nodeRuntimeEnabled = Object.keys(runtimeCompat).includes("node");
19170
17128
  // https://nodejs.org/api/esm.html#resolver-algorithm-specification
@@ -19184,7 +17142,8 @@ const createNodeEsmResolver = ({
19184
17142
  } = applyNodeEsmResolution({
19185
17143
  conditions: packageConditions,
19186
17144
  parentUrl,
19187
- specifier: reference.specifier
17145
+ specifier: reference.specifier,
17146
+ preservesSymlink
19188
17147
  });
19189
17148
  if (context.dev) {
19190
17149
  const dependsOnPackageJson = type !== "relative_specifier" && type !== "absolute_specifier" && type !== "node_builtin_specifier";
@@ -19315,11 +17274,13 @@ const jsenvPluginUrlResolution = ({
19315
17274
  if (node_esm) {
19316
17275
  if (node_esm === true) node_esm = {};
19317
17276
  const {
19318
- packageConditions
17277
+ packageConditions,
17278
+ preservesSymlink
19319
17279
  } = node_esm;
19320
17280
  resolvers[urlType] = createNodeEsmResolver({
19321
17281
  runtimeCompat,
19322
- packageConditions
17282
+ packageConditions,
17283
+ preservesSymlink
19323
17284
  });
19324
17285
  } else if (web) {
19325
17286
  resolvers[urlType] = resolveUrlUsingWebResolution;
@@ -19327,7 +17288,8 @@ const jsenvPluginUrlResolution = ({
19327
17288
  });
19328
17289
  if (!resolvers.js_module) {
19329
17290
  resolvers.js_module = createNodeEsmResolver({
19330
- runtimeCompat
17291
+ runtimeCompat,
17292
+ preservesSymlink: true
19331
17293
  });
19332
17294
  }
19333
17295
  if (!resolvers["*"]) {
@@ -22739,6 +20701,9 @@ const jsenvPluginRibbon = ({
22739
20701
  appliesDuring: "dev",
22740
20702
  transformUrlContent: {
22741
20703
  html: (urlInfo, context) => {
20704
+ if (urlInfo.data.noribbon) {
20705
+ return null;
20706
+ }
22742
20707
  const {
22743
20708
  ribbon
22744
20709
  } = URL_META.applyAssociations({
@@ -22826,8 +20791,8 @@ const getCorePlugins = ({
22826
20791
  ...fileSystemMagicRedirection
22827
20792
  }), jsenvPluginHttpUrls(), jsenvPluginUrlResolution({
22828
20793
  runtimeCompat,
22829
- urlResolution,
22830
- clientMainFileUrl
20794
+ clientMainFileUrl,
20795
+ urlResolution
22831
20796
  }), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), jsenvPluginNodeRuntime({
22832
20797
  runtimeCompat
22833
20798
  }), jsenvPluginBundling(bundling), jsenvPluginMinification(minification), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({
@@ -23699,36 +21664,36 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
23699
21664
  }
23700
21665
  if (rawUrlInfo.isEntryPoint) {
23701
21666
  addToBundlerIfAny(rawUrlInfo);
23702
- if (rawUrlInfo.type === "html") {
23703
- rawUrlInfo.dependencies.forEach(dependencyUrl => {
23704
- const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl);
23705
- if (dependencyUrlInfo.isInline) {
23706
- if (dependencyUrlInfo.type === "js_module") {
23707
- // bundle inline script type module deps
23708
- dependencyUrlInfo.references.forEach(inlineScriptRef => {
23709
- if (inlineScriptRef.type === "js_import") {
23710
- const inlineUrlInfo = rawGraph.getUrlInfo(inlineScriptRef.url);
23711
- addToBundlerIfAny(inlineUrlInfo);
23712
- }
23713
- });
23714
- }
23715
- // inline content cannot be bundled
23716
- return;
21667
+ }
21668
+ if (rawUrlInfo.type === "html") {
21669
+ rawUrlInfo.dependencies.forEach(dependencyUrl => {
21670
+ const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl);
21671
+ if (dependencyUrlInfo.isInline) {
21672
+ if (dependencyUrlInfo.type === "js_module") {
21673
+ // bundle inline script type module deps
21674
+ dependencyUrlInfo.references.forEach(inlineScriptRef => {
21675
+ if (inlineScriptRef.type === "js_import") {
21676
+ const inlineUrlInfo = rawGraph.getUrlInfo(inlineScriptRef.url);
21677
+ addToBundlerIfAny(inlineUrlInfo);
21678
+ }
21679
+ });
23717
21680
  }
23718
- addToBundlerIfAny(dependencyUrlInfo);
23719
- });
23720
- rawUrlInfo.references.forEach(reference => {
23721
- if (reference.isResourceHint && reference.expectedType === "js_module") {
23722
- const referencedUrlInfo = rawGraph.getUrlInfo(reference.url);
23723
- if (referencedUrlInfo &&
23724
- // something else than the resource hint is using this url
23725
- referencedUrlInfo.dependents.size > 0) {
23726
- addToBundlerIfAny(referencedUrlInfo);
23727
- }
21681
+ // inline content cannot be bundled
21682
+ return;
21683
+ }
21684
+ addToBundlerIfAny(dependencyUrlInfo);
21685
+ });
21686
+ rawUrlInfo.references.forEach(reference => {
21687
+ if (reference.isResourceHint && reference.expectedType === "js_module") {
21688
+ const referencedUrlInfo = rawGraph.getUrlInfo(reference.url);
21689
+ if (referencedUrlInfo &&
21690
+ // something else than the resource hint is using this url
21691
+ referencedUrlInfo.dependents.size > 0) {
21692
+ addToBundlerIfAny(referencedUrlInfo);
23728
21693
  }
23729
- });
23730
- return;
23731
- }
21694
+ }
21695
+ });
21696
+ return;
23732
21697
  }
23733
21698
  // File referenced with new URL('./file.js', import.meta.url)
23734
21699
  // are entry points that should be bundled