@jsenv/core 24.2.1 → 24.3.3

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 (154) hide show
  1. package/dist/browser_runtime/browser_runtime-fbd309a1.js +5137 -0
  2. package/dist/browser_runtime/browser_runtime-fbd309a1.js.map +1064 -0
  3. package/dist/{jsenv_browser_system.js → browser_system/browser_system-29eda202.js} +12 -12
  4. package/dist/{jsenv_browser_system.js.map → browser_system/browser_system-29eda202.js.map} +64 -64
  5. package/dist/build_manifest.js +12 -0
  6. package/dist/compile_proxy/assets/s.js-749702e8.map +242 -0
  7. package/dist/compile_proxy/compile_proxy-405777e6.html +2074 -0
  8. package/dist/compile_proxy/compile_proxy.html__inline__20-39c0801c.js.map +385 -0
  9. package/dist/{jsenv_event_source_client.js → event_source_client/event_source_client-9f14c8b9.js} +39 -21
  10. package/dist/event_source_client/event_source_client-9f14c8b9.js.map +127 -0
  11. package/dist/redirector/assets/s.js-749702e8.map +242 -0
  12. package/dist/redirector/redirector-237cd168.html +2118 -0
  13. package/dist/redirector/redirector.html__inline__15-33acb0b9.js.map +390 -0
  14. package/dist/toolbar/assets/compilation.css-209d68b4.map +12 -0
  15. package/dist/toolbar/assets/eventsource.css-38cd0a36.map +12 -0
  16. package/dist/toolbar/assets/execution.css-0ebe522f.map +12 -0
  17. package/dist/toolbar/assets/focus.css-3f9c156d.map +12 -0
  18. package/dist/toolbar/assets/light-theme.css-78b19a80.map +12 -0
  19. package/dist/toolbar/assets/overflow-menu.css-d9688a1c.map +12 -0
  20. package/dist/toolbar/assets/s.js-749702e8.map +242 -0
  21. package/dist/toolbar/assets/settings.css-2b81b245.map +12 -0
  22. package/dist/toolbar/assets/toolbar.main.css-846920e9.map +28 -0
  23. package/dist/toolbar/assets/tooltip.css-03395ee6.map +12 -0
  24. package/dist/toolbar/toolbar-29e91dcd.html +4779 -0
  25. package/dist/toolbar/toolbar.main-53e1ab2b.js.map +795 -0
  26. package/dist/toolbar_injector/assets/jsenv-logo-188b9ca6.svg +95 -0
  27. package/dist/{jsenv_toolbar_injector.js → toolbar_injector/toolbar_injector-0af91b43.js} +87 -65
  28. package/dist/toolbar_injector/toolbar_injector-0af91b43.js.map +294 -0
  29. package/main.js +0 -1
  30. package/package.json +2 -1
  31. package/readme.md +10 -7
  32. package/src/buildProject.js +6 -2
  33. package/src/dev_server.js +26 -130
  34. package/src/execute.js +7 -10
  35. package/src/importUsingChildProcess.js +1 -1
  36. package/src/internal/{runtime/detectBrowser/detectBrowser.js → browser_detection/browser_detection.js} +0 -0
  37. package/src/internal/{runtime/detectBrowser → browser_detection}/detectAndroid.js +0 -0
  38. package/src/internal/{runtime/detectBrowser → browser_detection}/detectChrome.js +0 -0
  39. package/src/internal/{runtime/detectBrowser → browser_detection}/detectEdge.js +0 -0
  40. package/src/internal/{runtime/detectBrowser → browser_detection}/detectElectron.js +0 -0
  41. package/src/internal/{runtime/detectBrowser → browser_detection}/detectFirefox.js +0 -0
  42. package/src/internal/{runtime/detectBrowser → browser_detection}/detectIOS.js +0 -0
  43. package/src/internal/{runtime/detectBrowser → browser_detection}/detectInternetExplorer.js +0 -0
  44. package/src/internal/{runtime/detectBrowser → browser_detection}/detectOpera.js +0 -0
  45. package/src/internal/{runtime/detectBrowser → browser_detection}/detectSafari.js +0 -0
  46. package/src/internal/{runtime/detectBrowser → browser_detection}/util.js +0 -0
  47. package/src/internal/{runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js → browser_feature_detection/browser_feature_detection.js} +116 -81
  48. package/src/internal/browser_feature_detection/compile_proxy.html +27 -0
  49. package/src/internal/browser_launcher/browser_runtime_report.js +75 -0
  50. package/src/internal/{browser-launcher → browser_launcher}/createSharing.js +0 -0
  51. package/src/internal/{browser-launcher → browser_launcher}/executeHtmlFile.js +13 -16
  52. package/src/internal/{browser-launcher → browser_launcher}/trackPageToNotify.js +0 -0
  53. package/src/internal/{browser-launcher/jsenv-browser-system.js → browser_runtime/browser_runtime.js} +4 -4
  54. package/src/internal/{runtime/createBrowserRuntime/createBrowserSystem.js → browser_runtime/browser_system.js} +3 -2
  55. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/createBrowserRuntime.js +7 -5
  56. package/src/internal/{browser-launcher → browser_runtime}/displayErrorInDocument.js +0 -0
  57. package/src/internal/{browser-launcher → browser_runtime}/displayErrorNotification.js +2 -4
  58. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/evalSource.js +2 -0
  59. package/src/internal/{runtime/createBrowserRuntime → browser_runtime}/makeNamespaceTransferable.js +0 -0
  60. package/src/internal/{browser-utils → browser_utils}/fetch-browser.js +2 -0
  61. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingFetch.js +3 -0
  62. package/src/internal/{browser-utils → browser_utils}/fetchAndEvalUsingScript.js +2 -0
  63. package/src/internal/{browser-utils → browser_utils}/fetchJson.js +0 -0
  64. package/src/internal/{browser-utils → browser_utils}/fetchUsingXHR.js +4 -4
  65. package/src/internal/building/buildUsingRollup.js +4 -0
  66. package/src/internal/building/createJsenvRollupPlugin.js +19 -9
  67. package/src/internal/building/css/applyPostCss.js +19 -8
  68. package/src/internal/building/css/moveCssUrls.js +44 -0
  69. package/src/internal/building/css/parseCssRessource.js +67 -17
  70. package/src/internal/building/css/parseCssUrls.js +29 -23
  71. package/src/internal/building/css/postcss_plugin_url_visitor.js +11 -20
  72. package/src/internal/building/css/replaceCssUrls.js +38 -19
  73. package/src/internal/building/css_module.js +6 -10
  74. package/src/internal/building/html/parseHtmlRessource.js +37 -11
  75. package/src/internal/building/parseRessource.js +3 -0
  76. package/src/internal/building/ressource_builder.js +12 -3
  77. package/src/internal/compiling/babel_plugin_import_assertions.js +1 -2
  78. package/src/internal/compiling/html_source_file_service.js +23 -21
  79. package/src/internal/compiling/jsenvCompilerForHtml.js +15 -22
  80. package/src/internal/compiling/startCompileServer.js +37 -32
  81. package/src/internal/dev_server/event_source_client/event_source_connection.js +28 -19
  82. package/src/internal/dev_server/exploring/exploring.html +7 -2
  83. package/src/internal/dev_server/exploring/fetchExploringJson.js +4 -9
  84. package/src/internal/dev_server/redirector/redirector.html +37 -2
  85. package/src/internal/dev_server/toolbar/compilation/toolbar.compilation.js +4 -7
  86. package/src/internal/dev_server/toolbar/eventsource/toolbar.eventsource.js +2 -2
  87. package/src/internal/dev_server/toolbar/notification/toolbar.notification.js +75 -44
  88. package/src/internal/dev_server/toolbar/toolbar.html +31 -5
  89. package/src/internal/dev_server/toolbar/toolbar.injector.js +55 -36
  90. package/src/internal/dev_server/toolbar/toolbar.main.js +45 -31
  91. package/src/internal/dev_server/toolbar/util/fetching.js +1 -1
  92. package/src/internal/executing/executeConcurrently.js +5 -4
  93. package/src/internal/executing/executePlan.js +1 -2
  94. package/src/internal/generateGroupMap/one_runtime_compat.js +1 -1
  95. package/src/internal/generateGroupMap/runtime_compat_composition.js +1 -1
  96. package/src/internal/generateGroupMap/runtime_support.js +1 -1
  97. package/src/internal/jsenvInternalFiles.js +0 -26
  98. package/src/internal/jsenv_builds.js +19 -0
  99. package/src/internal/{runtime/node-feature-detect/feature-detect-dynamic-import.mjs → node_feature_detection/feature_detect_dynamic_import.mjs} +0 -0
  100. package/src/internal/{runtime/node-feature-detect/feature-detect-top-level-await.mjs → node_feature_detection/feature_detect_top_level_await.mjs} +0 -0
  101. package/src/internal/{runtime/node-feature-detect → node_feature_detection}/nodeSupportsDynamicImport.js +0 -0
  102. package/src/internal/node_feature_detection/nodeSupportsTopLevelAwait.js +16 -0
  103. package/src/internal/{runtime/createNodeRuntime/scanNodeRuntimeFeatures.js → node_feature_detection/node_feature_detection.js} +12 -13
  104. package/src/internal/{node-launcher → node_launcher}/createChildProcessOptions.js +0 -0
  105. package/src/internal/{node-launcher → node_launcher}/createControllableNodeProcess.js +9 -14
  106. package/src/internal/{node-launcher → node_launcher}/kill_process_tree.js +0 -0
  107. package/src/internal/node_launcher/node_runtime_report.js +71 -0
  108. package/src/internal/{node-launcher → node_launcher}/processOptions.js +0 -0
  109. package/src/internal/{runtime/detectNode → node_runtime}/detectNode.js +0 -0
  110. package/src/internal/{runtime/createNodeRuntime → node_runtime}/evalSource.js +1 -1
  111. package/src/internal/{runtime/createNodeRuntime → node_runtime}/fetchSource.js +1 -1
  112. package/src/internal/{node-launcher → node_runtime}/nodeControllableFile.mjs +14 -11
  113. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithDynamicImport.js → node_runtime/node_execution_dynamic_import.js} +34 -6
  114. package/src/internal/node_runtime/node_execution_performance.js +67 -0
  115. package/src/internal/{runtime/createNodeRuntime/createNodeExecutionWithSystemJs.js → node_runtime/node_execution_systemjs.js} +38 -24
  116. package/src/internal/{runtime/createNodeRuntime/createNodeSystem.js → node_runtime/node_system.js} +4 -4
  117. package/src/internal/runtime/computeCompileIdFromGroupId.js +1 -0
  118. package/src/internal/runtime/resolveGroup.js +1 -1
  119. package/src/internal/runtime/resolveRuntimeGroup.js +2 -2
  120. package/src/internal/{semantic-versioning → semantic_versioning}/findHighestVersion.js +0 -0
  121. package/src/internal/{semantic-versioning → semantic_versioning}/findLowestVersion.js +0 -0
  122. package/src/internal/{semantic-versioning → semantic_versioning}/index.js +0 -0
  123. package/src/internal/{semantic-versioning → semantic_versioning}/valueToVersion.js +0 -0
  124. package/src/internal/{semantic-versioning → semantic_versioning}/versionCompare.js +0 -0
  125. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsAbove.js +0 -0
  126. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsBelow.js +0 -0
  127. package/src/internal/{semantic-versioning → semantic_versioning}/versionIsEqual.js +0 -0
  128. package/src/launchBrowser.js +12 -3
  129. package/src/launchNode.js +36 -7
  130. package/src/requireUsingChildProcess.js +1 -1
  131. package/dist/jsenv_compile_proxy.js +0 -1339
  132. package/dist/jsenv_compile_proxy.js.map +0 -378
  133. package/dist/jsenv_event_source_client.js.map +0 -126
  134. package/dist/jsenv_exploring_index.js +0 -1092
  135. package/dist/jsenv_exploring_index.js.map +0 -353
  136. package/dist/jsenv_exploring_redirector.js +0 -1386
  137. package/dist/jsenv_exploring_redirector.js.map +0 -384
  138. package/dist/jsenv_redirector.js +0 -1388
  139. package/dist/jsenv_redirector.js.map +0 -384
  140. package/dist/jsenv_toolbar.js +0 -2880
  141. package/dist/jsenv_toolbar.js.map +0 -771
  142. package/dist/jsenv_toolbar_injector.js.map +0 -301
  143. package/src/internal/browser-launcher/jsenv_compile_proxy.html +0 -13
  144. package/src/internal/browser-launcher/jsenv_compile_proxy.js +0 -5
  145. package/src/internal/dev_server/event_source_client/event_source_client_file_info.js +0 -17
  146. package/src/internal/dev_server/exploring/exploring_file_info.js +0 -21
  147. package/src/internal/dev_server/redirector/redirector.js +0 -30
  148. package/src/internal/dev_server/redirector/redirector_file_info.js +0 -24
  149. package/src/internal/dev_server/toolbar/backtolist/toolbar.backtolist.js +0 -33
  150. package/src/internal/dev_server/toolbar/toolbar_file_info.js +0 -37
  151. package/src/internal/node-launcher/node-js-file.js +0 -110
  152. package/src/internal/runtime/createNodeRuntime/createNodeRuntime.js +0 -32
  153. package/src/internal/runtime/node-feature-detect/nodeSupportsTopLevelAwait.js +0 -18
  154. package/src/nodeRuntime.js +0 -5
