@jsenv/core 39.3.2 → 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.
@@ -15032,6 +15032,8 @@ const jsenvPluginDirectoryReferenceEffect = (
15032
15032
  actionForDirectory = "copy";
15033
15033
  } else if (reference.type === "filesystem") {
15034
15034
  actionForDirectory = "copy";
15035
+ } else if (reference.type === "http_request") {
15036
+ actionForDirectory = "preserve";
15035
15037
  } else if (typeof directoryReferenceEffect === "string") {
15036
15038
  actionForDirectory = directoryReferenceEffect;
15037
15039
  } else if (typeof directoryReferenceEffect === "function") {
@@ -15049,7 +15051,9 @@ const jsenvPluginDirectoryReferenceEffect = (
15049
15051
  throw error;
15050
15052
  }
15051
15053
  if (actionForDirectory === "preserve") {
15052
- return `ignore:${reference.specifier}`;
15054
+ return reference.ownerUrlInfo.context.dev
15055
+ ? null
15056
+ : `ignore:${reference.specifier}`;
15053
15057
  }
15054
15058
  return null;
15055
15059
  },
@@ -17485,10 +17489,6 @@ const applyPackageSpecifierResolution = (specifier, resolutionContext) => {
17485
17489
  return browserFieldResolution;
17486
17490
  }
17487
17491
  const packageResolution = applyPackageResolve(specifier, resolutionContext);
17488
- const search = new URL(specifier, "file:///").search;
17489
- if (search) {
17490
- packageResolution.url = `${packageResolution.url}${search}`;
17491
- }
17492
17492
  return packageResolution;
17493
17493
  }
17494
17494
  };
@@ -18408,6 +18408,11 @@ const jsenvPluginNodeEsmResolution = (resolutionConfig = {}) => {
18408
18408
  }
18409
18409
  },
