@jsenv/core 40.8.4 → 40.9.1
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/browserslist_index/browserslist_index.js +43 -18
- 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 +42 -20
- package/dist/client/directory_listing/jsenv_core_node_modules.js +4 -4
- 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 +21 -21
- 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
|
@@ -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
|