@@ -29,12 +29,16 @@ import {
29
29
  createCallbackListNotifiedOnce,
30
30
  } from "@jsenv/abort"
31
31
 
32
+ import {
33
+ TOOLBAR_INJECTOR_BUILD_URL,
34
+ EVENT_SOURCE_CLIENT_BUILD_URL,
35
+ BROWSER_RUNTIME_BUILD_URL,
36
+ } from "@jsenv/core/dist/build_manifest.js"
32
37
  import { generateGroupMap } from "@jsenv/core/src/internal/generateGroupMap/generateGroupMap.js"
33
38
  import { isBrowserPartOfSupportedRuntimes } from "@jsenv/core/src/internal/generateGroupMap/runtime_support.js"
34
39
  import { loadBabelPluginMapFromFile } from "./load_babel_plugin_map_from_file.js"
35
40
  import { extractSyntaxBabelPluginMap } from "./babel_plugins.js"
36
41
  import {
37
- jsenvCompileProxyFileInfo,
38
42
  sourcemapMainFileInfo,
39
43
  sourcemapMappingFileInfo,
40
44
  } from "../jsenvInternalFiles.js"
@@ -47,6 +51,8 @@ import { createCompiledFileService } from "./createCompiledFileService.js"
47
51
  import { urlIsCompilationAsset } from "./compile-directory/compile-asset.js"
