@jsenv/core 40.12.2 → 40.12.4

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.
@@ -39,9 +39,8 @@ import { existsSync, lstatSync, readdirSync } from "node:fs";
39
39
  import { getDirectoryWatchPatterns } from "../../helpers/watch_source_files.js";
40
40
  import { FILE_AND_SERVER_URLS_CONVERTER } from "../../kitchen/file_and_server_urls_converter.js";
41
41
 
42
- const htmlFileUrlForDirectory = import.meta.resolve(
43
- "./client/directory_listing.html",
44
- );
42
+ const htmlFileUrlForDirectory = import.meta
43
+ .resolve("./client/directory_listing.html");
45
44
 
46
45
  export const jsenvPluginDirectoryListing = ({
47
46
  spa,
@@ -103,7 +102,7 @@ export const jsenvPluginDirectoryListing = ({
103
102
  if (!acceptsHtml) {
104
103
  return null;
105
104
  }
106
- reference.fsStat = null; // reset fsStat, now it's not a directory anyor
105
+ reference.fsStat = null; // reset fsStat as it's not a directory anymore
107
106
  return `${htmlFileUrlForDirectory}?url=${encodeURIComponent(url)}`;
108
107
  },
109
108
  transformUrlContent: {
@@ -3,12 +3,7 @@ import {
3
3
  applyFileSystemMagicResolution,
4
4
  getExtensionsToTry,
5
5
  } from "@jsenv/node-esm-resolution";
6
- import {
7
- urlIsOrIsInsideOf,
8
- urlToExtension,
9
- urlToFilename,
10
- urlToPathname,
11
- } from "@jsenv/urls";
6
+ import { urlIsOrIsInsideOf, urlToExtension, urlToFilename } from "@jsenv/urls";
12
7
  import { existsSync, realpathSync } from "node:fs";
13
8
  import { pathToFileURL } from "node:url";
14
9
 
@@ -94,19 +89,13 @@ export const jsenvPluginFsRedirection = ({
94
89
  applyFsStatEffectsOnUrlObject(urlObject, fsStat);
95
90
  }
96
91
  }
97
- if (!fsStat) {
98
- // for SPA we want to serve the root HTML file only when:
99
- // 1. There is no corresponding file on the filesystem
100
- // 2. The url pathname does not have an extension
101
- // This point assume client is requesting a file when there is an extension
102
- // and it assumes all routes will not use extension
103
- // 3. The url pathname does not ends with "/"
104
- // In that case we assume client explicitely asks to load a directory
105
- if (
106
- spa &&
107
- !urlToExtension(urlObject) &&
108
- !urlToPathname(urlObject).endsWith("/")
109
- ) {
92
+ if (spa) {
93
+ // for SPA we want to serve the root HTML file most of the time
94
+ if (!fsStat) {
95
+ if (urlToExtension(urlObject)) {
96
+ // url has an extension, we assume it's a file request -> let 404 happen
97
+ return null;
98
+ }
110
99
  const { requestedUrl, rootDirectoryUrl, mainFilePath } =
111
100
  reference.ownerUrlInfo.context;
112
101
  const closestHtmlRootFile = getClosestHtmlRootFile(
@@ -118,6 +107,16 @@ export const jsenvPluginFsRedirection = ({
118
107
  }
119
108
  return new URL(mainFilePath, rootDirectoryUrl);
120
109
  }
110
+ if (fsStat.isDirectory()) {
111
+ // When requesting a directory, check if we have an HTML entry file for that directory
112
+ const directoryEntryFileUrl = getDirectoryEntryFileUrl(urlObject);
113
+ if (directoryEntryFileUrl) {
114
+ reference.fsStat = readEntryStatSync(directoryEntryFileUrl);
115
+ return directoryEntryFileUrl;
116
+ }
117
+ }
118
+ }
119
+ if (!fsStat) {
121
120
  return null;
122
121
  }
123
122
  const urlBeforeSymlinkResolution = urlObject.href;
@@ -165,17 +164,24 @@ const resolveSymlink = (fileUrl) => {
165
164
  return realUrlObject.href;
166
165
  };
167
166
 
167
+ const getDirectoryEntryFileUrl = (directoryUrl) => {
168
+ const indexHtmlFileUrl = new URL(`index.html`, directoryUrl);
169
+ if (existsSync(indexHtmlFileUrl)) {
170
+ return indexHtmlFileUrl.href;
171
+ }
172
+ const filename = urlToFilename(directoryUrl);
173
+ const htmlFileUrlCandidate = new URL(`${filename}.html`, directoryUrl);
174
+ if (existsSync(htmlFileUrlCandidate)) {
175
+ return htmlFileUrlCandidate.href;
176
+ }
177
+ return null;
178
+ };
168
179
  const getClosestHtmlRootFile = (requestedUrl, serverRootDirectoryUrl) => {
169
180
  let directoryUrl = new URL("./", requestedUrl);
170
181
  while (true) {
171
- const indexHtmlFileUrl = new URL(`index.html`, directoryUrl);
172
- if (existsSync(indexHtmlFileUrl)) {
173
- return indexHtmlFileUrl.href;
174
- }
175
- const filename = urlToFilename(directoryUrl);
176
- const htmlFileUrlCandidate = new URL(`${filename}.html`, directoryUrl);
177
- if (existsSync(htmlFileUrlCandidate)) {
178
- return htmlFileUrlCandidate.href;
182
+ const directoryEntryFileUrl = getDirectoryEntryFileUrl(directoryUrl);
183
+ if (directoryEntryFileUrl) {
184
+ return directoryEntryFileUrl;
179
185
  }
180
186
  if (!urlIsOrIsInsideOf(directoryUrl, serverRootDirectoryUrl)) {
181
187
  return null;
@@ -2,14 +2,14 @@ export const injectRibbon = ({ text }) => {
2
2
  const css = /* css */ `
3
3
  #jsenv_ribbon_container {
4
4
  position: fixed;
5
- z-index: 1001;
6
5
  top: 0;
7
6
  right: 0;
7
+ z-index: 1001;
8
8
  width: 100px;
9
9
  height: 100px;
10
- overflow: hidden;
11
10
  opacity: 0.5;
12
11
  pointer-events: none;
12
+ overflow: hidden;
13
13
  }
14
14
  #jsenv_ribbon {
15
15
  position: absolute;
@@ -20,20 +20,20 @@ export const injectRibbon = ({ text }) => {
20
20
  }
21
21
  #jsenv_ribbon_text {
22
22
  position: absolute;
23
- left: 0px;
24
23
  top: 20px;
25
- transform: rotate(45deg);
24
+ left: 0px;
26
25
  display: block;
27
26
  width: 125px;
28
- line-height: 36px;
29
- background-color: orange;
30
27
  color: rgb(55, 7, 7);
31
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
32
28
  font-weight: 700;
33
29
  font-size: 16px;
34
30
  font-family: "Lato", sans-serif;
35
- text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
36
31
  text-align: center;
32
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
33
+ line-height: 36px;
34
+ background-color: orange;
35
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.1);
36
+ transform: rotate(45deg);
37
37
  user-select: none;
38
38
  }
39
39
  `;