@jsenv/core 39.3.3 → 39.3.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.
- package/dist/html/directory.html +156 -8
- package/dist/html/html_404_and_parent_dir.html +193 -8
- package/dist/jsenv_core.js +119 -65
- package/package.json +2 -2
- package/src/build/build.js +28 -26
- package/src/build/build_specifier_manager.js +7 -2
- package/src/plugins/directory_reference_effect/jsenv_plugin_directory_reference_effect.js +5 -1
- package/src/plugins/protocol_file/client/assets/dir.png +0 -0
- package/src/plugins/protocol_file/client/assets/directory.css +133 -0
- package/src/plugins/protocol_file/client/assets/file.png +0 -0
- package/src/plugins/protocol_file/client/directory.html +17 -0
- package/src/plugins/protocol_file/client/html_404_and_parent_dir.html +54 -0
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +75 -31
- package/src/plugins/resolution_node_esm/jsenv_plugin_node_esm_resolution.js +5 -1
- package/dist/html/html_404_and_parent_dir_is_empty.html +0 -16
- package/src/plugins/protocol_file/directory.html +0 -20
- package/src/plugins/protocol_file/html_404_and_parent_dir.html +0 -21
- package/src/plugins/protocol_file/html_404_and_parent_dir_is_empty.html +0 -18
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>404 ENOENT</title>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<link rel="icon" href="data:," />
|
|
7
|
+
<link
|
|
8
|
+
rel="stylesheet"
|
|
9
|
+
href="node_esm:@jsenv/core/src/plugins/protocol_file/client/assets/directory.css?inline"
|
|
10
|
+
/>
|
|
11
|
+
<style>
|
|
12
|
+
.error_message {
|
|
13
|
+
background-color: #fce4e4;
|
|
14
|
+
border: 1px solid #fcc2c3;
|
|
15
|
+
padding: 1.5em 1.2em;
|
|
16
|
+
margin: 1em;
|
|
17
|
+
display: block;
|
|
18
|
+
}
|
|
19
|
+
.error_text {
|
|
20
|
+
color: #cc0033;
|
|
21
|
+
font-weight: bold;
|
|
22
|
+
line-height: 2em;
|
|
23
|
+
text-shadow: 1px 1px rgba(250, 250, 250, 0.3);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.hint_message {
|
|
27
|
+
background-color: lightblue;
|
|
28
|
+
border: 1px solid #fcc2c3;
|
|
29
|
+
padding: 1.5em 1.2em;
|
|
30
|
+
margin: 1em;
|
|
31
|
+
display: block;
|
|
32
|
+
}
|
|
33
|
+
.hint_text {
|
|
34
|
+
color: black;
|
|
35
|
+
font-weight: bold;
|
|
36
|
+
line-height: 2em;
|
|
37
|
+
text-shadow: 1px 1px rgba(250, 250, 250, 0.3);
|
|
38
|
+
}
|
|
39
|
+
</style>
|
|
40
|
+
</head>
|
|
41
|
+
|
|
42
|
+
<body data-theme="dark">
|
|
43
|
+
<p class="error_message">
|
|
44
|
+
<span class="error_text">
|
|
45
|
+
No entry on the filesystem for <code>/${fileRelativeUrl}</code> (at
|
|
46
|
+
${fileUrl})
|
|
47
|
+
<br />
|
|
48
|
+
Content of the parent directory is listed below:
|
|
49
|
+
</span>
|
|
50
|
+
</p>
|
|
51
|
+
<h1 class="directory_nav">${parentDirectoryNav}</h1>
|
|
52
|
+
${parentDirectoryContent}
|
|
53
|
+
</body>
|
|
54
|
+
</html>
|
|
@@ -6,21 +6,21 @@ import { pickContentType } from "@jsenv/server";
|
|
|
6
6
|
import {
|
|
7
7
|
ensurePathnameTrailingSlash,
|
|
8
8
|
urlIsInsideOf,
|
|
9
|
+
urlToFilename,
|
|
9
10
|
urlToRelativeUrl,
|
|
10
11
|
} from "@jsenv/urls";
|
|
11
12
|
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
12
13
|
import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
13
14
|
import { jsenvPluginFsRedirection } from "./jsenv_plugin_fs_redirection.js";
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
-
"./
|
|
16
|
+
const html404AndParentDirFileUrl = new URL(
|
|
17
|
+
"./client/html_404_and_parent_dir.html",
|
|
17
18
|
import.meta.url,
|
|
18
19
|
);
|
|
19
|
-
const
|
|
20
|
-
"./
|
|
20
|
+
const htmlFileUrlForDirectory = new URL(
|
|
21
|
+
"./client/directory.html",
|
|
21
22
|
import.meta.url,
|
|
22
23
|
);
|
|
23
|
-
const htmlFileUrlForDirectory = new URL("./directory.html", import.meta.url);
|
|
24
24
|
|
|
25
25
|
export const jsenvPluginProtocolFile = ({
|
|
26
26
|
magicExtensions,
|
|
@@ -97,12 +97,14 @@ export const jsenvPluginProtocolFile = ({
|
|
|
97
97
|
? pickContentType(urlInfo.context.request, ["text/html"])
|
|
98
98
|
: false;
|
|
99
99
|
if (acceptsHtml) {
|
|
100
|
+
firstReference.expectedType = "html";
|
|
100
101
|
const html = generateHtmlForDirectory(
|
|
101
102
|
urlObject.href,
|
|
102
103
|
directoryContentArray,
|
|
103
104
|
urlInfo.context.rootDirectoryUrl,
|
|
104
105
|
);
|
|
105
106
|
return {
|
|
107
|
+
type: "html",
|
|
106
108
|
contentType: "text/html",
|
|
107
109
|
content: html,
|
|
108
110
|
};
|
|
@@ -143,6 +145,9 @@ export const jsenvPluginProtocolFile = ({
|
|
|
143
145
|
return {
|
|
144
146
|
contentType: "text/html",
|
|
145
147
|
content: html,
|
|
148
|
+
headers: {
|
|
149
|
+
"cache-control": "no-cache",
|
|
150
|
+
},
|
|
146
151
|
};
|
|
147
152
|
}
|
|
148
153
|
}
|
|
@@ -166,10 +171,13 @@ const generateHtmlForDirectory = (
|
|
|
166
171
|
rootDirectoryUrl,
|
|
167
172
|
) => {
|
|
168
173
|
directoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
|
|
174
|
+
|
|
169
175
|
const htmlForDirectory = String(readFileSync(htmlFileUrlForDirectory));
|
|
176
|
+
const directoryRelativeUrl = urlToRelativeUrl(directoryUrl, rootDirectoryUrl);
|
|
170
177
|
const replacers = {
|
|
171
|
-
directoryRelativeUrl: urlToRelativeUrl(directoryUrl, rootDirectoryUrl),
|
|
172
178
|
directoryUrl,
|
|
179
|
+
directoryNav: () =>
|
|
180
|
+
generateDirectoryNav(directoryRelativeUrl, rootDirectoryUrl),
|
|
173
181
|
directoryContent: () =>
|
|
174
182
|
generateDirectoryContent(
|
|
175
183
|
directoryContentArray,
|
|
@@ -186,30 +194,21 @@ const generateHtmlForENOENTOnHtmlFile = (
|
|
|
186
194
|
parentDirectoryUrl,
|
|
187
195
|
rootDirectoryUrl,
|
|
188
196
|
) => {
|
|
189
|
-
if (parentDirectoryContentArray.length === 0) {
|
|
190
|
-
const htmlFor404AndParentDirIsEmpty = String(
|
|
191
|
-
readFileSync(html404AndParentDirIsEmptyFileUrl),
|
|
192
|
-
);
|
|
193
|
-
return replacePlaceholders(htmlFor404AndParentDirIsEmpty, {
|
|
194
|
-
fileRelativeUrl: urlToRelativeUrl(url, rootDirectoryUrl),
|
|
195
|
-
parentDirectoryRelativeUrl: urlToRelativeUrl(
|
|
196
|
-
parentDirectoryUrl,
|
|
197
|
-
rootDirectoryUrl,
|
|
198
|
-
),
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
197
|
const htmlFor404AndParentDir = String(
|
|
202
198
|
readFileSync(html404AndParentDirFileUrl),
|
|
203
199
|
);
|
|
204
|
-
|
|
200
|
+
const fileRelativeUrl = urlToRelativeUrl(url, rootDirectoryUrl);
|
|
201
|
+
const parentDirectoryRelativeUrl = urlToRelativeUrl(
|
|
202
|
+
parentDirectoryUrl,
|
|
203
|
+
rootDirectoryUrl,
|
|
204
|
+
);
|
|
205
205
|
const replacers = {
|
|
206
206
|
fileUrl: url,
|
|
207
|
-
fileRelativeUrl
|
|
207
|
+
fileRelativeUrl,
|
|
208
208
|
parentDirectoryUrl,
|
|
209
|
-
parentDirectoryRelativeUrl
|
|
210
|
-
|
|
211
|
-
rootDirectoryUrl,
|
|
212
|
-
),
|
|
209
|
+
parentDirectoryRelativeUrl,
|
|
210
|
+
parentDirectoryNav: () =>
|
|
211
|
+
generateDirectoryNav(parentDirectoryRelativeUrl, rootDirectoryUrl),
|
|
213
212
|
parentDirectoryContent: () =>
|
|
214
213
|
generateDirectoryContent(
|
|
215
214
|
parentDirectoryContentArray,
|
|
@@ -220,11 +219,51 @@ const generateHtmlForENOENTOnHtmlFile = (
|
|
|
220
219
|
const html = replacePlaceholders(htmlFor404AndParentDir, replacers);
|
|
221
220
|
return html;
|
|
222
221
|
};
|
|
222
|
+
const generateDirectoryNav = (relativeUrl, rootDirectoryUrl) => {
|
|
223
|
+
const rootDirectoryUrlName = urlToFilename(rootDirectoryUrl);
|
|
224
|
+
const relativeUrlWithRoot = relativeUrl
|
|
225
|
+
? `${rootDirectoryUrlName}/${relativeUrl}`
|
|
226
|
+
: `${rootDirectoryUrlName}/`;
|
|
227
|
+
const isDir = relativeUrlWithRoot.endsWith("/");
|
|
228
|
+
const parts = isDir
|
|
229
|
+
? relativeUrlWithRoot.slice(0, -1).split("/")
|
|
230
|
+
: relativeUrlWithRoot.split("/");
|
|
231
|
+
let dirPartsHtml = "";
|
|
232
|
+
let i = 0;
|
|
233
|
+
while (i < parts.length) {
|
|
234
|
+
const part = parts[i];
|
|
235
|
+
const href = i === 0 ? "/" : `/${parts.slice(1, i + 1).join("/")}/`;
|
|
236
|
+
const text = part;
|
|
237
|
+
const isLastPart = i === parts.length - 1;
|
|
238
|
+
if (isLastPart) {
|
|
239
|
+
dirPartsHtml += `
|
|
240
|
+
<span class="directory_nav_item" data-current>
|
|
241
|
+
${text}
|
|
242
|
+
</span>`;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
dirPartsHtml += `
|
|
246
|
+
<a class="directory_nav_item" href="${href}">
|
|
247
|
+
${text}
|
|
248
|
+
</a>`;
|
|
249
|
+
dirPartsHtml += `
|
|
250
|
+
<span class="directory_separator">/</span>`;
|
|
251
|
+
i++;
|
|
252
|
+
}
|
|
253
|
+
if (isDir) {
|
|
254
|
+
dirPartsHtml += `
|
|
255
|
+
<span class="directory_separator">/</span>`;
|
|
256
|
+
}
|
|
257
|
+
return dirPartsHtml;
|
|
258
|
+
};
|
|
223
259
|
const generateDirectoryContent = (
|
|
224
260
|
directoryContentArray,
|
|
225
261
|
directoryUrl,
|
|
226
262
|
rootDirectoryUrl,
|
|
227
263
|
) => {
|
|
264
|
+
if (directoryContentArray.length === 0) {
|
|
265
|
+
return `<p>Directory is empty</p>`;
|
|
266
|
+
}
|
|
228
267
|
const sortedNames = [];
|
|
229
268
|
for (const filename of directoryContentArray) {
|
|
230
269
|
const fileUrlObject = new URL(filename, directoryUrl);
|
|
@@ -235,15 +274,20 @@ const generateDirectoryContent = (
|
|
|
235
274
|
}
|
|
236
275
|
}
|
|
237
276
|
sortedNames.sort(comparePathnames);
|
|
238
|
-
|
|
277
|
+
let html = `<ul class="directory_content">`;
|
|
278
|
+
for (const filename of sortedNames) {
|
|
239
279
|
const fileUrlObject = new URL(filename, directoryUrl);
|
|
240
280
|
const fileUrl = String(fileUrlObject);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
281
|
+
const fileUrlRelativeToParent = urlToRelativeUrl(fileUrl, directoryUrl);
|
|
282
|
+
const fileUrlRelativeToRoot = urlToRelativeUrl(fileUrl, rootDirectoryUrl);
|
|
283
|
+
const type = fileUrlRelativeToParent.endsWith("/") ? "dir" : "file";
|
|
284
|
+
html += `
|
|
285
|
+
<li class="directory_child" data-type="${type}">
|
|
286
|
+
<a href="/${fileUrlRelativeToRoot}">${fileUrlRelativeToParent}</a>
|
|
287
|
+
</li>`;
|
|
288
|
+
}
|
|
289
|
+
html += `\n </ul>`;
|
|
290
|
+
return html;
|
|
247
291
|
};
|
|
248
292
|
const replacePlaceholders = (html, replacers) => {
|
|
249
293
|
return html.replace(/\$\{(\w+)\}/g, (match, name) => {
|
|
@@ -57,6 +57,11 @@ export const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
resolveReference: (reference) => {
|
|
60
|
+
if (reference.specifier.startsWith("node_esm:")) {
|
|
61
|
+
reference.specifier = reference.specifier.slice("node_esm:".length);
|
|
62
|
+
const result = nodeEsmResolverDefault(reference);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
60
65
|
const urlType = urlTypeFromReference(reference);
|
|
61
66
|
const resolver = resolvers[urlType];
|
|
62
67
|
return resolver ? resolver(reference) : null;
|
|
@@ -83,6 +88,5 @@ const urlTypeFromReference = (reference) => {
|
|
|
83
88
|
if (reference.injected) {
|
|
84
89
|
return reference.expectedType;
|
|
85
90
|
}
|
|
86
|
-
|
|
87
91
|
return reference.ownerUrlInfo.type;
|
|
88
92
|
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>404 ENOENT</title>
|
|
5
|
-
<meta charset="utf-8">
|
|
6
|
-
<link rel="icon" href="data:,">
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
<p>No entry on the filesystem for <strong>/${fileRelativeUrl}</strong></p>
|
|
11
|
-
<p>
|
|
12
|
-
<a jsenv-ignore="" href="/${parentDirectoryRelativeUrl}">/${parentDirectoryRelativeUrl}</a>
|
|
13
|
-
directory is empty.
|
|
14
|
-
</p>
|
|
15
|
-
</body>
|
|
16
|
-
</html>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>Directory explorer</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<link rel="icon" href="data:," />
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
<h1>
|
|
11
|
-
<a jsenv-ignore href="/${directoryRelativeUrl}"
|
|
12
|
-
>/${directoryRelativeUrl}</a
|
|
13
|
-
>
|
|
14
|
-
directory content:
|
|
15
|
-
</h1>
|
|
16
|
-
<ul>
|
|
17
|
-
${directoryContent}
|
|
18
|
-
</ul>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>404 ENOENT</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<link rel="icon" href="data:," />
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
<p>No entry on the filesystem for <strong>/${fileRelativeUrl}</strong></p>
|
|
11
|
-
<p>
|
|
12
|
-
<a jsenv-ignore href="/${parentDirectoryRelativeUrl}"
|
|
13
|
-
>/${parentDirectoryRelativeUrl}</a
|
|
14
|
-
>
|
|
15
|
-
directory content:
|
|
16
|
-
</p>
|
|
17
|
-
<ul>
|
|
18
|
-
${parentDirectoryContent}
|
|
19
|
-
</ul>
|
|
20
|
-
</body>
|
|
21
|
-
</html>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<title>404 ENOENT</title>
|
|
5
|
-
<meta charset="utf-8" />
|
|
6
|
-
<link rel="icon" href="data:," />
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
<p>No entry on the filesystem for <strong>/${fileRelativeUrl}</strong></p>
|
|
11
|
-
<p>
|
|
12
|
-
<a jsenv-ignore href="/${parentDirectoryRelativeUrl}"
|
|
13
|
-
>/${parentDirectoryRelativeUrl}</a
|
|
14
|
-
>
|
|
15
|
-
directory is empty.
|
|
16
|
-
</p>
|
|
17
|
-
</body>
|
|
18
|
-
</html>
|