48
52
  import { createTransformHtmlSourceFileService } from "./html_source_file_service.js"
49
53
 
54
+ let compileServerId = 0
55
+
50
56
  export const startCompileServer = async ({
51
57
  signal = new AbortController().signal,
52
58
  handleSIGINT,
@@ -295,9 +301,6 @@ export const startCompileServer = async ({
295
301
  outDirectoryUrl,
296
302
  compileServerMetaFileInfo,
297
303
  }),
298
- "service: compile proxy": createCompileProxyService({
299
- projectDirectoryUrl,
300
- }),
301
304
  "service:compiled file": createCompiledFileService({
302
305
  logger,
303
306
 
@@ -388,6 +391,7 @@ export const startCompileServer = async ({
388
391
  })
389
392
 
390
393
  return {
394
+ id: compileServerId++,
391
395
  jsenvDirectoryRelativeUrl,
392
396
  outDirectoryRelativeUrl,
393
397
  ...compileServer,
@@ -913,15 +917,24 @@ const createSourceFileService = ({
913
917
  const relativeUrl = request.pathname.slice(1)
914
918
  projectFileRequestedCallback(relativeUrl, request)
915
919
 
916
- const responsePromise = fetchFileSystem(
917
- new URL(request.ressource.slice(1), projectDirectoryUrl),
918
- {
919
- headers: request.headers,
920
- etagEnabled: projectFileCacheStrategy === "etag",
921
- mtimeEnabled: projectFileCacheStrategy === "mtime",
922
- },
920
+ const fileUrl = new URL(request.ressource.slice(1), projectDirectoryUrl)
921
+ .href
922
+ const fileIsInsideJsenvDistDirectory = urlIsInsideOf(
923
+ fileUrl,
924
+ new URL("./dist/", jsenvCoreDirectoryUrl),
923
925
  )
924
926
 
927
+ const responsePromise = fetchFileSystem(fileUrl, {
928
+ headers: request.headers,
929
+ etagEnabled: projectFileCacheStrategy === "etag",
930
+ mtimeEnabled: projectFileCacheStrategy === "mtime",
931
+ ...(fileIsInsideJsenvDistDirectory
932
+ ? {
933
+ cacheControl: `private,max-age=${60 * 60 * 24 * 30},immutable`,
934
+ }
935
+ : {}),
936
+ })
937
+
925
938
  return responsePromise
926
939
  }
927
940
  }
@@ -965,6 +978,12 @@ const createCompileServerMetaFileInfo = ({
965
978
  sourcemapMappingFileInfo.url,
966
979
  projectDirectoryUrl,
967
980
  )
981
+ // The object below must list everything that can influence how the
982
+ // compiled files are generated. So that the cahce for those generated files is
983
+ // not reused when it should not
984
+ // In some cases the parameters influences only a subset of files and ideally
985
+ // this parameter should somehow invalidate a subset of the cache
986
+ // To keep things simple these parameters currently invalidates the whole cache
968
987
  const compileServerMeta = {
969
988
  jsenvDirectoryRelativeUrl,
970
989
  outDirectoryRelativeUrl,
@@ -983,8 +1002,15 @@ const createCompileServerMetaFileInfo = ({
983
1002
  sourcemapMappingFileRelativeUrl,
984
1003
  errorStackRemapping: true,
985
1004
 
1005
+ // used to consider the logic generating files may have changed
986
1006
  jsenvCorePackageVersion,
1007
+
1008
+ // impact only HTML files
987
1009
  jsenvToolbarInjection,
1010
+ TOOLBAR_INJECTOR_BUILD_URL,
1011
+ EVENT_SOURCE_CLIENT_BUILD_URL,
1012
+ BROWSER_RUNTIME_BUILD_URL,
1013
+
988
1014
  env,
989
1015
  }
990
1016
  return {
@@ -1054,27 +1080,6 @@ const createCompileServerMetaService = ({
1054
1080
  }
1055
1081
  }
1056
1082
 
1057
- const createCompileProxyService = ({ projectDirectoryUrl }) => {
1058
- const jsenvCompileProxyRelativeUrlForProject = urlToRelativeUrl(
1059
- jsenvCompileProxyFileInfo.jsenvBuildUrl,
1060
- projectDirectoryUrl,
1061
- )
1062
-
1063
- return (request) => {
1064
- if (request.ressource === "/.jsenv/jsenv_compile_proxy.js") {
1065
- const jsenvCompileProxyBuildServerUrl = `${request.origin}/${jsenvCompileProxyRelativeUrlForProject}`
1066
- return {
1067
- status: 307,
1068
- headers: {
1069
- location: jsenvCompileProxyBuildServerUrl,
1070
- },
1071
- }
1072
- }
1073
-
1074
- return null
1075
- }
1076
- }
1077
-
1078
1083
  const readPackage = (packagePath) => {
1079
1084
  const buffer = readFileSync(packagePath)
1080
1085
  const string = String(buffer)
@@ -11,21 +11,34 @@ export const createEventSourceConnection = (
11
11
  }
12
12
 
13
13
  const eventSourceOrigin = new URL(eventSourceUrl).origin
14
+ Object.keys(events).forEach((eventName) => {
15
+ const eventCallback = events[eventName]
16
+ events[eventName] = (e) => {
17
+ if (e.origin === eventSourceOrigin) {
18
+ if (e.lastEventId) {
19
+ lastEventId = e.lastEventId
20
+ }
21
+ eventCallback(e)
22
+ }
23
+ }
24
+ })
14
25
 
15
26
  let connectionStatus = "default"
16
27
  let connectionStatusChangeCallback = () => {}
17
- let disconnect = () => {}
28
+ let _disconnect = () => {}
18
29
 
19
30
  const goToStatus = (newStatus) => {
20
- connectionStatus = newStatus
21
- connectionStatusChangeCallback()
31
+ if (newStatus !== connectionStatus) {
32
+ connectionStatus = newStatus
33
+ connectionStatusChangeCallback()
34
+ }
22
35
  }
23
36
 
24
37
  const attemptConnection = (url) => {
25
38
  const eventSource = new EventSource(url, {
26
39
  withCredentials: true,
27
40
  })
28
- disconnect = () => {
41
+ _disconnect = () => {
29
42
  if (
30
43
  connectionStatus !== "connecting" &&
31
44
  connectionStatus !== "connected"
@@ -37,6 +50,9 @@ export const createEventSourceConnection = (
37
50
  }
38
51
  eventSource.onerror = undefined
39
52
  eventSource.close()
53
+ Object.keys(events).forEach((eventName) => {
54
+ eventSource.removeEventListener(eventName, events[eventName])
55
+ })
40
56
  goToStatus("disconnected")
41
57
  }
42
58
  let retryCount = 0
@@ -45,7 +61,7 @@ export const createEventSourceConnection = (
45
61
  if (errorEvent.target.readyState === EventSource.CONNECTING) {
46
62
  if (retryCount > retryMaxAttempt) {
47
63
  console.info(`could not connect after ${retryMaxAttempt} attempt`)
48
- disconnect()
64
+ _disconnect()
49
65
  return
50
66
  }
51
67
 
@@ -57,7 +73,7 @@ export const createEventSourceConnection = (
57
73
  console.info(
58
74
  `could not connect in less than ${retryAllocatedMs} ms`,
59
75
  )
60
- disconnect()
76
+ _disconnect()
61
77
  return
62
78
  }
63
79
  }
@@ -68,7 +84,7 @@ export const createEventSourceConnection = (
68
84
  }
69
85
 
70
86
  if (errorEvent.target.readyState === EventSource.CLOSED) {
71
- disconnect()
87
+ _disconnect()
72
88
  return
73
89
  }
74
90
  }
@@ -76,14 +92,7 @@ export const createEventSourceConnection = (
76
92
  goToStatus("connected")
77
93
  }
78
94
  Object.keys(events).forEach((eventName) => {
79
- eventSource.addEventListener(eventName, (e) => {
80
- if (e.origin === eventSourceOrigin) {
81
- if (e.lastEventId) {
82
- lastEventId = e.lastEventId
83
- }
84
- events[eventName](e)
85
- }
86
- })
95
+ eventSource.addEventListener(eventName, events[eventName])
87
96
  })
88
97
  if (!events.hasOwnProperty("welcome")) {
89
98
  eventSource.addEventListener("welcome", (e) => {
@@ -107,21 +116,21 @@ export const createEventSourceConnection = (
107
116
  }
108
117
 
109
118
  const removePageUnloadListener = listenPageUnload(() => {
110
- disconnect()
119
+ _disconnect()
111
120
  })
112
121
 
113
122
  const destroy = () => {
114
123
  removePageUnloadListener()
115
- disconnect()
124
+ _disconnect()
116
125
  }
117
126
 
118
127
  return {
119
128
  getConnectionStatus: () => connectionStatus,
120
- setConnectionStatusCallback: (callback) => {
129
+ setConnectionStatusChangeCallback: (callback) => {
121
130
  connectionStatusChangeCallback = callback
122
131
  },
123
132
  connect,
124
- disconnect,
133
+ disconnect: () => _disconnect(),
125
134
  destroy,
126
135
  }
127
136
  }
@@ -35,7 +35,12 @@
35
35
  <div id="explorables-header">
36
36
  <div id="explorables_header_and_menu">
37
37
  <h2 style="white-space: nowrap">
38
- <svg id="fileIconSvgConfig" viewBox="0 0 24 24">
38
+ <svg
39
+ id="fileIconSvgConfig"
40
+ viewBox="0 0 24 24"
41
+ width="32"
42
+ height="32"
43
+ >
39
44
  <path d="M0 0h24v24H0V0z" fill="none" />
40
45
  <path
41
46
  d="M8 16h8v2H8zm0-4h8v2H8zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"
@@ -69,6 +74,6 @@
69
74
  </section>
70
75
  </article>
71
76
  </div>
72
- <script src="/.jsenv/exploring.index.js"></script>
77
+ <script type="module" src="./exploring.js"></script>
73
78
  </body>
74
79
  </html>
@@ -1,6 +1,4 @@
1
- import { createDetailedMessage } from "@jsenv/logger"
2
-
3
- import { fetchJson } from "../../browser-utils/fetchJson.js"
1
+ import { fetchJson } from "../../browser_utils/fetchJson.js"
4
2
 
5
3
  export const fetchExploringJson = async ({ signal } = {}) => {
6
4
  try {
@@ -13,12 +11,9 @@ export const fetchExploringJson = async ({ signal } = {}) => {
13
11
  throw e
14
12
  }
15
13
  throw new Error(
16
- createDetailedMessage(
17
- `Cannot communicate with exploring server due to a network error`,
18
- {
19
- ["error stack"]: e.stack,
20
- },
21
- ),
14
+ `Cannot communicate with exploring server due to a network error
15
+ --- error stack ---
16
+ ${e.stack}`,
22
17
  )
23
18
  }
24
19
  }
@@ -1,13 +1,48 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Exploring redirector</title>
4
+ <title>Jsenv redirector</title>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <meta charset="utf-8" />
7
7
  <link rel="icon" href="data:," />
8
8
  </head>
9
9
 
10
10
  <body>
11
- <script src="/.jsenv/redirector.js"></script>
11
+ <script
12
+ type="importmap"
13
+ src="../../../../node_resolution.importmap"
14
+ ></script>
15
+ <script type="module">
16
+ import { scanBrowserRuntimeFeatures } from "../../browser_feature_detection/browser_feature_detection.js"
17
+
18
+ const redirect = async () => {
19
+ const redirectTarget = new URLSearchParams(window.location.search).get(
20
+ "redirect",
21
+ )
22
+ const browserRuntimeFeaturesReport = await scanBrowserRuntimeFeatures({
23
+ failFastOnFeatureDetection: true,
24
+ })
25
+
26
+ const href = `${getDirectoryUrl(
27
+ browserRuntimeFeaturesReport,
28
+ )}${redirectTarget}`
29
+ // It's IMPORTANT to use location.replace and NOT location.href = url
30
+ // otherwise it would break the back button
31
+ window.location.replace(href)
32
+ }
33
+
34
+ const getDirectoryUrl = ({
35
+ canAvoidCompilation,
36
+ outDirectoryRelativeUrl,
37
+ compileId,
38
+ }) => {
39
+ if (canAvoidCompilation) {
40
+ return `/`
41
+ }
42
+ return `/${outDirectoryRelativeUrl}${compileId}/`
43
+ }
44
+
45
+ redirect()
46
+ </script>
12
47
  </body>
13
48
  </html>
@@ -1,4 +1,4 @@
1
- import { scanBrowserRuntimeFeatures } from "../../../runtime/createBrowserRuntime/scanBrowserRuntimeFeatures.js"
1
+ import { scanBrowserRuntimeFeatures } from "../../../browser_feature_detection/browser_feature_detection.js"
2
2
  import { removeForceHideElement } from "../util/dom.js"
3
3
  import { enableVariant } from "../variant/variant.js"
4
4
 
@@ -133,8 +133,7 @@ const getBrowserSupportMessage = ({
133
133
  }) => {
134
134
  const parts = []
135
135
 
136
- const { importmapSupported } = featuresReport
137
- if (importmapSupported) {
136
+ if (featuresReport.importmap) {
138
137
  if (!missingOnly) {
139
138
  if (inlineImportMapIntoHTML) {
140
139
  parts.push(`importmaps are supported (only when inlined in html files)`)
@@ -146,8 +145,7 @@ const getBrowserSupportMessage = ({
146
145
  parts.push(`importmaps are not supported`)
147
146
  }
148
147
 
149
- const { dynamicImportSupported } = featuresReport
150
- if (dynamicImportSupported) {
148
+ if (featuresReport.dynamicImport) {
151
149
  if (!missingOnly) {
152
150
  parts.push(`dynamic imports are supported`)
153
151
  }
@@ -155,8 +153,7 @@ const getBrowserSupportMessage = ({
155
153
  parts.push(`dynamic imports are not supported`)
156
154
  }
157
155
 
158
- const { topLevelAwaitSupported } = featuresReport
159
- if (topLevelAwaitSupported) {
156
+ if (featuresReport.topLevelAwait) {
160
157
  if (!missingOnly) {
161
158
  parts.push(`top level await is supported`)
162
159
  }
@@ -15,9 +15,9 @@ export const initToolbarEventSource = ({ livereloading }) => {
15
15
  if (!livereloadingAvailableOnServer) {
16
16
  disableLivereloadSetting()
17
17
  }
18
- parentEventSourceClient.setConnectionStatusChangeCallback = () => {
18
+ parentEventSourceClient.setConnectionStatusChangeCallback(() => {
19
19
  updateEventSourceIndicator()
20
- }
20
+ })
21
21
  const livereloadCheckbox = document.querySelector("#toggle-livereload")
22
22
  livereloadCheckbox.checked = parentEventSourceClient.isLivereloadEnabled()
23
23
  livereloadCheckbox.onchange = () => {
@@ -1,25 +1,56 @@
1
1
  import { createPreference } from "../util/preferences.js"
2
+ import { enableVariant } from "../variant/variant.js"
2
3
 
4
+ const notificationAvailable = typeof window.Notification === "function"
3
5
  const notificationPreference = createPreference("notification")
4
6
 
5
7
  const arrayOfOpenedNotifications = []
6
8
  export const renderToolbarNotification = () => {
7
9
  const notifCheckbox = document.querySelector("#toggle-notifs")
8
- notifCheckbox.checked = getNotificationPreference()
9
- notifCheckbox.onchange = () => {
10
- setNotificationPreference(notifCheckbox.checked)
11
- if (notifCheckbox.checked) {
12
- // request permission early
13
- // especially useful on firefox where you can request permission
14
- // only inside a user generated event such as this onchange handler
15
- requestPermission()
16
- } else {
17
- // slice because arrayOfOpenedNotifications can be mutated while looping
18
- arrayOfOpenedNotifications.slice().forEach((notification) => {
19
- notification.close()
20
- })
10
+ if (!notificationAvailable) {
11
+ const notifSetting = document.querySelector(".settings-notification")
12
+ notifSetting.setAttribute("data-disabled", "true")
13
+ notifSetting.setAttribute(
14
+ "title",
15
+ `Notification not available in the browser`,
16
+ )
17
+ notifCheckbox.disabled = true
18
+ return
19
+ }
20
+
21
+ const updatePermission = () => {
22
+ if (Notification.permission === "denied") {
23
+ const notifSetting = document.querySelector(".settings-notification")
24
+ notifSetting.setAttribute("data-disabled", "true")
25
+ notifSetting.setAttribute("title", `Notification denied`)
26
+ notifCheckbox.disabled = true
27
+ return
28
+ }
29
+
30
+ notifCheckbox.checked = getNotificationPreference()
31
+ notifCheckbox.onchange = () => {
32
+ setNotificationPreference(notifCheckbox.checked)
33
+ if (!notifCheckbox.checked) {
34
+ // slice because arrayOfOpenedNotifications can be mutated while looping
35
+ arrayOfOpenedNotifications.slice().forEach((notification) => {
36
+ notification.close()
37
+ })
38
+ }
39
+ }
40
+ const notifPermission = Notification.permission
41
+ enableVariant(document.querySelector(".notification-text"), {
42
+ notif_permission: notifPermission === "granted" ? "yes" : "no",
43
+ })
44
+ if (notifPermission === "default") {
45
+ document.querySelector("a.request_notification_permission").onclick =
46
+ () => {
47
+ requestPermission().then(() => {
48
+ updatePermission()
49
+ })
50
+ }
21
51
  }
22
52
  }
53
+ updatePermission()
23
54
  }
24
55
 
25
56
  export const notifyExecutionResult = (
@@ -64,8 +95,6 @@ export const notifyExecutionResult = (
64
95
  }
65
96
  }
66
97
 
67
- const notificationAvailable = typeof window.Notification === "function"
68
-
69
98
  const getNotificationPreference = () =>
70
99
  notificationPreference.has() ? notificationPreference.get() : true
71
100
 
@@ -76,46 +105,48 @@ const getFaviconHref = () => {
76
105
  return link ? link.href : undefined
77
106
  }
78
107
 
108
+ let permission = "default"
109
+
79
110
  const notify = notificationAvailable
80
111
  ? async (
81
112
  title,
82
113
  { clickToFocus = false, clickToClose = false, ...options } = {},
83
114
  ) => {
84
- const permission = await requestPermission()
85
- if (permission === "granted") {
86
- const notification = new Notification(title, options)
87
- arrayOfOpenedNotifications.push(notification)
88
- notification.onclick = () => {
89
- // but if the user navigated inbetween
90
- // focusing window will show something else
91
- // in that case it could be great to do something
92
- // maybe like showing a message saying this execution
93
- // is no longer visible
94
- // we could also navigauate to this file execution but
95
- // there is no guarantee re-executing the file would give same output
96
- // and it would also trigger an other notification
97
- if (clickToFocus) window.focus()
98
- if (clickToClose) notification.close()
99
- }
100
- notification.onclose = () => {
101
- const index = arrayOfOpenedNotifications.indexOf(notification)
102
- if (index > -1) {
103
- arrayOfOpenedNotifications.splice(index, 1)
104
- }
115
+ if (permission !== "granted") {
116
+ return null
117
+ }
118
+
119
+ const notification = new Notification(title, options)
120
+ arrayOfOpenedNotifications.push(notification)
121
+ notification.onclick = () => {
122
+ // but if the user navigated inbetween
123
+ // focusing window will show something else
124
+ // in that case it could be great to do something
125
+ // maybe like showing a message saying this execution
126
+ // is no longer visible
127
+ // we could also navigauate to this file execution but
128
+ // there is no guarantee re-executing the file would give same output
129
+ // and it would also trigger an other notification
130
+ if (clickToFocus) window.focus()
131
+ if (clickToClose) notification.close()
132
+ }
133
+ notification.onclose = () => {
134
+ const index = arrayOfOpenedNotifications.indexOf(notification)
135
+ if (index > -1) {
136
+ arrayOfOpenedNotifications.splice(index, 1)
105
137
  }
106
- return notification
107
138
  }
108
- return null
139
+ return notification
109
140
  }
110
141
  : () => {}
111
142
 
112
- let permissionPromise
143
+ let requestPromise
113
144
  const requestPermission = notificationAvailable
114
145
  ? async () => {
115
- if (permissionPromise) return permissionPromise
116
- permissionPromise = Notification.requestPermission()
117
- const permission = await permissionPromise
118
- permissionPromise = undefined
146
+ if (requestPromise) return requestPromise
147
+ requestPromise = Notification.requestPermission()
148
+ permission = await requestPromise
149
+ requestPromise = undefined
119
150
  return permission
120
151
  }
121
- : () => Promise.resolve("denied")
152
+ : () => Promise.resolve("default")
@@ -5,7 +5,12 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <meta charset="utf-8" />
7
7
  <link rel="icon" href="data:," />
8
- <link rel="stylesheet" type="text/css" href="./toolbar.main.css" />
8
+ <link
9
+ rel="stylesheet"
10
+ type="text/css"
11
+ href="./toolbar.main.css"
12
+ data-jsenv-force-inline
13
+ />
9
14
  </head>
10
15
  <body>
11
16
  <div id="toolbar-overlay"></div>
@@ -13,7 +18,7 @@
13
18
  <div id="toolbar">
14
19
  <div id="toolbar-wrapper">
15
20
  <section id="file-list-link" data-responsive-toolbar-element>
16
- <a class="toolbar-icon-wrapper" href="">
21
+ <a class="toolbar-icon-wrapper" href="/">
17
22
  <svg
18
23
  id="fileIconSvg"
19
24
  class="iconToolbar"
@@ -251,7 +256,7 @@
251
256
  </div>
252
257
  <div id="settings-box-body">
253
258
  <div class="settings-box-items-wrapper">
254
- <div class="settings-box-item">
259
+ <div class="settings-box-item settings-notification">
255
260
  <div class="category-title">
256
261
  <svg
257
262
  xmlns="http://www.w3.org/2000/svg"
@@ -274,6 +279,14 @@
274
279
  </label>
275
280
  <div class="category-subtitle">
276
281
  Send system notification when execution fails or is fixed.
282
+ <div class="notification-text">
283
+ <a
284
+ data-when="notif_permission:no"
285
+ class="request_notification_permission"
286
+ href="javascript:void(0);"
287
+ >Enable notification</a
288
+ >
289
+ </div>
277
290
  </div>
278
291
  </div>
279
292
  <div class="settings-box-item settings-livereload">
@@ -526,7 +539,7 @@
526
539
  <!--
527
540
  Reusable svg(s)
528
541
  -->
529
- <div style="display: none">
542
+ <div style="display: none; position: absolute">
530
543
  <svg
531
544
  id="loading_svg"
532
545
  xmlns="http://www.w3.org/2000/svg"
@@ -551,6 +564,19 @@
551
564
  module approach wil be faster because
552
565
  no compilation will be necessary
553
566
  -->
554
- <script src="/.jsenv/toolbar.main.js"></script>
567
+ <script
568
+ type="importmap"
569
+ src="../../../../node_resolution.importmap"
570
+ ></script>
571
+ <script>
572
+ // here we should create something like window.toolbar = {}
573
+ // and a promise the toolbar injector can listen to act on the toolbar
574
+ // or we could just consider all communication should pass by postmessage
575
+ </script>
576
+ <script
577
+ type="module"
578
+ src="./toolbar.main.js"
579
+ data-jsenv-force-inline
580
+ ></script>
555
581
  </body>
556
582
  </html>