18410
18410
  resolveReference: (reference) => {
18411
+ if (reference.specifier.startsWith("node_esm:")) {
18412
+ reference.specifier = reference.specifier.slice("node_esm:".length);
18413
+ const result = nodeEsmResolverDefault(reference);
18414
+ return result;
18415
+ }
18411
18416
  const urlType = urlTypeFromReference(reference);
18412
18417
  const resolver = resolvers[urlType];
18413
18418
  return resolver ? resolver(reference) : null;
@@ -18434,7 +18439,6 @@ const urlTypeFromReference = (reference) => {
18434
18439
  if (reference.injected) {
18435
18440
  return reference.expectedType;
18436
18441
  }
18437
-
18438
18442
  return reference.ownerUrlInfo.type;
18439
18443
  };
18440
18444
 
@@ -18600,15 +18604,14 @@ const resolveSymlink = (fileUrl) => {
18600
18604
  return realUrlObject.href;
18601
18605
  };
18602
18606
 
18603
- const html404AndParentDirIsEmptyFileUrl = new URL(
18604
- "./html/html_404_and_parent_dir_is_empty.html",
18605
- import.meta.url,
18606
- );
18607
18607
  const html404AndParentDirFileUrl = new URL(
18608
18608
  "./html/html_404_and_parent_dir.html",
18609
18609
  import.meta.url,
18610
18610
  );
18611
- const htmlFileUrlForDirectory = new URL("./html/directory.html", import.meta.url);
18611
+ const htmlFileUrlForDirectory = new URL(
18612
+ "./html/directory.html",
18613
+ import.meta.url,
18614
+ );
18612
18615
 
18613
18616
  const jsenvPluginProtocolFile = ({
18614
18617
  magicExtensions,
@@ -18685,12 +18688,14 @@ const jsenvPluginProtocolFile = ({
18685
18688
  ? pickContentType(urlInfo.context.request, ["text/html"])
18686
18689
  : false;
18687
18690
  if (acceptsHtml) {
18691
+ firstReference.expectedType = "html";
18688
18692
  const html = generateHtmlForDirectory(
18689
18693
  urlObject.href,
18690
18694
  directoryContentArray,
18691
18695
  urlInfo.context.rootDirectoryUrl,
18692
18696
  );
18693
18697
  return {
18698
+ type: "html",
18694
18699
  contentType: "text/html",
18695
18700
  content: html,
18696
18701
  };
@@ -18731,6 +18736,9 @@ const jsenvPluginProtocolFile = ({
18731
18736
  return {
18732
18737
  contentType: "text/html",
18733
18738
  content: html,
18739
+ headers: {
18740
+ "cache-control": "no-cache",
18741
+ },
18734
18742
  };
18735
18743
  }
18736
18744
  }
@@ -18754,10 +18762,13 @@ const generateHtmlForDirectory = (
18754
18762
  rootDirectoryUrl,
18755
18763
  ) => {
18756
18764
  directoryUrl = assertAndNormalizeDirectoryUrl(directoryUrl);
18765
+
18757
18766
  const htmlForDirectory = String(readFileSync(htmlFileUrlForDirectory));
18767
+ const directoryRelativeUrl = urlToRelativeUrl(directoryUrl, rootDirectoryUrl);
18758
18768
  const replacers = {
18759
- directoryRelativeUrl: urlToRelativeUrl(directoryUrl, rootDirectoryUrl),
18760
18769
  directoryUrl,
18770
+ directoryNav: () =>
18771
+ generateDirectoryNav(directoryRelativeUrl, rootDirectoryUrl),
18761
18772
  directoryContent: () =>
18762
18773
  generateDirectoryContent(
18763
18774
  directoryContentArray,
@@ -18774,30 +18785,21 @@ const generateHtmlForENOENTOnHtmlFile = (
18774
18785
  parentDirectoryUrl,
18775
18786
  rootDirectoryUrl,
18776
18787
  ) => {
18777
- if (parentDirectoryContentArray.length === 0) {
18778
- const htmlFor404AndParentDirIsEmpty = String(
18779
- readFileSync(html404AndParentDirIsEmptyFileUrl),
18780
- );
18781
- return replacePlaceholders$1(htmlFor404AndParentDirIsEmpty, {
18782
- fileRelativeUrl: urlToRelativeUrl(url, rootDirectoryUrl),
18783
- parentDirectoryRelativeUrl: urlToRelativeUrl(
18784
- parentDirectoryUrl,
18785
- rootDirectoryUrl,
18786
- ),
18787
- });
18788
- }
18789
18788
  const htmlFor404AndParentDir = String(
18790
18789
  readFileSync(html404AndParentDirFileUrl),
18791
18790
  );
18792
-
18791
+ const fileRelativeUrl = urlToRelativeUrl(url, rootDirectoryUrl);
18792
+ const parentDirectoryRelativeUrl = urlToRelativeUrl(
18793
+ parentDirectoryUrl,
18794
+ rootDirectoryUrl,
18795
+ );
18793
18796
  const replacers = {
18794
18797
  fileUrl: url,
18795
- fileRelativeUrl: urlToRelativeUrl(url, rootDirectoryUrl),
18798
+ fileRelativeUrl,
18796
18799
  parentDirectoryUrl,
18797
- parentDirectoryRelativeUrl: urlToRelativeUrl(
18798
- parentDirectoryUrl,
18799
- rootDirectoryUrl,
18800
- ),
18800
+ parentDirectoryRelativeUrl,
18801
+ parentDirectoryNav: () =>
18802
+ generateDirectoryNav(parentDirectoryRelativeUrl, rootDirectoryUrl),
18801
18803
  parentDirectoryContent: () =>
18802
18804
  generateDirectoryContent(
18803
18805
  parentDirectoryContentArray,
@@ -18808,11 +18810,51 @@ const generateHtmlForENOENTOnHtmlFile = (
18808
18810
  const html = replacePlaceholders$1(htmlFor404AndParentDir, replacers);
18809
18811
  return html;
18810
18812
  };
18813
+ const generateDirectoryNav = (relativeUrl, rootDirectoryUrl) => {
18814
+ const rootDirectoryUrlName = urlToFilename$1(rootDirectoryUrl);
18815
+ const relativeUrlWithRoot = relativeUrl
18816
+ ? `${rootDirectoryUrlName}/${relativeUrl}`
18817
+ : `${rootDirectoryUrlName}/`;
18818
+ const isDir = relativeUrlWithRoot.endsWith("/");
18819
+ const parts = isDir
18820
+ ? relativeUrlWithRoot.slice(0, -1).split("/")
18821
+ : relativeUrlWithRoot.split("/");
18822
+ let dirPartsHtml = "";
18823
+ let i = 0;
18824
+ while (i < parts.length) {
18825
+ const part = parts[i];
18826
+ const href = i === 0 ? "/" : `/${parts.slice(1, i + 1).join("/")}/`;
18827
+ const text = part;
18828
+ const isLastPart = i === parts.length - 1;
18829
+ if (isLastPart) {
18830
+ dirPartsHtml += `
18831
+ <span class="directory_nav_item" data-current>
18832
+ ${text}
18833
+ </span>`;
18834
+ break;
18835
+ }
18836
+ dirPartsHtml += `
18837
+ <a class="directory_nav_item" href="${href}">
18838
+ ${text}
18839
+ </a>`;
18840
+ dirPartsHtml += `
18841
+ <span class="directory_separator">/</span>`;
18842
+ i++;
18843
+ }
18844
+ if (isDir) {
18845
+ dirPartsHtml += `
18846
+ <span class="directory_separator">/</span>`;
18847
+ }
18848
+ return dirPartsHtml;
18849
+ };
18811
18850
  const generateDirectoryContent = (
18812
18851
  directoryContentArray,
18813
18852
  directoryUrl,
18814
18853
  rootDirectoryUrl,
18815
18854
  ) => {
18855
+ if (directoryContentArray.length === 0) {
18856
+ return `<p>Directory is empty</p>`;
18857
+ }
18816
18858
  const sortedNames = [];
18817
18859
  for (const filename of directoryContentArray) {
18818
18860
  const fileUrlObject = new URL(filename, directoryUrl);
@@ -18823,15 +18865,20 @@ const generateDirectoryContent = (
18823
18865
  }
18824
18866
  }
18825
18867
  sortedNames.sort(comparePathnames);
18826
- return sortedNames.map((filename) => {
18868
+ let html = `<ul class="directory_content">`;
18869
+ for (const filename of sortedNames) {
18827
18870
  const fileUrlObject = new URL(filename, directoryUrl);
18828
18871
  const fileUrl = String(fileUrlObject);
18829
- let fileUrlRelative = urlToRelativeUrl(fileUrl, rootDirectoryUrl);
18830
- return `<li>
18831
- <a href="/${fileUrlRelative}">/${fileUrlRelative}</a>
18832
- </li>`;
18833
- }).join(`
18834
- `);
18872
+ const fileUrlRelativeToParent = urlToRelativeUrl(fileUrl, directoryUrl);
18873
+ const fileUrlRelativeToRoot = urlToRelativeUrl(fileUrl, rootDirectoryUrl);
18874
+ const type = fileUrlRelativeToParent.endsWith("/") ? "dir" : "file";
18875
+ html += `
18876
+ <li class="directory_child" data-type="${type}">
18877
+ <a href="/${fileUrlRelativeToRoot}">${fileUrlRelativeToParent}</a>
18878
+ </li>`;
18879
+ }
18880
+ html += `\n </ul>`;
18881
+ return html;
18835
18882
  };
18836
18883
  const replacePlaceholders$1 = (html, replacers) => {
18837
18884
  return html.replace(/\$\{(\w+)\}/g, (match, name) => {
@@ -20646,9 +20693,14 @@ const createBuildSpecifierManager = ({
20646
20693
 
20647
20694
  let buildSpecifier;
20648
20695
  if (base === "./") {
20649
- const parentBuildUrl = reference.ownerUrlInfo.isRoot
20696
+ const { ownerUrlInfo } = reference;
20697
+ const parentBuildUrl = ownerUrlInfo.isRoot
20650
20698
  ? buildDirectoryUrl
20651
- : urlInfoToBuildUrlMap.get(reference.ownerUrlInfo);
20699
+ : urlInfoToBuildUrlMap.get(
20700
+ ownerUrlInfo.isInline
20701
+ ? ownerUrlInfo.findParentIfInline()
20702
+ : ownerUrlInfo,
20703
+ );
20652
20704
  const urlRelativeToParent = urlToRelativeUrl(buildUrl, parentBuildUrl);
20653
20705
  if (urlRelativeToParent[0] === ".") {
20654
20706
  buildSpecifier = urlRelativeToParent;
@@ -21975,7 +22027,7 @@ const build = async ({
21975
22027
  process.env.CAPTURING_SIDE_EFFECTS ||
21976
22028
  urlIsInsideOf(sourceDirectoryUrl, jsenvCoreDirectoryUrl)
21977
22029
  ) {
21978
- outDirectoryUrl = new URL("../.jsenv/", sourceDirectoryUrl);
22030
+ outDirectoryUrl = new URL("../.jsenv_b/", sourceDirectoryUrl);
21979
22031
  } else {
21980
22032
  const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
21981
22033
  if (packageDirectoryUrl) {
@@ -22291,9 +22343,23 @@ build ${entryPointKeys.length} entry points`);
22291
22343
  addToBundlerIfAny(rawUrlInfo);
22292
22344
  }
22293
22345
  if (rawUrlInfo.type === "html") {
22294
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
22346
+ for (const referenceToOther of rawUrlInfo.referenceToOthersSet) {
22347
+ if (
22348
+ referenceToOther.isResourceHint &&
22349
+ referenceToOther.expectedType === "js_module"
22350
+ ) {
22351
+ const referencedUrlInfo = referenceToOther.urlInfo;
22352
+ if (
22353
+ referencedUrlInfo &&
22354
+ // something else than the resource hint is using this url
22355
+ referencedUrlInfo.referenceFromOthersSet.size > 0
22356
+ ) {
22357
+ addToBundlerIfAny(referencedUrlInfo);
22358
+ continue;
22359
+ }
22360
+ }
22295
22361
  if (referenceToOther.isWeak) {
22296
- return;
22362
+ continue;
22297
22363
  }
22298
22364
  const referencedUrlInfo = referenceToOther.urlInfo;
22299
22365
  if (referencedUrlInfo.isInline) {
@@ -22309,50 +22375,38 @@ build ${entryPointKeys.length} entry points`);
22309
22375
  );
22310
22376
  }
22311
22377
  // inline content cannot be bundled
22312
- return;
22378
+ continue;
22313
22379
  }
22314
22380
  addToBundlerIfAny(referencedUrlInfo);
22315
- });
22316
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
22317
- if (
22318
- referenceToOther.isResourceHint &&
22319
- referenceToOther.expectedType === "js_module"
22320
- ) {
22321
- const referencedUrlInfo = referenceToOther.urlInfo;
22322
- if (
22323
- referencedUrlInfo &&
22324
- // something else than the resource hint is using this url
22325
- referencedUrlInfo.referenceFromOthersSet.size > 0
22326
- ) {
22327
- addToBundlerIfAny(referencedUrlInfo);
22328
- }
22329
- }
22330
- });
22381
+ }
22331
22382
  return;
22332
22383
  }
22333
22384
  // File referenced with new URL('./file.js', import.meta.url)
22334
22385
  // are entry points that should be bundled
22335
22386
  // For instance we will bundle service worker/workers detected like this
22336
22387
  if (rawUrlInfo.type === "js_module") {
22337
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
22388
+ for (const referenceToOther of rawUrlInfo.referenceToOthersSet) {
22338
22389
  if (referenceToOther.type === "js_url") {
22339
22390
  const referencedUrlInfo = referenceToOther.urlInfo;
22391
+ let isAlreadyBundled = false;
22340
22392
  for (const referenceFromOther of referencedUrlInfo.referenceFromOthersSet) {
22341
22393
  if (referenceFromOther.url === referencedUrlInfo.url) {
22342
22394
  if (
22343
22395
  referenceFromOther.subtype === "import_dynamic" ||
22344
22396
  referenceFromOther.type === "script"
22345
22397
  ) {
22346
- // will already be bundled
22347
- return;
22398
+ isAlreadyBundled = true;
22399
+ break;
22348
22400
  }
22349
22401
  }
22350
22402
  }
22351
- addToBundlerIfAny(referencedUrlInfo);
22352
- return;
22403
+ if (!isAlreadyBundled) {
22404
+ addToBundlerIfAny(referencedUrlInfo);
22405
+ }
22406
+ continue;
22353
22407
  }
22354
22408
  if (referenceToOther.type === "js_inline_content") ;
22355
- });
22409
+ }
22356
22410
  }
22357
22411
  },
22358
22412
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "39.3.2",
3
+ "version": "39.3.4",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -74,10 +74,10 @@
74
74
  "@jsenv/importmap": "1.2.1",
75
75
  "@jsenv/integrity": "0.0.2",
76
76
  "@jsenv/js-module-fallback": "1.3.37",
77
- "@jsenv/node-esm-resolution": "1.0.2",
77
+ "@jsenv/node-esm-resolution": "1.0.3",
78
78
  "@jsenv/plugin-bundling": "2.7.7",
79
79
  "@jsenv/plugin-minification": "1.5.5",
80
- "@jsenv/plugin-supervisor": "1.5.17",
80
+ "@jsenv/plugin-supervisor": "1.5.18",
81
81
  "@jsenv/plugin-transpilation": "1.4.21",
82
82
  "@jsenv/runtime-compat": "1.3.1",
83
83
  "@jsenv/server": "15.2.19",
@@ -154,7 +154,7 @@ export const build = async ({
154
154
  process.env.CAPTURING_SIDE_EFFECTS ||
155
155
  urlIsInsideOf(sourceDirectoryUrl, jsenvCoreDirectoryUrl)
156
156
  ) {
157
- outDirectoryUrl = new URL("../.jsenv/", sourceDirectoryUrl);
157
+ outDirectoryUrl = new URL("../.jsenv_b/", sourceDirectoryUrl);
158
158
  } else {
159
159
  const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
160
160
  if (packageDirectoryUrl) {
@@ -470,9 +470,23 @@ build ${entryPointKeys.length} entry points`);
470
470
  addToBundlerIfAny(rawUrlInfo);
471
471
  }
472
472
  if (rawUrlInfo.type === "html") {
473
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
473
+ for (const referenceToOther of rawUrlInfo.referenceToOthersSet) {
474
+ if (
475
+ referenceToOther.isResourceHint &&
476
+ referenceToOther.expectedType === "js_module"
477
+ ) {
478
+ const referencedUrlInfo = referenceToOther.urlInfo;
479
+ if (
480
+ referencedUrlInfo &&
481
+ // something else than the resource hint is using this url
482
+ referencedUrlInfo.referenceFromOthersSet.size > 0
483
+ ) {
484
+ addToBundlerIfAny(referencedUrlInfo);
485
+ continue;
486
+ }
487
+ }
474
488
  if (referenceToOther.isWeak) {
475
- return;
489
+ continue;
476
490
  }
477
491
  const referencedUrlInfo = referenceToOther.urlInfo;
478
492
  if (referencedUrlInfo.isInline) {
@@ -488,52 +502,40 @@ build ${entryPointKeys.length} entry points`);
488
502
  );
489
503
  }
490
504
  // inline content cannot be bundled
491
- return;
505
+ continue;
492
506
  }
493
507
  addToBundlerIfAny(referencedUrlInfo);
494
- });
495
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
496
- if (
497
- referenceToOther.isResourceHint &&
498
- referenceToOther.expectedType === "js_module"
499
- ) {
500
- const referencedUrlInfo = referenceToOther.urlInfo;
501
- if (
502
- referencedUrlInfo &&
503
- // something else than the resource hint is using this url
504
- referencedUrlInfo.referenceFromOthersSet.size > 0
505
- ) {
506
- addToBundlerIfAny(referencedUrlInfo);
507
- }
508
- }
509
- });
508
+ }
510
509
  return;
511
510
  }
512
511
  // File referenced with new URL('./file.js', import.meta.url)
513
512
  // are entry points that should be bundled
514
513
  // For instance we will bundle service worker/workers detected like this
515
514
  if (rawUrlInfo.type === "js_module") {
516
- rawUrlInfo.referenceToOthersSet.forEach((referenceToOther) => {
515
+ for (const referenceToOther of rawUrlInfo.referenceToOthersSet) {
517
516
  if (referenceToOther.type === "js_url") {
518
517
  const referencedUrlInfo = referenceToOther.urlInfo;
518
+ let isAlreadyBundled = false;
519
519
  for (const referenceFromOther of referencedUrlInfo.referenceFromOthersSet) {
520
520
  if (referenceFromOther.url === referencedUrlInfo.url) {
521
521
  if (
522
522
  referenceFromOther.subtype === "import_dynamic" ||
523
523
  referenceFromOther.type === "script"
524
524
  ) {
525
- // will already be bundled
526
- return;
525
+ isAlreadyBundled = true;
526
+ break;
527
527
  }
528
528
  }
529
529
  }
530
- addToBundlerIfAny(referencedUrlInfo);
531
- return;
530
+ if (!isAlreadyBundled) {
531
+ addToBundlerIfAny(referencedUrlInfo);
532
+ }
533
+ continue;
532
534
  }
533
535
  if (referenceToOther.type === "js_inline_content") {
534
536
  // we should bundle it too right?
535
537
  }
536
- });
538
+ }
537
539
  }
538
540
  },
539
541
  );
