@jsenv/core 40.8.4 → 40.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.
- package/dist/build/build.js +76 -28
- package/dist/build/jsenv_core_packages.js +31 -11
- package/dist/client/directory_listing/css/directory_listing.css +10 -3
- package/dist/client/directory_listing/js/directory_listing.js +40 -18
- package/dist/js/drop_to_open.js +51 -0
- package/dist/js/import_meta_css.js +6 -1
- package/dist/start_dev_server/jsenv_core_packages.js +57 -41
- package/dist/start_dev_server/start_dev_server.js +78 -28
- package/package.json +6 -6
- package/src/dev/start_dev_server.js +2 -0
- package/src/kitchen/kitchen.js +5 -0
- package/src/plugins/drop_to_open/client/drop_to_open.js +49 -0
- package/src/plugins/drop_to_open/jsenv_plugin_drop_to_open.js +43 -0
- package/src/plugins/import_meta_css/client/import_meta_css.js +4 -1
- package/src/plugins/plugins.js +2 -0
- package/src/plugins/protocol_file/client/directory_listing.css +10 -3
- package/src/plugins/protocol_file/client/directory_listing.jsx +32 -15
- package/src/plugins/protocol_file/jsenv_plugin_directory_listing.js +1 -1
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +1 -1
- /package/src/{plugins/protocol_file → kitchen}/file_and_server_urls_converter.js +0 -0
package/dist/build/build.js
CHANGED
|
@@ -527,6 +527,34 @@ const assertFetchedContentCompliance = ({ urlInfo, content }) => {
|
|
|
527
527
|
}
|
|
528
528
|
};
|
|
529
529
|
|
|
530
|
+
const FILE_AND_SERVER_URLS_CONVERTER = {
|
|
531
|
+
asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
|
|
532
|
+
if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
|
|
533
|
+
const urlRelativeToServer = urlToRelativeUrl(
|
|
534
|
+
fileUrl,
|
|
535
|
+
serverRootDirectoryUrl,
|
|
536
|
+
);
|
|
537
|
+
return `/${urlRelativeToServer}`;
|
|
538
|
+
}
|
|
539
|
+
const urlRelativeToFilesystemRoot = String(fileUrl).slice(
|
|
540
|
+
"file:///".length,
|
|
541
|
+
);
|
|
542
|
+
return `/@fs/${urlRelativeToFilesystemRoot}`;
|
|
543
|
+
},
|
|
544
|
+
asFileUrl: (urlRelativeToServer, serverRootDirectoryUrl) => {
|
|
545
|
+
if (urlRelativeToServer.startsWith("/@fs/")) {
|
|
546
|
+
const urlRelativeToFilesystemRoot = urlRelativeToServer.slice(
|
|
547
|
+
"/@fs/".length,
|
|
548
|
+
);
|
|
549
|
+
return `file:///${urlRelativeToFilesystemRoot}`;
|
|
550
|
+
}
|
|
551
|
+
if (urlRelativeToServer[0] === "/") {
|
|
552
|
+
return new URL(urlRelativeToServer.slice(1), serverRootDirectoryUrl).href;
|
|
553
|
+
}
|
|
554
|
+
return new URL(urlRelativeToServer, serverRootDirectoryUrl).href;
|
|
555
|
+
},
|
|
556
|
+
};
|
|
557
|
+
|
|
530
558
|
const determineFileUrlForOutDirectory = (urlInfo) => {
|
|
531
559
|
let { url, filenameHint } = urlInfo;
|
|
532
560
|
const { rootDirectoryUrl, outDirectoryUrl } = urlInfo.context;
|
|
@@ -2952,6 +2980,10 @@ const createKitchen = ({
|
|
|
2952
2980
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
2953
2981
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
2954
2982
|
isPlaceholderInjection,
|
|
2983
|
+
asServerUrl: (fileUrl) =>
|
|
2984
|
+
FILE_AND_SERVER_URLS_CONVERTER.asServerUrl(fileUrl, rootDirectoryUrl),
|
|
2985
|
+
asFileUrl: (serverUrl) =>
|
|
2986
|
+
FILE_AND_SERVER_URLS_CONVERTER.asFileUrl(serverUrl, rootDirectoryUrl),
|
|
2955
2987
|
INJECTIONS,
|
|
2956
2988
|
getPluginMeta: null,
|
|
2957
2989
|
sourcemaps,
|
|
@@ -6486,34 +6518,6 @@ const jsenvPluginVersionSearchParam = () => {
|
|
|
6486
6518
|
};
|
|
6487
6519
|
};
|
|
6488
6520
|
|
|
6489
|
-
const FILE_AND_SERVER_URLS_CONVERTER = {
|
|
6490
|
-
asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
|
|
6491
|
-
if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
|
|
6492
|
-
const urlRelativeToServer = urlToRelativeUrl(
|
|
6493
|
-
fileUrl,
|
|
6494
|
-
serverRootDirectoryUrl,
|
|
6495
|
-
);
|
|
6496
|
-
return `/${urlRelativeToServer}`;
|
|
6497
|
-
}
|
|
6498
|
-
const urlRelativeToFilesystemRoot = String(fileUrl).slice(
|
|
6499
|
-
"file:///".length,
|
|
6500
|
-
);
|
|
6501
|
-
return `/@fs/${urlRelativeToFilesystemRoot}`;
|
|
6502
|
-
},
|
|
6503
|
-
asFileUrl: (urlRelativeToServer, serverRootDirectoryUrl) => {
|
|
6504
|
-
if (urlRelativeToServer.startsWith("/@fs/")) {
|
|
6505
|
-
const urlRelativeToFilesystemRoot = urlRelativeToServer.slice(
|
|
6506
|
-
"/@fs/".length,
|
|
6507
|
-
);
|
|
6508
|
-
return `file:///${urlRelativeToFilesystemRoot}`;
|
|
6509
|
-
}
|
|
6510
|
-
if (urlRelativeToServer[0] === "/") {
|
|
6511
|
-
return new URL(urlRelativeToServer.slice(1), serverRootDirectoryUrl).href;
|
|
6512
|
-
}
|
|
6513
|
-
return new URL(urlRelativeToServer, serverRootDirectoryUrl).href;
|
|
6514
|
-
},
|
|
6515
|
-
};
|
|
6516
|
-
|
|
6517
6521
|
/*
|
|
6518
6522
|
* NICE TO HAVE:
|
|
6519
6523
|
*
|
|
@@ -8818,6 +8822,49 @@ const jsenvPluginRibbon = ({
|
|
|
8818
8822
|
};
|
|
8819
8823
|
};
|
|
8820
8824
|
|
|
8825
|
+
/**
|
|
8826
|
+
* HTML page server by jsenv dev server will listen for drop events
|
|
8827
|
+
* and redirect the browser to the dropped file location.
|
|
8828
|
+
*
|
|
8829
|
+
* Works only for VSCode right now (because it sets "resourceurls" dataTransfer type).
|
|
8830
|
+
*
|
|
8831
|
+
*/
|
|
8832
|
+
|
|
8833
|
+
|
|
8834
|
+
const jsenvPluginDropToOpen = () => {
|
|
8835
|
+
const clientFileUrl = import.meta.resolve("../js/drop_to_open.js");
|
|
8836
|
+
return {
|
|
8837
|
+
name: "jsenv:drop_to_open",
|
|
8838
|
+
appliesDuring: "dev",
|
|
8839
|
+
transformUrlContent: {
|
|
8840
|
+
html: (urlInfo) => {
|
|
8841
|
+
const htmlAst = parseHtml({
|
|
8842
|
+
html: urlInfo.content,
|
|
8843
|
+
url: urlInfo.url,
|
|
8844
|
+
});
|
|
8845
|
+
const clientFileReference = urlInfo.dependencies.inject({
|
|
8846
|
+
type: "script",
|
|
8847
|
+
subtype: "js_module",
|
|
8848
|
+
expectedType: "js_module",
|
|
8849
|
+
specifier: clientFileUrl,
|
|
8850
|
+
});
|
|
8851
|
+
injectJsenvScript(htmlAst, {
|
|
8852
|
+
type: "module",
|
|
8853
|
+
src: clientFileReference.generatedSpecifier,
|
|
8854
|
+
initCall: {
|
|
8855
|
+
callee: "initDropToOpen",
|
|
8856
|
+
params: {
|
|
8857
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
8858
|
+
},
|
|
8859
|
+
},
|
|
8860
|
+
pluginName: "jsenv:drop_to_open",
|
|
8861
|
+
});
|
|
8862
|
+
return stringifyHtmlAst(htmlAst);
|
|
8863
|
+
},
|
|
8864
|
+
},
|
|
8865
|
+
};
|
|
8866
|
+
};
|
|
8867
|
+
|
|
8821
8868
|
const jsenvPluginCleanHTML = () => {
|
|
8822
8869
|
return {
|
|
8823
8870
|
name: "jsenv:cleanup_html_during_dev",
|
|
@@ -9198,6 +9245,7 @@ const getCorePlugins = ({
|
|
|
9198
9245
|
: []),
|
|
9199
9246
|
...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []),
|
|
9200
9247
|
...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
|
|
9248
|
+
jsenvPluginDropToOpen(),
|
|
9201
9249
|
jsenvPluginCleanHTML(),
|
|
9202
9250
|
jsenvPluginChromeDevtoolsJson(),
|
|
9203
9251
|
...(packageSideEffects
|
|
@@ -2692,15 +2692,24 @@ const createLookupPackageDirectory = () => {
|
|
|
2692
2692
|
};
|
|
2693
2693
|
|
|
2694
2694
|
const readPackageAtOrNull = (packageDirectoryUrl) => {
|
|
2695
|
+
const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl);
|
|
2696
|
+
let packageJsonFileContentBuffer;
|
|
2695
2697
|
try {
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2698
|
+
packageJsonFileContentBuffer = readFileSync$1(packageJsonFileUrl, "utf8");
|
|
2699
|
+
} catch (e) {
|
|
2700
|
+
if (e.code === "ENOENT") {
|
|
2701
|
+
return null;
|
|
2702
|
+
}
|
|
2703
|
+
throw e;
|
|
2704
|
+
}
|
|
2705
|
+
const packageJsonFileContentString = String(packageJsonFileContentBuffer);
|
|
2706
|
+
try {
|
|
2707
|
+
const packageJsonFileContentObject = JSON.parse(
|
|
2708
|
+
packageJsonFileContentString,
|
|
2699
2709
|
);
|
|
2700
|
-
|
|
2701
|
-
return packageJSON;
|
|
2710
|
+
return packageJsonFileContentObject;
|
|
2702
2711
|
} catch {
|
|
2703
|
-
|
|
2712
|
+
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
2704
2713
|
}
|
|
2705
2714
|
};
|
|
2706
2715
|
|
|
@@ -5244,13 +5253,24 @@ const defaultLookupPackageScope = (url) => {
|
|
|
5244
5253
|
};
|
|
5245
5254
|
|
|
5246
5255
|
const defaultReadPackageJson = (packageUrl) => {
|
|
5247
|
-
const
|
|
5248
|
-
|
|
5249
|
-
const string = String(buffer);
|
|
5256
|
+
const packageJsonFileUrl = new URL("./package.json", packageUrl);
|
|
5257
|
+
let packageJsonFileContentBuffer;
|
|
5250
5258
|
try {
|
|
5251
|
-
|
|
5259
|
+
packageJsonFileContentBuffer = readFileSync$1(packageJsonFileUrl, "utf8");
|
|
5260
|
+
} catch (e) {
|
|
5261
|
+
if (e.code === "ENOENT") {
|
|
5262
|
+
return null;
|
|
5263
|
+
}
|
|
5264
|
+
throw e;
|
|
5265
|
+
}
|
|
5266
|
+
const packageJsonFileContentString = String(packageJsonFileContentBuffer);
|
|
5267
|
+
try {
|
|
5268
|
+
const packageJsonFileContentObject = JSON.parse(
|
|
5269
|
+
packageJsonFileContentString,
|
|
5270
|
+
);
|
|
5271
|
+
return packageJsonFileContentObject;
|
|
5252
5272
|
} catch {
|
|
5253
|
-
throw new Error(`Invalid package configuration`);
|
|
5273
|
+
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
5254
5274
|
}
|
|
5255
5275
|
};
|
|
5256
5276
|
|
|
@@ -99,8 +99,10 @@ a.nav_item_text {
|
|
|
99
99
|
|
|
100
100
|
.directory_content {
|
|
101
101
|
border-radius: 3px;
|
|
102
|
+
flex-direction: column;
|
|
102
103
|
margin: 10px 15px;
|
|
103
104
|
list-style-type: none;
|
|
105
|
+
display: flex;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
.directory_content_item {
|
|
@@ -109,7 +111,7 @@ a.nav_item_text {
|
|
|
109
111
|
min-height: 19px;
|
|
110
112
|
padding: 10px 15px;
|
|
111
113
|
font-size: 15px;
|
|
112
|
-
display: flex;
|
|
114
|
+
display: inline-flex;
|
|
113
115
|
position: relative;
|
|
114
116
|
}
|
|
115
117
|
|
|
@@ -117,13 +119,16 @@ a.nav_item_text {
|
|
|
117
119
|
flex: 1;
|
|
118
120
|
align-items: center;
|
|
119
121
|
gap: 10px;
|
|
122
|
+
min-width: 0;
|
|
123
|
+
max-width: 100%;
|
|
120
124
|
text-decoration: none;
|
|
121
|
-
display: flex;
|
|
125
|
+
display: inline-flex;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
.directory_content_item_icon {
|
|
125
129
|
aspect-ratio: 1;
|
|
126
130
|
color: #f1f1f1;
|
|
131
|
+
flex-shrink: 0;
|
|
127
132
|
width: 15px;
|
|
128
133
|
display: flex;
|
|
129
134
|
}
|
|
@@ -133,7 +138,9 @@ a.nav_item_text {
|
|
|
133
138
|
}
|
|
134
139
|
|
|
135
140
|
.directory_content_item_text {
|
|
136
|
-
|
|
141
|
+
flex-grow: 1;
|
|
142
|
+
align-items: center;
|
|
143
|
+
display: inline-flex;
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
.directory_content_item:last-child {
|
|
@@ -53,15 +53,17 @@ const ErrorMessage = () => {
|
|
|
53
53
|
errorText = u(k, {
|
|
54
54
|
children: [u("strong", {
|
|
55
55
|
children: "File not found:"
|
|
56
|
-
}), "\xA0", u(
|
|
57
|
-
children: [u("
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
}), "\xA0", u(Overflow, {
|
|
57
|
+
children: [u("code", {
|
|
58
|
+
children: [u("span", {
|
|
59
|
+
className: "file_path_good",
|
|
60
|
+
children: filePathExisting
|
|
61
|
+
}), u("span", {
|
|
62
|
+
className: "file_path_bad",
|
|
63
|
+
children: filePathNotFound
|
|
64
|
+
})]
|
|
65
|
+
}), " ", "does not exist on the server."]
|
|
66
|
+
})]
|
|
65
67
|
});
|
|
66
68
|
errorSuggestion = u(k, {
|
|
67
69
|
children: [u("span", {
|
|
@@ -84,6 +86,21 @@ const ErrorMessage = () => {
|
|
|
84
86
|
})]
|
|
85
87
|
});
|
|
86
88
|
};
|
|
89
|
+
const Overflow = ({
|
|
90
|
+
children,
|
|
91
|
+
afterContent
|
|
92
|
+
}) => {
|
|
93
|
+
return u("div", {
|
|
94
|
+
style: "display: flex; flex-wrap: wrap; overflow: hidden; width: 100%; box-sizing: border-box; white-space: nowrap; text-overflow: ellipsis;",
|
|
95
|
+
children: u("div", {
|
|
96
|
+
style: "display: flex; flex-grow: 1; width: 0;",
|
|
97
|
+
children: [u("div", {
|
|
98
|
+
style: "overflow: hidden; max-width: 100%; text-overflow: ellipsis;",
|
|
99
|
+
children: children
|
|
100
|
+
}), afterContent]
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
};
|
|
87
104
|
const Breadcrumb = ({
|
|
88
105
|
items
|
|
89
106
|
}) => {
|
|
@@ -163,7 +180,7 @@ const DirectoryContent = ({
|
|
|
163
180
|
url: directoryItem.urlRelativeToServer,
|
|
164
181
|
isDirectory: directoryItem.url.endsWith("/"),
|
|
165
182
|
isMainFile: directoryItem.isMainFile,
|
|
166
|
-
children: directoryItem.urlRelativeToCurrentDirectory
|
|
183
|
+
children: decodeURI(directoryItem.urlRelativeToCurrentDirectory)
|
|
167
184
|
}, directoryItem.url);
|
|
168
185
|
})
|
|
169
186
|
});
|
|
@@ -189,14 +206,19 @@ const DirectoryContentItem = ({
|
|
|
189
206
|
children: u(Icon, {
|
|
190
207
|
url: isMainFile ? homeIconUrl : isDirectory ? directoryIconUrl : fileIconUrl
|
|
191
208
|
})
|
|
192
|
-
}),
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
children: u(
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
}), u("span", {
|
|
210
|
+
className: "directory_content_item_text",
|
|
211
|
+
children: [u(Overflow, {
|
|
212
|
+
children: children
|
|
213
|
+
}), isDirectory ? u(k, {
|
|
214
|
+
children: [u("span", {
|
|
215
|
+
style: "flex:1"
|
|
216
|
+
}), u("span", {
|
|
217
|
+
className: "directory_content_item_arrow",
|
|
218
|
+
children: u(RightArrowSvg, {})
|
|
219
|
+
})]
|
|
220
|
+
}) : null]
|
|
221
|
+
})]
|
|
200
222
|
})
|
|
201
223
|
});
|
|
202
224
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const initDropToOpen = ({ rootDirectoryUrl }) => {
|
|
2
|
+
const dataTransferCandidates = [
|
|
3
|
+
(dataTransfer) => {
|
|
4
|
+
if (!dataTransfer.types.includes("resourceurls")) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return () => {
|
|
8
|
+
const data = dataTransfer.getData("resourceurls");
|
|
9
|
+
const urls = JSON.parse(data);
|
|
10
|
+
if (!Array.isArray(urls) || urls.length === 0) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const [url] = urls;
|
|
14
|
+
const fileUrl = new URL(url).href;
|
|
15
|
+
let serverUrl;
|
|
16
|
+
|
|
17
|
+
if (fileUrl.startsWith(rootDirectoryUrl)) {
|
|
18
|
+
const serverRelativeUrl = fileUrl.slice(rootDirectoryUrl.length);
|
|
19
|
+
serverUrl = `/${serverRelativeUrl}`;
|
|
20
|
+
} else {
|
|
21
|
+
serverUrl = `/@fs/${fileUrl}`;
|
|
22
|
+
}
|
|
23
|
+
window.location.href = serverUrl;
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
document.addEventListener("dragover", (event) => {
|
|
29
|
+
for (const candidate of dataTransferCandidates) {
|
|
30
|
+
const dataTransferHandler = candidate(event.dataTransfer);
|
|
31
|
+
if (dataTransferHandler) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
document.addEventListener("drop", (event) => {
|
|
38
|
+
let handler;
|
|
39
|
+
for (const candidate of dataTransferCandidates) {
|
|
40
|
+
const dataTransferHandler = candidate(event.dataTransfer);
|
|
41
|
+
if (dataTransferHandler) {
|
|
42
|
+
handler = dataTransferHandler;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
handler();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { initDropToOpen };
|
|
@@ -2,12 +2,17 @@ import "file:///Users/dmail/Documents/dev/jsenv/core/packages/internal/plugin-tr
|
|
|
2
2
|
|
|
3
3
|
const installImportMetaCss = importMeta => {
|
|
4
4
|
let cssText = "";
|
|
5
|
-
let stylesheet = new CSSStyleSheet(
|
|
5
|
+
let stylesheet = new CSSStyleSheet({
|
|
6
|
+
baseUrl: importMeta.url
|
|
7
|
+
});
|
|
6
8
|
let adopted = false;
|
|
7
9
|
const css = {
|
|
8
10
|
toString: () => cssText,
|
|
9
11
|
update: value => {
|
|
10
12
|
cssText = value;
|
|
13
|
+
cssText += `
|
|
14
|
+
/* sourceURL=${importMeta.url} */
|
|
15
|
+
/* inlined from ${importMeta.url} */`;
|
|
11
16
|
stylesheet.replaceSync(cssText);
|
|
12
17
|
},
|
|
13
18
|
inject: () => {
|
|
@@ -267,6 +267,31 @@ const UNICODE = createUnicode({
|
|
|
267
267
|
ANSI,
|
|
268
268
|
});
|
|
269
269
|
|
|
270
|
+
const prefixFirstAndIndentRemainingLines = (
|
|
271
|
+
text,
|
|
272
|
+
{ prefix, indentation, trimLines, trimLastLine },
|
|
273
|
+
) => {
|
|
274
|
+
const lines = text.split(/\r?\n/);
|
|
275
|
+
const firstLine = lines.shift();
|
|
276
|
+
if (indentation === undefined) {
|
|
277
|
+
{
|
|
278
|
+
indentation = " "; // prefix + space
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
let result = `${prefix} ${firstLine}` ;
|
|
282
|
+
let i = 0;
|
|
283
|
+
while (i < lines.length) {
|
|
284
|
+
const line = trimLines ? lines[i].trim() : lines[i];
|
|
285
|
+
i++;
|
|
286
|
+
result += line.length
|
|
287
|
+
? `\n${indentation}${line}`
|
|
288
|
+
: trimLastLine && i === lines.length
|
|
289
|
+
? ""
|
|
290
|
+
: `\n`;
|
|
291
|
+
}
|
|
292
|
+
return result;
|
|
293
|
+
};
|
|
294
|
+
|
|
270
295
|
const setRoundedPrecision = (
|
|
271
296
|
number,
|
|
272
297
|
{ decimals = 1, decimalsWhenSmall = decimals } = {},
|
|
@@ -643,10 +668,9 @@ const formatError = (error) => {
|
|
|
643
668
|
const { cause } = error;
|
|
644
669
|
if (cause) {
|
|
645
670
|
const formatCause = (cause, depth) => {
|
|
646
|
-
let causeText = prefixFirstAndIndentRemainingLines({
|
|
671
|
+
let causeText = prefixFirstAndIndentRemainingLines(cause.stack, {
|
|
647
672
|
prefix: " [cause]:",
|
|
648
673
|
indentation: " ".repeat(depth + 1),
|
|
649
|
-
text: cause.stack,
|
|
650
674
|
});
|
|
651
675
|
const nestedCause = cause.cause;
|
|
652
676
|
if (nestedCause) {
|
|
@@ -661,34 +685,6 @@ const formatError = (error) => {
|
|
|
661
685
|
return text;
|
|
662
686
|
};
|
|
663
687
|
|
|
664
|
-
const prefixFirstAndIndentRemainingLines = ({
|
|
665
|
-
prefix,
|
|
666
|
-
indentation,
|
|
667
|
-
text,
|
|
668
|
-
trimLines,
|
|
669
|
-
trimLastLine,
|
|
670
|
-
}) => {
|
|
671
|
-
const lines = text.split(/\r?\n/);
|
|
672
|
-
const firstLine = lines.shift();
|
|
673
|
-
if (indentation === undefined) {
|
|
674
|
-
{
|
|
675
|
-
indentation = " "; // prefix + space
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
let result = `${prefix} ${firstLine}` ;
|
|
679
|
-
let i = 0;
|
|
680
|
-
while (i < lines.length) {
|
|
681
|
-
const line = trimLines ? lines[i].trim() : lines[i];
|
|
682
|
-
i++;
|
|
683
|
-
result += line.length
|
|
684
|
-
? `\n${indentation}${line}`
|
|
685
|
-
: trimLastLine && i === lines.length
|
|
686
|
-
? ""
|
|
687
|
-
: `\n`;
|
|
688
|
-
}
|
|
689
|
-
return result;
|
|
690
|
-
};
|
|
691
|
-
|
|
692
688
|
const LOG_LEVEL_OFF = "off";
|
|
693
689
|
|
|
694
690
|
const LOG_LEVEL_DEBUG = "debug";
|
|
@@ -1958,15 +1954,24 @@ const lookupPackageDirectory = (currentUrl) => {
|
|
|
1958
1954
|
};
|
|
1959
1955
|
|
|
1960
1956
|
const readPackageAtOrNull = (packageDirectoryUrl) => {
|
|
1957
|
+
const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl);
|
|
1958
|
+
let packageJsonFileContentBuffer;
|
|
1959
|
+
try {
|
|
1960
|
+
packageJsonFileContentBuffer = readFileSync(packageJsonFileUrl, "utf8");
|
|
1961
|
+
} catch (e) {
|
|
1962
|
+
if (e.code === "ENOENT") {
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
throw e;
|
|
1966
|
+
}
|
|
1967
|
+
const packageJsonFileContentString = String(packageJsonFileContentBuffer);
|
|
1961
1968
|
try {
|
|
1962
|
-
const
|
|
1963
|
-
|
|
1964
|
-
"utf8",
|
|
1969
|
+
const packageJsonFileContentObject = JSON.parse(
|
|
1970
|
+
packageJsonFileContentString,
|
|
1965
1971
|
);
|
|
1966
|
-
|
|
1967
|
-
return packageJSON;
|
|
1972
|
+
return packageJsonFileContentObject;
|
|
1968
1973
|
} catch {
|
|
1969
|
-
|
|
1974
|
+
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
1970
1975
|
}
|
|
1971
1976
|
};
|
|
1972
1977
|
|
|
@@ -3878,13 +3883,24 @@ const defaultLookupPackageScope = (url) => {
|
|
|
3878
3883
|
};
|
|
3879
3884
|
|
|
3880
3885
|
const defaultReadPackageJson = (packageUrl) => {
|
|
3881
|
-
const
|
|
3882
|
-
|
|
3883
|
-
const string = String(buffer);
|
|
3886
|
+
const packageJsonFileUrl = new URL("./package.json", packageUrl);
|
|
3887
|
+
let packageJsonFileContentBuffer;
|
|
3884
3888
|
try {
|
|
3885
|
-
|
|
3889
|
+
packageJsonFileContentBuffer = readFileSync(packageJsonFileUrl, "utf8");
|
|
3890
|
+
} catch (e) {
|
|
3891
|
+
if (e.code === "ENOENT") {
|
|
3892
|
+
return null;
|
|
3893
|
+
}
|
|
3894
|
+
throw e;
|
|
3895
|
+
}
|
|
3896
|
+
const packageJsonFileContentString = String(packageJsonFileContentBuffer);
|
|
3897
|
+
try {
|
|
3898
|
+
const packageJsonFileContentObject = JSON.parse(
|
|
3899
|
+
packageJsonFileContentString,
|
|
3900
|
+
);
|
|
3901
|
+
return packageJsonFileContentObject;
|
|
3886
3902
|
} catch {
|
|
3887
|
-
throw new Error(`Invalid package configuration`);
|
|
3903
|
+
throw new Error(`Invalid package configuration at ${packageJsonFileUrl}`);
|
|
3888
3904
|
}
|
|
3889
3905
|
};
|
|
3890
3906
|
|
|
@@ -586,6 +586,34 @@ const assertFetchedContentCompliance = ({ urlInfo, content }) => {
|
|
|
586
586
|
}
|
|
587
587
|
};
|
|
588
588
|
|
|
589
|
+
const FILE_AND_SERVER_URLS_CONVERTER = {
|
|
590
|
+
asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
|
|
591
|
+
if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
|
|
592
|
+
const urlRelativeToServer = urlToRelativeUrl(
|
|
593
|
+
fileUrl,
|
|
594
|
+
serverRootDirectoryUrl,
|
|
595
|
+
);
|
|
596
|
+
return `/${urlRelativeToServer}`;
|
|
597
|
+
}
|
|
598
|
+
const urlRelativeToFilesystemRoot = String(fileUrl).slice(
|
|
599
|
+
"file:///".length,
|
|
600
|
+
);
|
|
601
|
+
return `/@fs/${urlRelativeToFilesystemRoot}`;
|
|
602
|
+
},
|
|
603
|
+
asFileUrl: (urlRelativeToServer, serverRootDirectoryUrl) => {
|
|
604
|
+
if (urlRelativeToServer.startsWith("/@fs/")) {
|
|
605
|
+
const urlRelativeToFilesystemRoot = urlRelativeToServer.slice(
|
|
606
|
+
"/@fs/".length,
|
|
607
|
+
);
|
|
608
|
+
return `file:///${urlRelativeToFilesystemRoot}`;
|
|
609
|
+
}
|
|
610
|
+
if (urlRelativeToServer[0] === "/") {
|
|
611
|
+
return new URL(urlRelativeToServer.slice(1), serverRootDirectoryUrl).href;
|
|
612
|
+
}
|
|
613
|
+
return new URL(urlRelativeToServer, serverRootDirectoryUrl).href;
|
|
614
|
+
},
|
|
615
|
+
};
|
|
616
|
+
|
|
589
617
|
const determineFileUrlForOutDirectory = (urlInfo) => {
|
|
590
618
|
let { url, filenameHint } = urlInfo;
|
|
591
619
|
const { rootDirectoryUrl, outDirectoryUrl } = urlInfo.context;
|
|
@@ -2992,6 +3020,10 @@ const createKitchen = ({
|
|
|
2992
3020
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
2993
3021
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
2994
3022
|
isPlaceholderInjection,
|
|
3023
|
+
asServerUrl: (fileUrl) =>
|
|
3024
|
+
FILE_AND_SERVER_URLS_CONVERTER.asServerUrl(fileUrl, rootDirectoryUrl),
|
|
3025
|
+
asFileUrl: (serverUrl) =>
|
|
3026
|
+
FILE_AND_SERVER_URLS_CONVERTER.asFileUrl(serverUrl, rootDirectoryUrl),
|
|
2995
3027
|
INJECTIONS,
|
|
2996
3028
|
getPluginMeta: null,
|
|
2997
3029
|
sourcemaps,
|
|
@@ -6191,34 +6223,6 @@ const jsenvPluginVersionSearchParam = () => {
|
|
|
6191
6223
|
};
|
|
6192
6224
|
};
|
|
6193
6225
|
|
|
6194
|
-
const FILE_AND_SERVER_URLS_CONVERTER = {
|
|
6195
|
-
asServerUrl: (fileUrl, serverRootDirectoryUrl) => {
|
|
6196
|
-
if (urlIsOrIsInsideOf(fileUrl, serverRootDirectoryUrl)) {
|
|
6197
|
-
const urlRelativeToServer = urlToRelativeUrl(
|
|
6198
|
-
fileUrl,
|
|
6199
|
-
serverRootDirectoryUrl,
|
|
6200
|
-
);
|
|
6201
|
-
return `/${urlRelativeToServer}`;
|
|
6202
|
-
}
|
|
6203
|
-
const urlRelativeToFilesystemRoot = String(fileUrl).slice(
|
|
6204
|
-
"file:///".length,
|
|
6205
|
-
);
|
|
6206
|
-
return `/@fs/${urlRelativeToFilesystemRoot}`;
|
|
6207
|
-
},
|
|
6208
|
-
asFileUrl: (urlRelativeToServer, serverRootDirectoryUrl) => {
|
|
6209
|
-
if (urlRelativeToServer.startsWith("/@fs/")) {
|
|
6210
|
-
const urlRelativeToFilesystemRoot = urlRelativeToServer.slice(
|
|
6211
|
-
"/@fs/".length,
|
|
6212
|
-
);
|
|
6213
|
-
return `file:///${urlRelativeToFilesystemRoot}`;
|
|
6214
|
-
}
|
|
6215
|
-
if (urlRelativeToServer[0] === "/") {
|
|
6216
|
-
return new URL(urlRelativeToServer.slice(1), serverRootDirectoryUrl).href;
|
|
6217
|
-
}
|
|
6218
|
-
return new URL(urlRelativeToServer, serverRootDirectoryUrl).href;
|
|
6219
|
-
},
|
|
6220
|
-
};
|
|
6221
|
-
|
|
6222
6226
|
/*
|
|
6223
6227
|
* NICE TO HAVE:
|
|
6224
6228
|
*
|
|
@@ -8858,6 +8862,49 @@ const jsenvPluginRibbon = ({
|
|
|
8858
8862
|
};
|
|
8859
8863
|
};
|
|
8860
8864
|
|
|
8865
|
+
/**
|
|
8866
|
+
* HTML page server by jsenv dev server will listen for drop events
|
|
8867
|
+
* and redirect the browser to the dropped file location.
|
|
8868
|
+
*
|
|
8869
|
+
* Works only for VSCode right now (because it sets "resourceurls" dataTransfer type).
|
|
8870
|
+
*
|
|
8871
|
+
*/
|
|
8872
|
+
|
|
8873
|
+
|
|
8874
|
+
const jsenvPluginDropToOpen = () => {
|
|
8875
|
+
const clientFileUrl = import.meta.resolve("../js/drop_to_open.js");
|
|
8876
|
+
return {
|
|
8877
|
+
name: "jsenv:drop_to_open",
|
|
8878
|
+
appliesDuring: "dev",
|
|
8879
|
+
transformUrlContent: {
|
|
8880
|
+
html: (urlInfo) => {
|
|
8881
|
+
const htmlAst = parseHtml({
|
|
8882
|
+
html: urlInfo.content,
|
|
8883
|
+
url: urlInfo.url,
|
|
8884
|
+
});
|
|
8885
|
+
const clientFileReference = urlInfo.dependencies.inject({
|
|
8886
|
+
type: "script",
|
|
8887
|
+
subtype: "js_module",
|
|
8888
|
+
expectedType: "js_module",
|
|
8889
|
+
specifier: clientFileUrl,
|
|
8890
|
+
});
|
|
8891
|
+
injectJsenvScript(htmlAst, {
|
|
8892
|
+
type: "module",
|
|
8893
|
+
src: clientFileReference.generatedSpecifier,
|
|
8894
|
+
initCall: {
|
|
8895
|
+
callee: "initDropToOpen",
|
|
8896
|
+
params: {
|
|
8897
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
8898
|
+
},
|
|
8899
|
+
},
|
|
8900
|
+
pluginName: "jsenv:drop_to_open",
|
|
8901
|
+
});
|
|
8902
|
+
return stringifyHtmlAst(htmlAst);
|
|
8903
|
+
},
|
|
8904
|
+
},
|
|
8905
|
+
};
|
|
8906
|
+
};
|
|
8907
|
+
|
|
8861
8908
|
const jsenvPluginCleanHTML = () => {
|
|
8862
8909
|
return {
|
|
8863
8910
|
name: "jsenv:cleanup_html_during_dev",
|
|
@@ -9238,6 +9285,7 @@ const getCorePlugins = ({
|
|
|
9238
9285
|
: []),
|
|
9239
9286
|
...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []),
|
|
9240
9287
|
...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
|
|
9288
|
+
jsenvPluginDropToOpen(),
|
|
9241
9289
|
jsenvPluginCleanHTML(),
|
|
9242
9290
|
jsenvPluginChromeDevtoolsJson(),
|
|
9243
9291
|
...(packageSideEffects
|
|
@@ -9405,6 +9453,7 @@ const startDevServer = async ({
|
|
|
9405
9453
|
http2 = false,
|
|
9406
9454
|
logLevel = EXECUTED_BY_TEST_PLAN ? "warn" : "info",
|
|
9407
9455
|
serverLogLevel = "warn",
|
|
9456
|
+
serverRouterLogLevel = "warn",
|
|
9408
9457
|
services = [],
|
|
9409
9458
|
|
|
9410
9459
|
signal = new AbortController().signal,
|
|
@@ -10011,6 +10060,7 @@ const startDevServer = async ({
|
|
|
10011
10060
|
stopOnInternalError: false,
|
|
10012
10061
|
keepProcessAlive,
|
|
10013
10062
|
logLevel: serverLogLevel,
|
|
10063
|
+
routerLogLevel: serverRouterLogLevel,
|
|
10014
10064
|
startLog: false,
|
|
10015
10065
|
|
|
10016
10066
|
https,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "40.
|
|
3
|
+
"version": "40.9.0",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@jsenv/plugin-minification": "1.7.0",
|
|
82
82
|
"@jsenv/plugin-supervisor": "1.7.5",
|
|
83
83
|
"@jsenv/plugin-transpilation": "1.5.52",
|
|
84
|
-
"@jsenv/server": "16.
|
|
84
|
+
"@jsenv/server": "16.3.0",
|
|
85
85
|
"@jsenv/sourcemap": "1.3.10",
|
|
86
86
|
"react-table": "7.8.0"
|
|
87
87
|
},
|
|
@@ -102,12 +102,12 @@
|
|
|
102
102
|
"@jsenv/integrity": "workspace:*",
|
|
103
103
|
"@jsenv/md-up": "workspace:*",
|
|
104
104
|
"@jsenv/monorepo": "workspace:*",
|
|
105
|
+
"@jsenv/navi": "workspace:*",
|
|
105
106
|
"@jsenv/node-esm-resolution": "workspace:*",
|
|
106
107
|
"@jsenv/os-metrics": "workspace:*",
|
|
107
108
|
"@jsenv/performance-impact": "workspace:*",
|
|
108
109
|
"@jsenv/plugin-as-js-classic": "workspace:*",
|
|
109
110
|
"@jsenv/plugin-database-manager": "workspace:*",
|
|
110
|
-
"@jsenv/router": "workspace:*",
|
|
111
111
|
"@jsenv/runtime-compat": "workspace:*",
|
|
112
112
|
"@jsenv/snapshot": "workspace:*",
|
|
113
113
|
"@jsenv/terminal-table": "workspace:*",
|
|
@@ -124,11 +124,11 @@
|
|
|
124
124
|
"playwright": "1.52.0",
|
|
125
125
|
"preact": "10.26.5",
|
|
126
126
|
"preact-iso": "2.9.1",
|
|
127
|
-
"prettier": "3.
|
|
127
|
+
"prettier": "3.6.2",
|
|
128
128
|
"prettier-plugin-embed": "0.5.0",
|
|
129
129
|
"prettier-plugin-organize-imports": "4.1.0",
|
|
130
|
-
"prettier-plugin-packagejson": "2.5.
|
|
131
|
-
"prettier-plugin-sql": "0.19.
|
|
130
|
+
"prettier-plugin-packagejson": "2.5.18",
|
|
131
|
+
"prettier-plugin-sql": "0.19.2",
|
|
132
132
|
"strip-ansi": "7.1.0"
|
|
133
133
|
},
|
|
134
134
|
"packageManager": "npm@11.3.0",
|
|
@@ -68,6 +68,7 @@ export const startDevServer = async ({
|
|
|
68
68
|
http2 = false,
|
|
69
69
|
logLevel = EXECUTED_BY_TEST_PLAN ? "warn" : "info",
|
|
70
70
|
serverLogLevel = "warn",
|
|
71
|
+
serverRouterLogLevel = "warn",
|
|
71
72
|
services = [],
|
|
72
73
|
|
|
73
74
|
signal = new AbortController().signal,
|
|
@@ -676,6 +677,7 @@ export const startDevServer = async ({
|
|
|
676
677
|
stopOnInternalError: false,
|
|
677
678
|
keepProcessAlive,
|
|
678
679
|
logLevel: serverLogLevel,
|
|
680
|
+
routerLogLevel: serverRouterLogLevel,
|
|
679
681
|
startLog: false,
|
|
680
682
|
|
|
681
683
|
https,
|
package/src/kitchen/kitchen.js
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
defineNonEnumerableProperties,
|
|
13
13
|
} from "./errors.js";
|
|
14
14
|
import { assertFetchedContentCompliance } from "./fetched_content_compliance.js";
|
|
15
|
+
import { FILE_AND_SERVER_URLS_CONVERTER } from "./file_and_server_urls_converter.js";
|
|
15
16
|
import {
|
|
16
17
|
determineFileUrlForOutDirectory,
|
|
17
18
|
determineSourcemapFileUrl,
|
|
@@ -107,6 +108,10 @@ export const createKitchen = ({
|
|
|
107
108
|
isSupportedOnCurrentClients: memoizeIsSupported(clientRuntimeCompat),
|
|
108
109
|
isSupportedOnFutureClients: memoizeIsSupported(runtimeCompat),
|
|
109
110
|
isPlaceholderInjection,
|
|
111
|
+
asServerUrl: (fileUrl) =>
|
|
112
|
+
FILE_AND_SERVER_URLS_CONVERTER.asServerUrl(fileUrl, rootDirectoryUrl),
|
|
113
|
+
asFileUrl: (serverUrl) =>
|
|
114
|
+
FILE_AND_SERVER_URLS_CONVERTER.asFileUrl(serverUrl, rootDirectoryUrl),
|
|
110
115
|
INJECTIONS,
|
|
111
116
|
getPluginMeta: null,
|
|
112
117
|
sourcemaps,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const initDropToOpen = ({ rootDirectoryUrl }) => {
|
|
2
|
+
const dataTransferCandidates = [
|
|
3
|
+
(dataTransfer) => {
|
|
4
|
+
if (!dataTransfer.types.includes("resourceurls")) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
return () => {
|
|
8
|
+
const data = dataTransfer.getData("resourceurls");
|
|
9
|
+
const urls = JSON.parse(data);
|
|
10
|
+
if (!Array.isArray(urls) || urls.length === 0) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const [url] = urls;
|
|
14
|
+
const fileUrl = new URL(url).href;
|
|
15
|
+
let serverUrl;
|
|
16
|
+
|
|
17
|
+
if (fileUrl.startsWith(rootDirectoryUrl)) {
|
|
18
|
+
const serverRelativeUrl = fileUrl.slice(rootDirectoryUrl.length);
|
|
19
|
+
serverUrl = `/${serverRelativeUrl}`;
|
|
20
|
+
} else {
|
|
21
|
+
serverUrl = `/@fs/${fileUrl}`;
|
|
22
|
+
}
|
|
23
|
+
window.location.href = serverUrl;
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
document.addEventListener("dragover", (event) => {
|
|
29
|
+
for (const candidate of dataTransferCandidates) {
|
|
30
|
+
const dataTransferHandler = candidate(event.dataTransfer);
|
|
31
|
+
if (dataTransferHandler) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
document.addEventListener("drop", (event) => {
|
|
38
|
+
let handler;
|
|
39
|
+
for (const candidate of dataTransferCandidates) {
|
|
40
|
+
const dataTransferHandler = candidate(event.dataTransfer);
|
|
41
|
+
if (dataTransferHandler) {
|
|
42
|
+
handler = dataTransferHandler;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
handler();
|
|
48
|
+
});
|
|
49
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML page server by jsenv dev server will listen for drop events
|
|
3
|
+
* and redirect the browser to the dropped file location.
|
|
4
|
+
*
|
|
5
|
+
* Works only for VSCode right now (because it sets "resourceurls" dataTransfer type).
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { injectJsenvScript, parseHtml, stringifyHtmlAst } from "@jsenv/ast";
|
|
10
|
+
|
|
11
|
+
export const jsenvPluginDropToOpen = () => {
|
|
12
|
+
const clientFileUrl = import.meta.resolve("./client/drop_to_open.js");
|
|
13
|
+
return {
|
|
14
|
+
name: "jsenv:drop_to_open",
|
|
15
|
+
appliesDuring: "dev",
|
|
16
|
+
transformUrlContent: {
|
|
17
|
+
html: (urlInfo) => {
|
|
18
|
+
const htmlAst = parseHtml({
|
|
19
|
+
html: urlInfo.content,
|
|
20
|
+
url: urlInfo.url,
|
|
21
|
+
});
|
|
22
|
+
const clientFileReference = urlInfo.dependencies.inject({
|
|
23
|
+
type: "script",
|
|
24
|
+
subtype: "js_module",
|
|
25
|
+
expectedType: "js_module",
|
|
26
|
+
specifier: clientFileUrl,
|
|
27
|
+
});
|
|
28
|
+
injectJsenvScript(htmlAst, {
|
|
29
|
+
type: "module",
|
|
30
|
+
src: clientFileReference.generatedSpecifier,
|
|
31
|
+
initCall: {
|
|
32
|
+
callee: "initDropToOpen",
|
|
33
|
+
params: {
|
|
34
|
+
rootDirectoryUrl: urlInfo.context.rootDirectoryUrl,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
pluginName: "jsenv:drop_to_open",
|
|
38
|
+
});
|
|
39
|
+
return stringifyHtmlAst(htmlAst);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
export const installImportMetaCss = (importMeta) => {
|
|
2
2
|
let cssText = "";
|
|
3
|
-
let stylesheet = new CSSStyleSheet();
|
|
3
|
+
let stylesheet = new CSSStyleSheet({ baseUrl: importMeta.url });
|
|
4
4
|
let adopted = false;
|
|
5
5
|
|
|
6
6
|
const css = {
|
|
7
7
|
toString: () => cssText,
|
|
8
8
|
update: (value) => {
|
|
9
9
|
cssText = value;
|
|
10
|
+
cssText += `
|
|
11
|
+
/* sourceURL=${importMeta.url} */
|
|
12
|
+
/* inlined from ${importMeta.url} */`;
|
|
10
13
|
stylesheet.replaceSync(cssText);
|
|
11
14
|
},
|
|
12
15
|
inject: () => {
|
package/src/plugins/plugins.js
CHANGED
|
@@ -23,6 +23,7 @@ import { jsenvPluginAutoreload } from "./autoreload/jsenv_plugin_autoreload.js";
|
|
|
23
23
|
import { jsenvPluginCacheControl } from "./cache_control/jsenv_plugin_cache_control.js";
|
|
24
24
|
// other
|
|
25
25
|
import { jsenvPluginRibbon } from "./ribbon/jsenv_plugin_ribbon.js";
|
|
26
|
+
import { jsenvPluginDropToOpen } from "./drop_to_open/jsenv_plugin_drop_to_open.js";
|
|
26
27
|
import { jsenvPluginCleanHTML } from "./clean_html/jsenv_plugin_clean_html.js";
|
|
27
28
|
import { jsenvPluginChromeDevtoolsJson } from "./chrome_devtools_json/jsenv_plugin_chrome_devtools_json.js";
|
|
28
29
|
import { jsenvPluginAutoreloadOnServerRestart } from "./autoreload_on_server_restart/jsenv_plugin_autoreload_on_server_restart.js";
|
|
@@ -146,6 +147,7 @@ export const getCorePlugins = ({
|
|
|
146
147
|
: []),
|
|
147
148
|
...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []),
|
|
148
149
|
...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
|
|
150
|
+
jsenvPluginDropToOpen(),
|
|
149
151
|
jsenvPluginCleanHTML(),
|
|
150
152
|
jsenvPluginChromeDevtoolsJson(),
|
|
151
153
|
...(packageSideEffects
|
|
@@ -101,9 +101,11 @@ a.nav_item_text {
|
|
|
101
101
|
margin: 10px 15px 10px 15px;
|
|
102
102
|
list-style-type: none;
|
|
103
103
|
border-radius: 3px;
|
|
104
|
+
display: flex;
|
|
105
|
+
flex-direction: column;
|
|
104
106
|
}
|
|
105
107
|
.directory_content_item {
|
|
106
|
-
display: flex;
|
|
108
|
+
display: inline-flex;
|
|
107
109
|
position: relative;
|
|
108
110
|
padding: 10px 15px 10px 15px;
|
|
109
111
|
font-size: 15px;
|
|
@@ -112,7 +114,9 @@ a.nav_item_text {
|
|
|
112
114
|
align-items: center;
|
|
113
115
|
}
|
|
114
116
|
.directory_content_item_link {
|
|
115
|
-
display: flex;
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
min-width: 0;
|
|
119
|
+
max-width: 100%;
|
|
116
120
|
flex: 1;
|
|
117
121
|
gap: 10px;
|
|
118
122
|
align-items: center;
|
|
@@ -123,12 +127,15 @@ a.nav_item_text {
|
|
|
123
127
|
aspect-ratio: 1/1;
|
|
124
128
|
display: flex;
|
|
125
129
|
color: #f1f1f1;
|
|
130
|
+
flex-shrink: 0;
|
|
126
131
|
}
|
|
127
132
|
.directory_content_item_icon img {
|
|
128
133
|
width: 100%;
|
|
129
134
|
}
|
|
130
135
|
.directory_content_item_text {
|
|
131
|
-
display: flex;
|
|
136
|
+
display: inline-flex;
|
|
137
|
+
flex-grow: 1;
|
|
138
|
+
align-items: center;
|
|
132
139
|
}
|
|
133
140
|
.directory_content_item:last-child {
|
|
134
141
|
border-bottom: none;
|
|
@@ -63,11 +63,13 @@ const ErrorMessage = () => {
|
|
|
63
63
|
errorText = (
|
|
64
64
|
<>
|
|
65
65
|
<strong>File not found:</strong>
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
<Overflow>
|
|
67
|
+
<code>
|
|
68
|
+
<span className="file_path_good">{filePathExisting}</span>
|
|
69
|
+
<span className="file_path_bad">{filePathNotFound}</span>
|
|
70
|
+
</code>{" "}
|
|
71
|
+
does not exist on the server.
|
|
72
|
+
</Overflow>
|
|
71
73
|
</>
|
|
72
74
|
);
|
|
73
75
|
errorSuggestion = (
|
|
@@ -90,6 +92,19 @@ const ErrorMessage = () => {
|
|
|
90
92
|
);
|
|
91
93
|
};
|
|
92
94
|
|
|
95
|
+
const Overflow = ({ children, afterContent }) => {
|
|
96
|
+
return (
|
|
97
|
+
<div style="display: flex; flex-wrap: wrap; overflow: hidden; width: 100%; box-sizing: border-box; white-space: nowrap; text-overflow: ellipsis;">
|
|
98
|
+
<div style="display: flex; flex-grow: 1; width: 0;">
|
|
99
|
+
<div style="overflow: hidden; max-width: 100%; text-overflow: ellipsis;">
|
|
100
|
+
{children}
|
|
101
|
+
</div>
|
|
102
|
+
{afterContent}
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
93
108
|
const Breadcrumb = ({ items }) => {
|
|
94
109
|
return (
|
|
95
110
|
<h1 className="nav">
|
|
@@ -170,7 +185,7 @@ const DirectoryContent = ({ items }) => {
|
|
|
170
185
|
isDirectory={directoryItem.url.endsWith("/")}
|
|
171
186
|
isMainFile={directoryItem.isMainFile}
|
|
172
187
|
>
|
|
173
|
-
{directoryItem.urlRelativeToCurrentDirectory}
|
|
188
|
+
{decodeURI(directoryItem.urlRelativeToCurrentDirectory)}
|
|
174
189
|
</DirectoryContentItem>
|
|
175
190
|
);
|
|
176
191
|
})}
|
|
@@ -201,15 +216,17 @@ const DirectoryContentItem = ({ url, isDirectory, isMainFile, children }) => {
|
|
|
201
216
|
}
|
|
202
217
|
/>
|
|
203
218
|
</span>
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
<span className="directory_content_item_text">
|
|
220
|
+
<Overflow>{children}</Overflow>
|
|
221
|
+
{isDirectory ? (
|
|
222
|
+
<>
|
|
223
|
+
<span style="flex:1"></span>
|
|
224
|
+
<span className="directory_content_item_arrow">
|
|
225
|
+
<RightArrowSvg />
|
|
226
|
+
</span>
|
|
227
|
+
</>
|
|
228
|
+
) : null}
|
|
229
|
+
</span>
|
|
213
230
|
</a>
|
|
214
231
|
</li>
|
|
215
232
|
);
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
} from "@jsenv/urls";
|
|
38
38
|
import { existsSync, lstatSync, readdirSync } from "node:fs";
|
|
39
39
|
import { getDirectoryWatchPatterns } from "../../helpers/watch_source_files.js";
|
|
40
|
-
import { FILE_AND_SERVER_URLS_CONVERTER } from "
|
|
40
|
+
import { FILE_AND_SERVER_URLS_CONVERTER } from "../../kitchen/file_and_server_urls_converter.js";
|
|
41
41
|
|
|
42
42
|
const htmlFileUrlForDirectory = import.meta.resolve(
|
|
43
43
|
"./client/directory_listing.html",
|
|
@@ -2,7 +2,7 @@ import { readEntryStatSync } from "@jsenv/filesystem";
|
|
|
2
2
|
import { ensurePathnameTrailingSlash } from "@jsenv/urls";
|
|
3
3
|
import { CONTENT_TYPE } from "@jsenv/utils/src/content_type/content_type.js";
|
|
4
4
|
import { readFileSync, readdirSync } from "node:fs";
|
|
5
|
-
import { FILE_AND_SERVER_URLS_CONVERTER } from "
|
|
5
|
+
import { FILE_AND_SERVER_URLS_CONVERTER } from "../../kitchen/file_and_server_urls_converter.js";
|
|
6
6
|
import { jsenvPluginDirectoryListing } from "./jsenv_plugin_directory_listing.js";
|
|
7
7
|
import { jsenvPluginFsRedirection } from "./jsenv_plugin_fs_redirection.js";
|
|
8
8
|
|
|
File without changes
|