@jsenv/core 39.0.4 → 39.1.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.
@@ -13,7 +13,7 @@ import http from "node:http";
13
13
  import { Readable, Stream, Writable } from "node:stream";
14
14
  import { Http2ServerResponse } from "node:http2";
15
15
  import { lookup } from "node:dns";
16
- import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, parseJsUrls, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getHtmlNodeAttributePosition, parseSrcSet, getUrlForContentInsideHtml, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls, getUrlForContentInsideJs, analyzeLinkNode, findHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
16
+ import { injectJsImport, visitJsAstUntil, applyBabelPlugins, parseHtml, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, getHtmlNodeText, stringifyHtmlAst, setHtmlNodeAttributes, parseJsUrls, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, generateUrlForInlineContent, parseJsWithAcorn, getHtmlNodePosition, getHtmlNodeAttributePosition, parseSrcSet, getUrlForContentInsideHtml, removeHtmlNodeText, setHtmlNodeText, removeHtmlNode, parseCssUrls, getUrlForContentInsideJs, analyzeLinkNode, injectJsenvScript, findHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
17
17
  import { sourcemapConverter, createMagicSource, composeTwoSourcemaps, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
18
18
  import { createRequire } from "node:module";
19
19
  import { systemJsClientFileUrlDefault, convertJsModuleToJsClassic } from "@jsenv/js-module-fallback";
@@ -818,7 +818,7 @@ const createAnsi = ({ supported }) => {
818
818
  if (!color) {
819
819
  return text;
820
820
  }
821
- if (text && text.trim() === "") {
821
+ if (typeof text === "string" && text.trim() === "") {
822
822
  // cannot set color of blank chars
823
823
  return text;
824
824
  }
@@ -11441,10 +11441,10 @@ const prependJsClassicInHtml = (htmlUrlInfo, urlInfoToPrepend) => {
11441
11441
  htmlAst,
11442
11442
  createHtmlNode({
11443
11443
  tagName: "script",
11444
- textContent: urlInfoToPrepend.content,
11445
11444
  ...(urlInfoToPrepend.url
11446
11445
  ? { "inlined-from-src": urlInfoToPrepend.url }
11447
11446
  : {}),
11447
+ children: urlInfoToPrepend.content,
11448
11448
  }),
11449
11449
  "jsenv:core",
11450
11450
  );
@@ -12747,7 +12747,8 @@ const createPluginController = (
12747
12747
  key === "name" ||
12748
12748
  key === "appliesDuring" ||
12749
12749
  key === "init" ||
12750
- key === "serverEvents"
12750
+ key === "serverEvents" ||
12751
+ key === "mustStayFirst"
12751
12752
  ) {
12752
12753
  continue;
12753
12754
  }
@@ -12766,7 +12767,15 @@ const createPluginController = (
12766
12767
  value: hookValue,
12767
12768
  };
12768
12769
  if (position === "start") {
12769
- group.unshift(hook);
12770
+ let i = 0;
12771
+ while (i < group.length) {
12772
+ const before = group[i];
12773
+ if (!before.plugin.mustStayFirst) {
12774
+ break;
12775
+ }
12776
+ i++;
12777
+ }
12778
+ group.splice(i, 0, hook);
12770
12779
  } else {
12771
12780
  group.push(hook);
12772
12781
  }
@@ -12891,7 +12900,7 @@ const createPluginController = (
12891
12900
  }
12892
12901
  }
12893
12902
  };
12894
- const callAsyncHooks = async (hookName, info, callback) => {
12903
+ const callAsyncHooks = async (hookName, info, callback, options) => {
12895
12904
  const hooks = hookGroups[hookName];
12896
12905
  if (hooks) {
12897
12906
  for (const hook of hooks) {
@@ -12915,7 +12924,7 @@ const createPluginController = (
12915
12924
  }
12916
12925
  return null;
12917
12926
  };
12918
- const callAsyncHooksUntil = (hookName, info) => {
12927
+ const callAsyncHooksUntil = async (hookName, info, options) => {
12919
12928
  const hooks = hookGroups[hookName];
12920
12929
  if (!hooks) {
12921
12930
  return null;
@@ -12923,22 +12932,23 @@ const createPluginController = (
12923
12932
  if (hooks.length === 0) {
12924
12933
  return null;
12925
12934
  }
12926
- return new Promise((resolve, reject) => {
12927
- const visit = (index) => {
12928
- if (index >= hooks.length) {
12929
- return resolve();
12930
- }
12931
- const hook = hooks[index];
12932
- const returnValue = callAsyncHook(hook, info);
12933
- return Promise.resolve(returnValue).then((output) => {
12934
- if (output) {
12935
- return resolve(output);
12936
- }
12937
- return visit(index + 1);
12938
- }, reject);
12939
- };
12940
- visit(0);
12941
- });
12935
+ let result;
12936
+ let index = 0;
12937
+ const visit = async () => {
12938
+ if (index >= hooks.length) {
12939
+ return;
12940
+ }
12941
+ const hook = hooks[index];
12942
+ const returnValue = await callAsyncHook(hook, info);
12943
+ if (returnValue) {
12944
+ result = returnValue;
12945
+ return;
12946
+ }
12947
+ index++;
12948
+ await visit();
12949
+ };
12950
+ await visit();
12951
+ return result;
12942
12952
  };
12943
12953
 
12944
12954
  return {
@@ -12986,11 +12996,7 @@ const assertAndNormalizeReturnValue = (hook, returnValue, info) => {
12986
12996
  if (!returnValueAssertion.appliesTo.includes(hook.name)) {
12987
12997
  continue;
12988
12998
  }
12989
- const assertionResult = returnValueAssertion.assertion(
12990
- returnValue,
12991
- info,
12992
- hook,
12993
- );
12999
+ const assertionResult = returnValueAssertion.assertion(returnValue, info);
12994
13000
  if (assertionResult !== undefined) {
12995
13001
  // normalization
12996
13002
  returnValue = assertionResult;
@@ -13024,7 +13030,7 @@ const returnValueAssertions = [
13024
13030
  "finalizeUrlContent",
13025
13031
  "optimizeUrlContent",
13026
13032
  ],
13027
- assertion: (valueReturned, urlInfo, hook) => {
13033
+ assertion: (valueReturned, urlInfo) => {
13028
13034
  if (typeof valueReturned === "string" || Buffer.isBuffer(valueReturned)) {
13029
13035
  return { content: valueReturned };
13030
13036
  }
@@ -13033,12 +13039,6 @@ const returnValueAssertions = [
13033
13039
  if (urlInfo.url.startsWith("ignore:")) {
13034
13040
  return undefined;
13035
13041
  }
13036
- if (urlInfo.type === "html") {
13037
- const { scriptInjections } = valueReturned;
13038
- if (scriptInjections) {
13039
- return applyScriptInjections(urlInfo, scriptInjections, hook);
13040
- }
13041
- }
13042
13042
  if (typeof content !== "string" && !Buffer.isBuffer(content) && !body) {
13043
13043
  throw new Error(
13044
13044
  `Unexpected "content" returned by plugin: it must be a string or a buffer; got ${content}`,
@@ -13053,61 +13053,92 @@ const returnValueAssertions = [
13053
13053
  },
13054
13054
  ];
13055
13055
 
13056
- const applyScriptInjections = (htmlUrlInfo, scriptInjections, hook) => {
13057
- const htmlAst = parseHtml({
13058
- html: htmlUrlInfo.content,
13059
- url: htmlUrlInfo.url,
13060
- });
13056
+ const jsenvPluginHtmlSyntaxErrorFallback = () => {
13057
+ const htmlSyntaxErrorFileUrl = new URL(
13058
+ "./html/html_syntax_error.html",
13059
+ import.meta.url,
13060
+ );
13061
13061
 
13062
- scriptInjections.reverse().forEach((scriptInjection) => {
13063
- const { setup } = scriptInjection;
13064
- if (setup) {
13065
- const setupGlobalName = setup.name;
13066
- const setupParamSource = stringifyParams$1(setup.param, " ");
13067
- const inlineJs = `${setupGlobalName}({${setupParamSource}})`;
13068
- injectHtmlNodeAsEarlyAsPossible(
13069
- htmlAst,
13070
- createHtmlNode({
13071
- tagName: "script",
13072
- textContent: inlineJs,
13073
- }),
13074
- hook.plugin.name,
13075
- );
13076
- }
13077
- const scriptReference = htmlUrlInfo.dependencies.inject({
13078
- type: "script",
13079
- subtype: scriptInjection.type === "module" ? "js_module" : "js_classic",
13080
- expectedType:
13081
- scriptInjection.type === "module" ? "js_module" : "js_classic",
13082
- specifier: scriptInjection.src,
13083
- });
13084
- injectHtmlNodeAsEarlyAsPossible(
13085
- htmlAst,
13086
- createHtmlNode({
13087
- tagName: "script",
13088
- ...(scriptInjection.type === "module" ? { type: "module" } : {}),
13089
- src: scriptReference.generatedSpecifier,
13090
- }),
13091
- hook.plugin.name,
13092
- );
13093
- });
13094
- const htmlModified = stringifyHtmlAst(htmlAst);
13095
13062
  return {
13096
- content: htmlModified,
13063
+ mustStayFirst: true,
13064
+ name: "jsenv:html_syntax_error_fallback",
13065
+ appliesDuring: "dev",
13066
+ transformUrlContent: {
13067
+ html: (urlInfo) => {
13068
+ try {
13069
+ parseHtml({
13070
+ html: urlInfo.content,
13071
+ url: urlInfo.url,
13072
+ });
13073
+ return null;
13074
+ } catch (e) {
13075
+ if (e.code !== "PARSE_ERROR") {
13076
+ return null;
13077
+ }
13078
+ const line = e.line;
13079
+ const column = e.column;
13080
+ const htmlErrorContentFrame = generateContentFrame({
13081
+ content: urlInfo.content,
13082
+ line,
13083
+ column,
13084
+ });
13085
+ urlInfo.kitchen.context.logger
13086
+ .error(`Error while handling ${urlInfo.context.request ? urlInfo.context.request.url : urlInfo.url}:
13087
+ ${e.reasonCode}
13088
+ ${urlInfo.url}:${line}:${column}
13089
+ ${htmlErrorContentFrame}`);
13090
+ const html = generateHtmlForSyntaxError(e, {
13091
+ htmlUrl: urlInfo.url,
13092
+ rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
13093
+ htmlErrorContentFrame,
13094
+ htmlSyntaxErrorFileUrl,
13095
+ });
13096
+ return html;
13097
+ }
13098
+ },
13099
+ },
13097
13100
  };
13098
13101
  };
13099
13102
 
13100
- const stringifyParams$1 = (params, prefix = "") => {
13101
- const source = JSON.stringify(params, null, prefix);
13102
- if (prefix.length) {
13103
- // remove leading "{\n"
13104
- // remove leading prefix
13105
- // remove trailing "\n}"
13106
- return source.slice(2 + prefix.length, -2);
13107
- }
13108
- // remove leading "{"
13109
- // remove trailing "}"
13110
- return source.slice(1, -1);
13103
+ const generateHtmlForSyntaxError = (
13104
+ htmlSyntaxError,
13105
+ { htmlUrl, rootDirectoryUrl, htmlErrorContentFrame, htmlSyntaxErrorFileUrl },
13106
+ ) => {
13107
+ const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
13108
+ const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
13109
+ const { line, column } = htmlSyntaxError;
13110
+ const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
13111
+ const replacers = {
13112
+ fileRelativeUrl: htmlRelativeUrl,
13113
+ reasonCode: htmlSyntaxError.reasonCode,
13114
+ errorLinkHref: `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
13115
+ urlWithLineAndColumn,
13116
+ )}')`,
13117
+ errorLinkText: `${htmlRelativeUrl}:${line}:${column}`,
13118
+ syntaxError: escapeHtml(htmlErrorContentFrame),
13119
+ };
13120
+ const html = replacePlaceholders$2(htmlForSyntaxError, replacers);
13121
+ return html;
13122
+ };
13123
+ const escapeHtml = (string) => {
13124
+ return string
13125
+ .replace(/&/g, "&amp;")
13126
+ .replace(/</g, "&lt;")
13127
+ .replace(/>/g, "&gt;")
13128
+ .replace(/"/g, "&quot;")
13129
+ .replace(/'/g, "&#039;");
13130
+ };
13131
+ const replacePlaceholders$2 = (html, replacers) => {
13132
+ return html.replace(/\$\{(\w+)\}/g, (match, name) => {
13133
+ const replacer = replacers[name];
13134
+ if (replacer === undefined) {
13135
+ return match;
13136
+ }
13137
+ if (typeof replacer === "function") {
13138
+ return replacer();
13139
+ }
13140
+ return replacer;
13141
+ });
13111
13142
  };
13112
13143
 
13113
13144
  const defineGettersOnPropertiesDerivedFromOriginalContent = (
@@ -14092,6 +14123,7 @@ const createKitchen = ({
14092
14123
  initialPluginsMeta,
14093
14124
  );
14094
14125
  kitchen.pluginController = pluginController;
14126
+ pluginController.pushPlugin(jsenvPluginHtmlSyntaxErrorFallback());
14095
14127
  plugins.forEach((pluginEntry) => {
14096
14128
  pluginController.pushPlugin(pluginEntry);
14097
14129
  });
@@ -15821,11 +15853,6 @@ const applyDefaultExtension = ({ url, importer, defaultExtension }) => {
15821
15853
  return url
15822
15854
  };
15823
15855
 
15824
- const htmlSyntaxErrorFileUrl = new URL(
15825
- "./html/html_syntax_error.html",
15826
- import.meta.url,
15827
- );
15828
-
15829
15856
  const jsenvPluginHtmlReferenceAnalysis = ({
15830
15857
  inlineContent,
15831
15858
  inlineConvertedScript,
@@ -15933,41 +15960,10 @@ const jsenvPluginHtmlReferenceAnalysis = ({
15933
15960
  },
15934
15961
  html: async (urlInfo) => {
15935
15962
  let importmapFound = false;
15936
-
15937
- let htmlAst;
15938
- try {
15939
- htmlAst = parseHtml({
15940
- html: urlInfo.content,
15941
- url: urlInfo.url,
15942
- });
15943
- } catch (e) {
15944
- if (e.code === "PARSE_ERROR") {
15945
- const line = e.line;
15946
- const column = e.column;
15947
- const htmlErrorContentFrame = generateContentFrame({
15948
- content: urlInfo.content,
15949
- line,
15950
- column,
15951
- });
15952
- urlInfo.kitchen.context.logger
15953
- .error(`Error while handling ${urlInfo.context.request ? urlInfo.context.request.url : urlInfo.url}:
15954
- ${e.reasonCode}
15955
- ${urlInfo.url}:${line}:${column}
15956
- ${htmlErrorContentFrame}`);
15957
- const html = generateHtmlForSyntaxError(e, {
15958
- htmlUrl: urlInfo.url,
15959
- rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
15960
- htmlErrorContentFrame,
15961
- });
15962
- htmlAst = parseHtml({
15963
- html,
15964
- url: htmlSyntaxErrorFileUrl,
15965
- });
15966
- } else {
15967
- throw e;
15968
- }
15969
- }
15970
-
15963
+ const htmlAst = parseHtml({
15964
+ html: urlInfo.content,
15965
+ url: urlInfo.url,
15966
+ });
15971
15967
  const importmapLoaded = startLoadingImportmap(urlInfo);
15972
15968
 
15973
15969
  try {
@@ -16419,47 +16415,6 @@ const visitNonIgnoredHtmlNode = (htmlAst, visitors) => {
16419
16415
  visitHtmlNodes(htmlAst, visitorsInstrumented);
16420
16416
  };
16421
16417
 
16422
- const generateHtmlForSyntaxError = (
16423
- htmlSyntaxError,
16424
- { htmlUrl, rootDirectoryUrl, htmlErrorContentFrame },
16425
- ) => {
16426
- const htmlForSyntaxError = String(readFileSync(htmlSyntaxErrorFileUrl));
16427
- const htmlRelativeUrl = urlToRelativeUrl(htmlUrl, rootDirectoryUrl);
16428
- const { line, column } = htmlSyntaxError;
16429
- const urlWithLineAndColumn = `${htmlUrl}:${line}:${column}`;
16430
- const replacers = {
16431
- fileRelativeUrl: htmlRelativeUrl,
16432
- reasonCode: htmlSyntaxError.reasonCode,
16433
- errorLinkHref: `javascript:window.fetch('/__open_in_editor__/${encodeURIComponent(
16434
- urlWithLineAndColumn,
16435
- )}')`,
16436
- errorLinkText: `${htmlRelativeUrl}:${line}:${column}`,
16437
- syntaxError: escapeHtml(htmlErrorContentFrame),
16438
- };
16439
- const html = replacePlaceholders$2(htmlForSyntaxError, replacers);
16440
- return html;
16441
- };
16442
- const escapeHtml = (string) => {
16443
- return string
16444
- .replace(/&/g, "&amp;")
16445
- .replace(/</g, "&lt;")
16446
- .replace(/>/g, "&gt;")
16447
- .replace(/"/g, "&quot;")
16448
- .replace(/'/g, "&#039;");
16449
- };
16450
- const replacePlaceholders$2 = (html, replacers) => {
16451
- return html.replace(/\$\{(\w+)\}/g, (match, name) => {
16452
- const replacer = replacers[name];
16453
- if (replacer === undefined) {
16454
- return match;
16455
- }
16456
- if (typeof replacer === "function") {
16457
- return replacer();
16458
- }
16459
- return replacer;
16460
- });
16461
- };
16462
-
16463
16418
  const crossOriginCompatibleTagNames = ["script", "link", "img", "source"];
16464
16419
  const integrityCompatibleTagNames = ["script", "link", "img", "source"];
16465
16420
  const readFetchMetas = (node) => {
@@ -19709,29 +19664,22 @@ const jsenvPluginAutoreloadClient = () => {
19709
19664
  url: htmlUrlInfo.url,
19710
19665
  });
19711
19666
  const autoreloadClientReference = htmlUrlInfo.dependencies.inject({
19712
- type: "script",
19667
+ type: "js_import",
19713
19668
  subtype: "js_module",
19714
19669
  expectedType: "js_module",
19715
19670
  specifier: autoreloadClientFileUrl,
19716
19671
  });
19717
- const paramsJson = JSON.stringify(
19718
- {
19719
- mainFilePath: `/${htmlUrlInfo.kitchen.context.mainFilePath}`,
19672
+ injectJsenvScript(htmlAst, {
19673
+ type: "module",
19674
+ src: autoreloadClientReference.generatedSpecifier,
19675
+ initCall: {
19676
+ callee: "initAutoreload",
19677
+ params: {
19678
+ mainFilePath: `/${htmlUrlInfo.kitchen.context.mainFilePath}`,
19679
+ },
19720
19680
  },
19721
- null,
19722
- " ",
19723
- );
19724
- injectHtmlNodeAsEarlyAsPossible(
19725
- htmlAst,
19726
- createHtmlNode({
19727
- tagName: "script",
19728
- type: "module",
19729
- textContent: `import { initAutoreload } from "${autoreloadClientReference.generatedSpecifier}";
19730
-
19731
- initAutoreload(${paramsJson});`,
19732
- }),
19733
- "jsenv:autoreload_client",
19734
- );
19681
+ pluginName: "jsenv:autoreload_client",
19682
+ });
19735
19683
  const htmlModified = stringifyHtmlAst(htmlAst);
19736
19684
  return {
19737
19685
  content: htmlModified,
@@ -20161,27 +20109,22 @@ const jsenvPluginRibbon = ({
20161
20109
  url: urlInfo.url,
20162
20110
  });
20163
20111
  const ribbonClientFileReference = urlInfo.dependencies.inject({
20164
- type: "script",
20112
+ type: "js_import",
20165
20113
  subtype: "js_module",
20166
20114
  expectedType: "js_module",
20167
20115
  specifier: ribbonClientFileUrl.href,
20168
20116
  });
20169
- const paramsJson = JSON.stringify(
20170
- { text: urlInfo.context.dev ? "DEV" : "BUILD" },
20171
- null,
20172
- " ",
20173
- );
20174
- injectHtmlNodeAsEarlyAsPossible(
20175
- htmlAst,
20176
- createHtmlNode({
20177
- tagName: "script",
20178
- type: "module",
20179
- textContent: `import { injectRibbon } from "${ribbonClientFileReference.generatedSpecifier}";
20180
-
20181
- injectRibbon(${paramsJson});`,
20182
- }),
20183
- "jsenv:ribbon",
20184
- );
20117
+ injectJsenvScript(htmlAst, {
20118
+ type: "module",
20119
+ src: ribbonClientFileReference.generatedSpecifier,
20120
+ initCall: {
20121
+ callee: "injectRibbon",
20122
+ params: {
20123
+ text: urlInfo.context.dev ? "DEV" : "BUILD",
20124
+ },
20125
+ },
20126
+ pluginName: "jsenv:ribbon",
20127
+ });
20185
20128
  return stringifyHtmlAst(htmlAst);
20186
20129
  },
20187
20130
  },
@@ -20198,9 +20141,10 @@ const jsenvPluginCleanHTML = () => {
20198
20141
  html: urlInfo.content,
20199
20142
  url: urlInfo.url,
20200
20143
  });
20201
- return stringifyHtmlAst(htmlAst, {
20144
+ const htmlClean = stringifyHtmlAst(htmlAst, {
20202
20145
  cleanupPositionAttributes: true,
20203
20146
  });
20147
+ return htmlClean;
20204
20148
  },
20205
20149
  },
20206
20150
  };
@@ -20572,7 +20516,7 @@ const injectVersionMappingsAsImportmap = (urlInfo, versionMappings) => {
20572
20516
  createHtmlNode({
20573
20517
  tagName: "script",
20574
20518
  type: "importmap",
20575
- textContent: importmapMinification
20519
+ children: importmapMinification
20576
20520
  ? JSON.stringify({ imports: versionMappings })
20577
20521
  : JSON.stringify({ imports: versionMappings }, null, " "),
20578
20522
  }),
@@ -22484,6 +22428,7 @@ build ${entryPointKeys.length} entry points`);
22484
22428
  * to provide "serverEvents" used by other plugins
22485
22429
  */
22486
22430
 
22431
+
22487
22432
  const serverEventsClientFileUrl = new URL(
22488
22433
  "./js/server_events_client.js",
22489
22434
  import.meta.url,
@@ -22494,20 +22439,22 @@ const jsenvPluginServerEventsClientInjection = ({ logs = true }) => {
22494
22439
  name: "jsenv:server_events_client_injection",
22495
22440
  appliesDuring: "*",
22496
22441
  transformUrlContent: {
22497
- html: () => {
22498
- return {
22499
- scriptInjections: [
22500
- {
22501
- src: serverEventsClientFileUrl,
22502
- setup: {
22503
- name: "window.__server_events__.setup",
22504
- param: {
22505
- logs,
22506
- },
22507
- },
22442
+ html: (urlInfo) => {
22443
+ const htmlAst = parseHtml({
22444
+ html: urlInfo.content,
22445
+ url: urlInfo.url,
22446
+ });
22447
+ injectJsenvScript(htmlAst, {
22448
+ src: serverEventsClientFileUrl,
22449
+ initCall: {
22450
+ callee: "window.__server_events__.setup",
22451
+ params: {
22452
+ logs,
22508
22453
  },
22509
- ],
22510
- };
22454
+ },
22455
+ pluginName: "jsenv:server_events_client_injection",
22456
+ });
22457
+ return stringifyHtmlAst(htmlAst);
22511
22458
  },
22512
22459
  },
22513
22460
  };
@@ -22893,8 +22840,7 @@ const startDevServer = async ({
22893
22840
  const serverEventInit = allServerEvents[serverEventName];
22894
22841
  serverEventInit(serverEventInfo);
22895
22842
  });
22896
- // "pushPlugin" so that event source client connection can be put as early as possible in html
22897
- kitchen.pluginController.pushPlugin(
22843
+ kitchen.pluginController.unshiftPlugin(
22898
22844
  jsenvPluginServerEventsClientInjection(
22899
22845
  clientAutoreload.clientServerEventsConfig,
22900
22846
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "39.0.4",
3
+ "version": "39.1.0",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -66,17 +66,17 @@
66
66
  "dependencies": {
67
67
  "@financial-times/polyfill-useragent-normaliser": "1.10.2",
68
68
  "@jsenv/abort": "4.3.0",
69
- "@jsenv/ast": "6.1.4",
69
+ "@jsenv/ast": "6.2.1",
70
70
  "@jsenv/filesystem": "4.7.5",
71
- "@jsenv/humanize": "1.2.2",
71
+ "@jsenv/humanize": "1.2.3",
72
72
  "@jsenv/importmap": "1.2.1",
73
73
  "@jsenv/integrity": "0.0.2",
74
- "@jsenv/js-module-fallback": "1.3.21",
74
+ "@jsenv/js-module-fallback": "1.3.22",
75
75
  "@jsenv/node-esm-resolution": "1.0.2",
76
76
  "@jsenv/plugin-bundling": "2.6.15",
77
77
  "@jsenv/plugin-minification": "1.5.4",
78
- "@jsenv/plugin-supervisor": "1.4.16",
79
- "@jsenv/plugin-transpilation": "1.4.4",
78
+ "@jsenv/plugin-supervisor": "1.5.0",
79
+ "@jsenv/plugin-transpilation": "1.4.5",
80
80
  "@jsenv/runtime-compat": "1.3.0",
81
81
  "@jsenv/server": "15.2.12",
82
82
  "@jsenv/sourcemap": "1.2.13",
@@ -85,7 +85,7 @@
85
85
  "@jsenv/utils": "2.1.1"
86
86
  },
87
87
  "devDependencies": {
88
- "@babel/eslint-parser": "7.24.7",
88
+ "@babel/eslint-parser": "7.24.8",
89
89
  "@babel/plugin-syntax-import-attributes": "7.24.7",
90
90
  "@babel/plugin-syntax-optional-chaining-assign": "7.24.7",
91
91
  "@jsenv/assert": "./packages/independent/assert/",
@@ -74,7 +74,7 @@ export const injectVersionMappingsAsImportmap = (urlInfo, versionMappings) => {
74
74
  createHtmlNode({
75
75
  tagName: "script",
76
76
  type: "importmap",
77
- textContent: importmapMinification
77
+ children: importmapMinification
78
78
  ? JSON.stringify({ imports: versionMappings })
79
79
  : JSON.stringify({ imports: versionMappings }, null, " "),
80
80
  }),
@@ -366,8 +366,7 @@ export const startDevServer = async ({
366
366
  const serverEventInit = allServerEvents[serverEventName];
367
367
  serverEventInit(serverEventInfo);
368
368
  });
369
- // "pushPlugin" so that event source client connection can be put as early as possible in html
370
- kitchen.pluginController.pushPlugin(
369
+ kitchen.pluginController.unshiftPlugin(
371
370
  jsenvPluginServerEventsClientInjection(
372
371
  clientAutoreload.clientServerEventsConfig,
373
372
  ),
@@ -39,13 +39,13 @@ export const executeCommand = (
39
39
  commandProcess.stdout.on("data", (data) => {
40
40
  stdoutDatas.push(data);
41
41
  logger.debug(data);
42
- onStderr(data);
42
+ onStdout(data);
43
43
  });
44
44
  let stderrDatas = [];
45
45
  commandProcess.stderr.on("data", (data) => {
46
46
  stderrDatas.push(data);
47
47
  logger.debug(data);
48
- onStdout(data);
48
+ onStderr(data);
49
49
  });
50
50
  if (commandProcess.stdin) {
51
51
  commandProcess.stdin.on("error", (error) => {
@@ -13,6 +13,7 @@ import { RUNTIME_COMPAT } from "@jsenv/runtime-compat";
13
13
  import { createUrlGraph } from "./url_graph/url_graph.js";
14
14
  import { urlSpecifierEncoding } from "./url_graph/url_specifier_encoding.js";
15
15
  import { createPluginController } from "../plugins/plugin_controller.js";
16
+ import { jsenvPluginHtmlSyntaxErrorFallback } from "../plugins/html_syntax_error_fallback/jsenv_plugin_html_syntax_error_fallback.js";
16
17
  import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js";
17
18
  import {
18
19
  createResolveUrlError,
@@ -93,6 +94,7 @@ export const createKitchen = ({
93
94
  initialPluginsMeta,
94
95
  );
95
96
  kitchen.pluginController = pluginController;
97
+ pluginController.pushPlugin(jsenvPluginHtmlSyntaxErrorFallback());
96
98
  plugins.forEach((pluginEntry) => {
97
99
  pluginController.pushPlugin(pluginEntry);
98
100
  });
@@ -52,10 +52,10 @@ const prependJsClassicInHtml = (htmlUrlInfo, urlInfoToPrepend) => {
52
52
  htmlAst,
53
53
  createHtmlNode({
54
54
  tagName: "script",
55
- textContent: urlInfoToPrepend.content,
56
55
  ...(urlInfoToPrepend.url
57
56
  ? { "inlined-from-src": urlInfoToPrepend.url }
58
57
  : {}),
58
+ children: urlInfoToPrepend.content,
59
59
  }),
60
60
  "jsenv:core",
61
61
  );