@@ -87,9 +87,14 @@ export const createBuildSpecifierManager = ({
87
87
 
88
88
  let buildSpecifier;
89
89
  if (base === "./") {
90
- const parentBuildUrl = reference.ownerUrlInfo.isRoot
90
+ const { ownerUrlInfo } = reference;
91
+ const parentBuildUrl = ownerUrlInfo.isRoot
91
92
  ? buildDirectoryUrl
92
- : urlInfoToBuildUrlMap.get(reference.ownerUrlInfo);
93
+ : urlInfoToBuildUrlMap.get(
94
+ ownerUrlInfo.isInline
95
+ ? ownerUrlInfo.findParentIfInline()
96
+ : ownerUrlInfo,
97
+ );
93
98
  const urlRelativeToParent = urlToRelativeUrl(buildUrl, parentBuildUrl);
94
99
  if (urlRelativeToParent[0] === ".") {
95
100
  buildSpecifier = urlRelativeToParent;
@@ -38,6 +38,8 @@ export const jsenvPluginDirectoryReferenceEffect = (
38
38
  actionForDirectory = "copy";
39
39
  } else if (reference.type === "filesystem") {
40
40
  actionForDirectory = "copy";
41
+ } else if (reference.type === "http_request") {
42
+ actionForDirectory = "preserve";
41
43
  } else if (typeof directoryReferenceEffect === "string") {
42
44
  actionForDirectory = directoryReferenceEffect;
43
45
  } else if (typeof directoryReferenceEffect === "function") {
@@ -55,7 +57,9 @@ export const jsenvPluginDirectoryReferenceEffect = (
55
57
  throw error;
56
58
  }
57
59
  if (actionForDirectory === "preserve") {
58
- return `ignore:${reference.specifier}`;
60
+ return reference.ownerUrlInfo.context.dev
61
+ ? null
62
+ : `ignore:${reference.specifier}`;
59
63
  }
60
64
  return null;
61
65
  },
@@ -0,0 +1,133 @@
1
+ html,
2
+ body,
3
+ h1,
4
+ div,
5
+ p,
6
+ ul,
7
+ li,
8
+ a,
9
+ p,
10
+ button {
11
+ margin: 0;
12
+ padding: 0;
13
+ border: 0;
14
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
15
+ -webkit-font-smoothing: antialiased;
16
+ -moz-osx-font-smoothing: grayscale;
17
+ }
18
+ .directory_nav {
19
+ font-size: 16px;
20
+ font-weight: bold;
21
+ margin: 20px 25px 15px 25px;
22
+ display: flex;
23
+ }
24
+ .directory_nav_item {
25
+ text-decoration: none;
26
+ position: relative;
27
+ }
28
+ .directory_separator {
29
+ margin: 0 0.3em;
30
+ }
31
+ .directory_separator:first-child {
32
+ margin-left: 0;
33
+ }
34
+ .directory_content {
35
+ margin: 10px 15px 10px 15px;
36
+ list-style-type: none;
37
+ border-radius: 3px;
38
+ }
39
+ .directory_child {
40
+ position: relative;
41
+ padding: 10px 15px 10px 15px;
42
+ background-size: 16px 16px;
43
+ background-position: 15px center;
44
+ background-repeat: no-repeat;
45
+ text-indent: 30px;
46
+ font-size: 15px;
47
+ min-height: 19px;
48
+ box-sizing: border-box;
49
+ }
50
+ .directory_child::after {
51
+ position: absolute;
52
+ content: " ";
53
+ display: block;
54
+ bottom: 0;
55
+ left: 15px;
56
+ right: 0;
57
+ }
58
+ .directory_child:last-child {
59
+ border-bottom: none;
60
+ padding-bottom: 10px;
61
+ }
62
+ .directory_child:last-child::after {
63
+ content: none;
64
+ }
65
+ .directory_child[data-type="file"] {
66
+ background-image: url("./file.png?inline");
67
+ }
68
+ .directory_child[data-type="dir"] {
69
+ background-image: url("./dir.png?inline");
70
+ }
71
+ .directory_child[data-type="dir"]::before {
72
+ content: " ";
73
+ position: absolute;
74
+ display: block;
75
+ width: 5px;
76
+ height: 5px;
77
+ border-top-right-radius: 1px;
78
+ transform: rotate(45deg);
79
+ right: 15px;
80
+ top: 16px;
81
+ }
82
+ .directory_child a {
83
+ text-decoration: none;
84
+ display: block;
85
+ }
86
+
87
+ body[data-theme="dark"] {
88
+ background: #121212;
89
+ }
90
+ body[data-theme="light"] {
91
+ background: #f1f1f1;
92
+ }
93
+ body[data-theme="dark"] .directory_nav_item {
94
+ color: #999999;
95
+ }
96
+ body[data-theme="dark"] .directory_nav_item[data-current] {
97
+ color: #f1f1f1;
98
+ }
99
+ body[data-theme="light"] .directory_nav_item {
100
+ color: #000000;
101
+ }
102
+ body[data-theme="dark"] .directory_separator {
103
+ color: #666666;
104
+ }
105
+ body[data-theme="light"] .directory_separator {
106
+ color: #999999;
107
+ }
108
+ body[data-theme="dark"] .directory_content {
109
+ background: #1e1e1e;
110
+ }
111
+ body[data-theme="light"] .directory_content {
112
+ background: #fefefe;
113
+ }
114
+ body[data-theme="dark"] .directory_child {
115
+ border-bottom: 1px solid #121212;
116
+ }
117
+ body[data-theme="light"] .directory_child {
118
+ border-bottom: 1px solid #f1f1f1;
119
+ }
120
+ body[data-theme="dark"] .directory_child[data-type="dir"]::before {
121
+ border-top: 2px solid #666666;
122
+ border-right: 2px solid #666666;
123
+ }
124
+ body[data-theme="light"] .directory_child[data-type="file"]::before {
125
+ border-top: 2px solid #999999;
126
+ border-right: 2px solid #999999;
127
+ }
128
+ body[data-theme="dark"] .directory_child a {
129
+ color: #ffffff;
130
+ }
131
+ body[data-theme="light"] .directory_child a {
132
+ color: #000000;
133
+ }
@@ -0,0 +1,17 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Directory explorer</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
+ </head>
12
+
13
+ <body data-theme="dark">
14
+ <h1 class="directory_nav">${directoryNav}</h1>
15
+ ${directoryContent}
16
+ </body>
17
+ </html>