@staticbolt/core 1.0.0-beta.11 → 1.0.0-beta.12

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.
@@ -1,18 +1,18 @@
1
- import { A as isHtmlMetadata, B as DependencyTracker, C as PrintFormattedError, D as filterScriptMetadata, E as traverse, F as isSvgMetadata, I as isTextAssetMetadata, L as isWebManifestMetadata, M as isPackageMetadata, N as isScriptMetadata, O as filterStyleMetadata, P as isStyleMetadata, R as isScriptType, S as valueOrError, T as generator, _ as mergeMaps, b as safeReadFileSync, c as downloadContent, d as hashContent, f as humanReadableBytes, h as isURL, j as isMarkdownMetadata, k as isBinaryAssetMetadata, l as escapeHtml, n as bytesToKB, s as cloneObject, w as printFmtError, z as METADATA_TYPES } from "../utilities-CZmLMi93.mjs";
2
- import { _ as CUSTOM_ATTRIBUTES, a as extname, c as join, d as parse$2, g as CONFIG_FILE_NAME, h as resolve, i as dirname, l as matchPath, m as replaceExtension, n as createLog, o as isAbsolute, p as relative, r as basename, s as isSubpath, t as Log, u as normalize } from "../logger-BfIn1ytK.mjs";
1
+ import { A as isStyleMetadata, C as filterScriptMetadata, D as isMarkdownMetadata, E as isHtmlMetadata, F as METADATA_TYPES, H as isValidRelativePath, I as Resolver, L as readJsonFile, M as isTextAssetMetadata, N as isWebManifestMetadata, O as isPackageMetadata, P as isScriptType, S as traverse, T as isBinaryAssetMetadata, U as splitHtmlLink, V as valueOrError, W as DependencyTracker, _ as mergeMaps, b as printFmtError, c as downloadContent, d as hashContent, f as humanReadableBytes, h as isURL, j as isSvgMetadata, k as isScriptMetadata, l as escapeHtml, n as bytesToKB, s as cloneObject, w as filterStyleMetadata, x as generator, y as PrintFormattedError, z as safeReadFileSync } from "../utilities-Bu5rdDC9.mjs";
2
+ import { _ as resolve, a as basename, c as isAbsolute, d as matchPath, f as normalize, g as replaceExtension, h as relative, i as createLog, l as isSubpath, n as CUSTOM_ATTRIBUTES, o as dirname, p as parse$2, r as Log, s as extname, t as CONFIG_FILE_NAME, u as join } from "../common-Bkh8-tjA.mjs";
3
3
  import { createRequire } from "node:module";
4
+ import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
4
5
  import nodePath from "node:path";
5
- import { HTMLElement, NodeType, parse } from "@staticbolt/node-html-parser";
6
6
  import c from "chalk";
7
+ import json5 from "json5";
8
+ import { HTMLElement, NodeType, parse } from "@staticbolt/node-html-parser";
7
9
  import postcss from "postcss";
8
10
  import { common, createEmphasize } from "emphasize";
9
- import { copyFileSync, cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
10
11
  import { globSync } from "glob";
11
12
  import { minify_sync } from "terser";
12
13
  import * as esbuild from "esbuild";
13
14
  import * as t from "@babel/types";
14
15
  import sharp from "sharp";
15
- import json5 from "json5";
16
16
  import { generateSW } from "workbox-build";
17
17
  import { optimize } from "svgo";
18
18
  import postcssrc from "postcss-load-config";
@@ -47,46 +47,10 @@ import Fastify from "fastify";
47
47
  import { WebSocketServer } from "ws";
48
48
  import browserslistFn from "browserslist";
49
49
  import chokidar from "chokidar";
50
- import { ResolverFactory } from "oxc-resolver";
51
50
  import ttf2woff2 from "ttf2woff2";
52
51
  import * as z from "zod";
53
52
  import * as fontKit from "fontkit";
54
53
 
55
- //#region src/utilities/html-links.ts
56
- /**
57
- * Checks if the link is an HTML link (not a file link)
58
- *
59
- * @param source - The link
60
- * @returns
61
- */
62
- function isHtmlLink(source) {
63
- return /^(?:#|https?|mailto:|tel:|url\(|ftp:|data:|javascript:)/i.test(source);
64
- }
65
- function isValidRelativePath(source) {
66
- if (!source) return false;
67
- if (isAbsolute(source)) return false;
68
- if (isHtmlLink(source)) return false;
69
- return true;
70
- }
71
- function splitHtmlLink(url) {
72
- const qIndex = url.indexOf("?");
73
- const hIndex = url.indexOf("#");
74
- let delimIndex = -1;
75
- if (qIndex !== -1 && hIndex !== -1) delimIndex = Math.min(qIndex, hIndex);
76
- else if (qIndex !== -1) delimIndex = qIndex;
77
- else if (hIndex !== -1) delimIndex = hIndex;
78
- if (delimIndex !== -1) {
79
- const pathEnd = url[delimIndex - 1] === "/" ? delimIndex - 1 : delimIndex;
80
- return [url.slice(0, pathEnd), url.slice(pathEnd)];
81
- }
82
- if (url.endsWith("/")) {
83
- if (url === "/" || url === "./") return [url, ""];
84
- return [url.slice(0, -1), "/"];
85
- }
86
- return [url, ""];
87
- }
88
-
89
- //#endregion
90
54
  //#region src/helpers/find-deps.ts
91
55
  var DepsFinder = class {
92
56
  #depsMap = /* @__PURE__ */ new Map();
@@ -1583,20 +1547,6 @@ async function loadPrettier(filePath) {
1583
1547
  }
1584
1548
  }
1585
1549
 
1586
- //#endregion
1587
- //#region src/utilities/read-json-file.ts
1588
- /** Read a file and parse it as JSON safely. */
1589
- function readJsonFile(path, code) {
1590
- if (!code) {
1591
- const [fileString, readError] = safeReadFileSync(path, "utf8");
1592
- if (readError) return [null, readError];
1593
- code = fileString;
1594
- }
1595
- const [parsed, parseError] = valueOrError(json5.parse)(code);
1596
- if (parseError !== null) return [null, parseError];
1597
- return [parsed, null];
1598
- }
1599
-
1600
1550
  //#endregion
1601
1551
  //#region src/plugins/i18n/get-locales.ts
1602
1552
  function getLocals(options) {
@@ -3067,6 +3017,28 @@ function htmlBuildTimeScript(options = {}) {
3067
3017
  }
3068
3018
  for (const node of metadata.ast.querySelectorAll(query)) node.remove();
3069
3019
  }
3020
+ },
3021
+ lspHtmlData() {
3022
+ return {
3023
+ version: 1.1,
3024
+ tags: [{
3025
+ name: "script",
3026
+ attributes: [
3027
+ {
3028
+ name: buildAttribute,
3029
+ description: "This attribute is used to mark the script as build-time script."
3030
+ },
3031
+ {
3032
+ name: fullDomAttribute,
3033
+ description: "Opt into a full DOM context using `jsdom`. When not present, the lighter `@staticbolt/node-html-parser` is used instead."
3034
+ },
3035
+ {
3036
+ name: contextAttribute,
3037
+ description: "Pass global context object as JSON to be available in the script during execution."
3038
+ }
3039
+ ]
3040
+ }]
3041
+ };
3070
3042
  }
3071
3043
  };
3072
3044
  }
@@ -3326,6 +3298,32 @@ function htmlBundleScriptPlugin(options = {}) {
3326
3298
  node.textContent = "";
3327
3299
  this.addMetadata(newScriptMetadata);
3328
3300
  }
3301
+ },
3302
+ lspHtmlData() {
3303
+ return {
3304
+ version: 1.1,
3305
+ tags: [{
3306
+ name: "script",
3307
+ attributes: [
3308
+ {
3309
+ name: bundleAttribute,
3310
+ description: "Enable script bundling."
3311
+ },
3312
+ {
3313
+ name: bundleOutAttribute,
3314
+ description: "Specify the output path for bundled scripts relative to the output directory.\nIf the script has a `src` attribute, the output path will default to `{filename}.bundle.js`.\nIf the script has no `src` attribute, the default behavior is to keep the script inline."
3315
+ },
3316
+ {
3317
+ name: externalsAttribute,
3318
+ description: `Glob patterns list to treat as external during bundling. (semicolon-separated)\n\nDefaults to "${defaultExternal.join(";")}".`
3319
+ },
3320
+ {
3321
+ name: externalsExcludeAttribute,
3322
+ description: `Glob patterns that exempt files from being treated as external, even if they match \`externals\`. (semicolon-separated)\n\nDefaults to "${defaultExternalExclude.join(";")}".`
3323
+ }
3324
+ ]
3325
+ }]
3326
+ };
3329
3327
  }
3330
3328
  };
3331
3329
  }
@@ -3395,6 +3393,24 @@ function htmlBundleStylePlugin(options = {}) {
3395
3393
  continue;
3396
3394
  }
3397
3395
  }
3396
+ },
3397
+ lspHtmlData() {
3398
+ return {
3399
+ version: 1.1,
3400
+ tags: [{
3401
+ name: "link",
3402
+ attributes: [{
3403
+ name: bundleAttribute,
3404
+ description: "Enable style bundling."
3405
+ }]
3406
+ }, {
3407
+ name: "style",
3408
+ attributes: [{
3409
+ name: bundleAttribute,
3410
+ description: "Enable style bundling."
3411
+ }]
3412
+ }]
3413
+ };
3398
3414
  }
3399
3415
  };
3400
3416
  }
@@ -3409,6 +3425,16 @@ function htmlFragmentPlugin(options = {}) {
3409
3425
  if (!isHtmlMetadata(metadata)) return;
3410
3426
  const elements = metadata.ast.querySelectorAll(tag);
3411
3427
  for (const node of elements) node.replaceWith(node.innerHTML.trim());
3428
+ },
3429
+ lspHtmlData() {
3430
+ return {
3431
+ version: 1.1,
3432
+ tags: [{
3433
+ name: tag,
3434
+ description: "At build time, this tag is replaced with its contents.",
3435
+ attributes: []
3436
+ }]
3437
+ };
3412
3438
  }
3413
3439
  };
3414
3440
  }
@@ -3504,6 +3530,18 @@ function htmlIifeScriptPlugin(options = {}) {
3504
3530
  continue;
3505
3531
  }
3506
3532
  }
3533
+ },
3534
+ lspHtmlData() {
3535
+ return {
3536
+ version: 1.1,
3537
+ tags: [{
3538
+ name: "script",
3539
+ attributes: [{
3540
+ name: iifeAttribute,
3541
+ description: "Enabling this will wrap the script content in an IIFE (Immediately Invoked Function Expression).\n\nWorks only with inline global scripts."
3542
+ }]
3543
+ }]
3544
+ };
3507
3545
  }
3508
3546
  };
3509
3547
  }
@@ -3550,6 +3588,18 @@ function htmlInlineScriptPlugin(options = {}) {
3550
3588
  metadata.scriptsMetadataList.set(metadataID, scriptMetadataClone);
3551
3589
  scriptTag.removeAttribute("src");
3552
3590
  }
3591
+ },
3592
+ lspHtmlData() {
3593
+ return {
3594
+ version: 1.1,
3595
+ tags: [{
3596
+ name: "script",
3597
+ attributes: [{
3598
+ name: inlineAttribute,
3599
+ description: "Enable inlining external scripts directly into the HTML at build time. It supports local files, remote URLs."
3600
+ }]
3601
+ }]
3602
+ };
3553
3603
  }
3554
3604
  };
3555
3605
  }
@@ -3615,6 +3665,18 @@ function htmlInlineStylePlugin(options = {}) {
3615
3665
  const attributesString = Object.entries(linkTag.attrs).map(([name, value]) => `${name}="${value}"`).join(" ");
3616
3666
  linkTag.replaceWith(`<style ${attributesString}></style>`);
3617
3667
  }
3668
+ },
3669
+ lspHtmlData() {
3670
+ return {
3671
+ version: 1.1,
3672
+ tags: [{
3673
+ name: "link",
3674
+ attributes: [{
3675
+ name: inlineAttribute,
3676
+ description: "Enable inlining external stylesheets directly into the HTML at build time. It supports both local files and remote URLs."
3677
+ }]
3678
+ }]
3679
+ };
3618
3680
  }
3619
3681
  };
3620
3682
  }
@@ -3689,6 +3751,18 @@ function HtmlInlineSvgPlugin(options = {}) {
3689
3751
  for (const [attribute, value] of Object.entries(node.attrs)) svgElement.setAttribute(attribute, value);
3690
3752
  node.replaceWith(svgElement);
3691
3753
  }
3754
+ },
3755
+ lspHtmlData() {
3756
+ return {
3757
+ version: 1.1,
3758
+ tags: [{
3759
+ name: "svg",
3760
+ attributes: [{
3761
+ name: inlineAttribute,
3762
+ description: "Enable inlining external SVGs directly into the HTML at build time. It supports both local files and remote URLs."
3763
+ }]
3764
+ }]
3765
+ };
3692
3766
  }
3693
3767
  };
3694
3768
  }
@@ -3787,6 +3861,22 @@ function htmlInlineTextPlugin(options = {}) {
3787
3861
  const importers = deps.getImporters(id);
3788
3862
  for (const importer of importers) compileSet.add(importer);
3789
3863
  }
3864
+ },
3865
+ lspHtmlData() {
3866
+ return {
3867
+ version: 1.1,
3868
+ tags: [{
3869
+ name: tag,
3870
+ description: "At build time, this tag is replaced with the contents of the external text file.",
3871
+ attributes: [{
3872
+ name: sourceAttribute,
3873
+ description: "The path to the external text file."
3874
+ }, {
3875
+ name: noEscapeAttribute,
3876
+ description: "Disable HTML escaping."
3877
+ }]
3878
+ }]
3879
+ };
3790
3880
  }
3791
3881
  };
3792
3882
  }
@@ -3845,6 +3935,35 @@ function htmlInsertPlugin(options = {}) {
3845
3935
  filePath: metadata.id
3846
3936
  });
3847
3937
  }
3938
+ },
3939
+ lspHtmlData() {
3940
+ return {
3941
+ version: 1.1,
3942
+ tags: [{
3943
+ name: tag,
3944
+ description: "At build time, inject HTML content into any target element on the page using a CSS selector at build time.",
3945
+ attributes: [
3946
+ {
3947
+ name: selectorAttribute,
3948
+ description: "The CSS selector of the target element."
3949
+ },
3950
+ {
3951
+ name: replaceAttribute,
3952
+ description: "Replace the target element with the contents of the custom insert element."
3953
+ },
3954
+ {
3955
+ name: whereAttribute,
3956
+ description: "The position of the inserted element.",
3957
+ values: [
3958
+ { name: "beforebegin" },
3959
+ { name: "afterbegin" },
3960
+ { name: "beforeend" },
3961
+ { name: "afterend" }
3962
+ ]
3963
+ }
3964
+ ]
3965
+ }]
3966
+ };
3848
3967
  }
3849
3968
  };
3850
3969
  }
@@ -3892,14 +4011,14 @@ function executeExpression$1(expressionString, data) {
3892
4011
  //#endregion
3893
4012
  //#region src/plugins/html-layout/html-layout-plugin.ts
3894
4013
  function htmlLayoutPlugin(options = {}) {
3895
- const tags = options.tags ?? ["layout", "part"];
4014
+ const layoutTags = options.tags ?? ["layout", "part"];
3896
4015
  const sourceAttribute = options.layoutSourceAttribute ?? "src";
3897
4016
  const dataSourceAttribute = options.dataSourceAttribute ?? "dataSource";
3898
4017
  const dataJsonAttribute = options.dataJsonAttribute ?? "dataJson";
3899
4018
  const alwaysIncludeAttribute = options.alwaysIncludeAttribute ?? "always-include";
3900
4019
  const addAttributeAttribute = options.addAttributeAttribute ?? "add-attr";
3901
4020
  const removeAttributeAttribute = options.removeAttributeAttribute ?? "remove-attr";
3902
- const query = tags.join(",");
4021
+ const query = layoutTags.join(",");
3903
4022
  const printFmtError = PrintFormattedError.create({ function: htmlLayoutPlugin });
3904
4023
  const htmlLayoutMetadataCache = [];
3905
4024
  /**
@@ -3909,12 +4028,12 @@ function htmlLayoutPlugin(options = {}) {
3909
4028
  const dataSourceCache = /* @__PURE__ */ new Map();
3910
4029
  function isLayoutPath(path) {
3911
4030
  const fileName = basename(path);
3912
- return tags.some((tag) => fileName.endsWith(`.${tag}.html`));
4031
+ return layoutTags.some((tag) => fileName.endsWith(`.${tag}.html`));
3913
4032
  }
3914
4033
  return {
3915
4034
  name: "html-layout",
3916
4035
  load(content, relativePath, { type }) {
3917
- if (type && !tags.includes(type)) return;
4036
+ if (type && !layoutTags.includes(type)) return;
3918
4037
  if (!isLayoutPath(relativePath)) return;
3919
4038
  const textAssetMetadata = {
3920
4039
  type: METADATA_TYPES.TextAsset,
@@ -3953,7 +4072,7 @@ function htmlLayoutPlugin(options = {}) {
3953
4072
  }
3954
4073
  if (isMarkdownMetadata(metadata)) for (const [key, source] of Object.entries(metadata.ast.frontmatter)) {
3955
4074
  if (!source) continue;
3956
- if (tags.includes(key) || key === dataSourceAttribute) sources.push({
4075
+ if (layoutTags.includes(key) || key === dataSourceAttribute) sources.push({
3957
4076
  get source() {
3958
4077
  return source;
3959
4078
  },
@@ -4178,7 +4297,7 @@ function htmlLayoutPlugin(options = {}) {
4178
4297
  return;
4179
4298
  }
4180
4299
  if (isMarkdownMetadata(metadata)) {
4181
- const tag = Object.keys(metadata.ast.frontmatter).find((key) => tags.includes(key));
4300
+ const tag = Object.keys(metadata.ast.frontmatter).find((key) => layoutTags.includes(key));
4182
4301
  if (!tag) return;
4183
4302
  let attributesString = "";
4184
4303
  for (const [key, value] of Object.entries(metadata.ast.frontmatter)) attributesString += `${key === tag ? sourceAttribute : key}="${value}" `;
@@ -4190,6 +4309,56 @@ function htmlLayoutPlugin(options = {}) {
4190
4309
  };
4191
4310
  return;
4192
4311
  }
4312
+ },
4313
+ lspHtmlData() {
4314
+ const attributes = [
4315
+ {
4316
+ name: sourceAttribute,
4317
+ description: "The path to the layout to use."
4318
+ },
4319
+ {
4320
+ name: dataSourceAttribute,
4321
+ description: "The path for a JSON file containing data for the layout."
4322
+ },
4323
+ {
4324
+ name: dataJsonAttribute,
4325
+ description: "The layout data in JSON format."
4326
+ }
4327
+ ];
4328
+ const alwaysInclude = {
4329
+ name: alwaysIncludeAttribute,
4330
+ description: "When using a layout more than once on the same page. Always include this script/style/link[rel='stylesheet'] even if it is already present."
4331
+ };
4332
+ const tags = [
4333
+ {
4334
+ name: "script",
4335
+ attributes: [alwaysInclude]
4336
+ },
4337
+ {
4338
+ name: "link",
4339
+ attributes: [alwaysInclude]
4340
+ },
4341
+ {
4342
+ name: "style",
4343
+ attributes: [alwaysInclude]
4344
+ }
4345
+ ];
4346
+ for (const tag of layoutTags) tags.push({
4347
+ name: tag,
4348
+ description: `This tag allows inlining a \`${tag}\` file.`,
4349
+ attributes
4350
+ });
4351
+ return {
4352
+ version: 1.1,
4353
+ tags,
4354
+ globalAttributes: [{
4355
+ name: addAttributeAttribute,
4356
+ description: "Inside a layout file only.Prefix for conditionally adding boolean attributes.Append the target attribute name as a suffix — `add-attr-open`, `add-attr-disabled`, etc. The value is a JS expression evaluated after placeholder resolution; if it is non-empty and not `\"false\"`, the named attribute is added to the element. Multiple `add-attr-*` attributes can appear on the same element."
4357
+ }, {
4358
+ name: removeAttributeAttribute,
4359
+ description: "Inside a layout file only.Prefix for conditionally removing boolean attributes.Append the target attribute name as a suffix — `remove-attr-open`, `remove-attr-disabled`, etc. The value is a JS expression evaluated after placeholder resolution; if it is non-empty and not `\"false\"`, the named attribute is removed from the element. Multiple `remove-attr-*` attributes can appear on the same element."
4360
+ }]
4361
+ };
4193
4362
  }
4194
4363
  };
4195
4364
  }
@@ -4257,7 +4426,22 @@ function htmlMarkdownPlugin(options = {}) {
4257
4426
  });
4258
4427
  continue;
4259
4428
  }
4260
- node.innerHTML = await markdownMetadata.ast.render();
4429
+ const asHtmlString = await markdownMetadata.ast.render();
4430
+ const htmlMetadata = await this.load(metadata.filePath, {
4431
+ code: asHtmlString,
4432
+ type: "html"
4433
+ });
4434
+ if (!isHtmlMetadata(htmlMetadata)) {
4435
+ printFmtError("Invalid HTML file:", metadata.filePath, {
4436
+ node,
4437
+ filePath: metadata.id
4438
+ });
4439
+ continue;
4440
+ }
4441
+ const metadataList = await this.resolveAndLoad(htmlMetadata);
4442
+ this.addMetadata(metadataList.slice(1));
4443
+ await this.transformAndSync(metadataList);
4444
+ node.set_content(htmlMetadata.ast.children);
4261
4445
  }
4262
4446
  const currentSources = /* @__PURE__ */ new Set();
4263
4447
  const markdowns = metadata.ast.querySelectorAll(markdownTag);
@@ -4281,8 +4465,23 @@ function htmlMarkdownPlugin(options = {}) {
4281
4465
  continue;
4282
4466
  }
4283
4467
  currentSources.add(sourceRelative);
4284
- const content = await markdownMetadata.ast.render();
4285
- node.replaceWith(content);
4468
+ const asHtmlString = await markdownMetadata.ast.render();
4469
+ const htmlMetadata = await this.load(sourceRelative, {
4470
+ code: asHtmlString,
4471
+ type: "html"
4472
+ });
4473
+ if (!isHtmlMetadata(htmlMetadata)) {
4474
+ printFmtError("Invalid HTML file:", sourceRelative, {
4475
+ node,
4476
+ filePath: metadata.id
4477
+ });
4478
+ continue;
4479
+ }
4480
+ const metadataList = await this.resolveAndLoad(htmlMetadata);
4481
+ this.addMetadata(metadataList.slice(1));
4482
+ await this.transformAndSync(metadataList);
4483
+ await this.rebase(htmlMetadata, join(this.root, metadata.filePath));
4484
+ node.replaceWith(...htmlMetadata.ast.children);
4286
4485
  }
4287
4486
  deps.update(metadata.id, currentSources);
4288
4487
  },
@@ -4295,6 +4494,23 @@ function htmlMarkdownPlugin(options = {}) {
4295
4494
  const importers = deps.getImporters(id);
4296
4495
  for (const importer of importers) compileSet.add(importer);
4297
4496
  }
4497
+ },
4498
+ lspHtmlData() {
4499
+ return {
4500
+ version: 1.1,
4501
+ globalAttributes: [{
4502
+ name: mdAttribute,
4503
+ description: "Render the contents of this element as markdown."
4504
+ }],
4505
+ tags: [{
4506
+ name: markdownTag,
4507
+ description: "This tag lets you render Markdown files inside HTML.",
4508
+ attributes: [{
4509
+ name: sourceAttribute,
4510
+ description: "The path to the external markdown file."
4511
+ }]
4512
+ }]
4513
+ };
4298
4514
  }
4299
4515
  };
4300
4516
  }
@@ -4900,8 +5116,8 @@ function getPreloadInfo(filePath) {
4900
5116
  //#region src/plugins/html-preload/html-preload-plugin.ts
4901
5117
  function htmlPreloadPlugin(options = {}) {
4902
5118
  const preloadAttribute = options.preloadAttribute ?? "preload";
4903
- const includeAttribute = options.includeAttribute ?? "include";
4904
- const excludeAttribute = options.excludeAttribute ?? "exclude";
5119
+ const includeAttribute = options.includeAttribute ?? "preload-include";
5120
+ const excludeAttribute = options.excludeAttribute ?? "preload-exclude";
4905
5121
  const asTypes = [
4906
5122
  "script",
4907
5123
  "style",
@@ -4980,6 +5196,37 @@ function htmlPreloadPlugin(options = {}) {
4980
5196
  head.insertAdjacentHTML("beforeend", linkTags.join("\n"));
4981
5197
  }
4982
5198
  }
5199
+ },
5200
+ lspHtmlData() {
5201
+ const attributes = [
5202
+ {
5203
+ name: preloadAttribute,
5204
+ description: `Enable preloading.
5205
+ Automatically generates \`<link rel="preload">\` tags for the dependencies of your scripts and stylesheets.
5206
+ This tells the browser to start fetching those files early, before they are discovered through normal parsing.
5207
+
5208
+ You can narrow down the files to preload by specifying a space-separated list of dependency types, additionally you can use the \`${includeAttribute}\` and \`${excludeAttribute}\` attributes.`,
5209
+ values: asTypes.map((type) => ({ name: type }))
5210
+ },
5211
+ {
5212
+ name: includeAttribute,
5213
+ description: `Glob patterns list to include when using the \`${preloadAttribute}\` attribute. (semicolon-separated)`
5214
+ },
5215
+ {
5216
+ name: excludeAttribute,
5217
+ description: `Glob patterns list to exclude when using the \`${preloadAttribute}\` attribute. (semicolon-separated)`
5218
+ }
5219
+ ];
5220
+ return {
5221
+ version: 1.1,
5222
+ tags: [{
5223
+ name: "link",
5224
+ attributes
5225
+ }, {
5226
+ name: "script",
5227
+ attributes
5228
+ }]
5229
+ };
4983
5230
  }
4984
5231
  };
4985
5232
  }
@@ -6257,207 +6504,6 @@ function printExecutionTime(executionTime) {
6257
6504
  console.log();
6258
6505
  }
6259
6506
 
6260
- //#endregion
6261
- //#region src/resolver/get-aliases.ts
6262
- /** Gets path aliases from `tsconfig.json` */
6263
- function getPathAliases(root) {
6264
- const [tsconfig, tsconfigParseError] = readTsconfig(root);
6265
- if (tsconfigParseError !== null) return [null, tsconfigParseError];
6266
- const paths = tsconfig.paths ?? {};
6267
- const alias = {};
6268
- for (const key in paths) {
6269
- const aliasName = key.replace(/\*$/, "");
6270
- alias[aliasName] = paths[key][0].replace(/\*$/, "");
6271
- }
6272
- return [alias, null];
6273
- }
6274
- function readTsconfig(root) {
6275
- const [tsconfig, tsconfigParseError] = readJsonFile(join(root, "tsconfig.json"));
6276
- if (tsconfigParseError !== null) return [null, tsconfigParseError];
6277
- if (!tsconfig.compilerOptions) return [null, /* @__PURE__ */ new Error("[readTsconfig] No compilerOptions found in tsconfig.json")];
6278
- return [tsconfig.compilerOptions, null];
6279
- }
6280
-
6281
- //#endregion
6282
- //#region src/resolver/resolver.ts
6283
- const nodeModulesResolver = new ResolverFactory({
6284
- conditionNames: [
6285
- "browser",
6286
- "import",
6287
- "default"
6288
- ],
6289
- extensions: [
6290
- ".js",
6291
- ".json",
6292
- ".node",
6293
- ".css"
6294
- ],
6295
- symlinks: false
6296
- });
6297
- var Resolver = class Resolver {
6298
- root;
6299
- aliases = {};
6300
- notFound = /* @__PURE__ */ new Set();
6301
- files = /* @__PURE__ */ new Set();
6302
- directories = /* @__PURE__ */ new Set();
6303
- static JS_EXTENSIONS = new Set([
6304
- ".js",
6305
- ".mjs",
6306
- ".cjs",
6307
- ".jsx",
6308
- ".ts",
6309
- ".mts",
6310
- ".cts",
6311
- ".tsx"
6312
- ]);
6313
- static HTML_EXTENSIONS = new Set([".html", ".md"]);
6314
- constructor(root) {
6315
- this.root = root;
6316
- const [aliases] = getPathAliases(root);
6317
- if (aliases) this.aliases = aliases;
6318
- }
6319
- resolve(sourceOrLink, filePath) {
6320
- if (!isValidRelativePath(sourceOrLink)) return;
6321
- const absFilePath = isAbsolute(filePath) ? filePath : join(this.root, filePath);
6322
- const [source, suffix] = splitHtmlLink(sourceOrLink);
6323
- if (isAbsolute(source)) return;
6324
- const checkDirectory = suffix === "/";
6325
- const absSource = join(dirname(absFilePath), source);
6326
- const foundFile = this.findFile(absSource, checkDirectory);
6327
- if (foundFile) return {
6328
- path: foundFile,
6329
- exists: true,
6330
- suffix
6331
- };
6332
- const sourceForAlias = suffix === "/" ? source + "/" : source;
6333
- const resolvedPathAlias = Resolver.resolvePathAlias(sourceForAlias, this.aliases);
6334
- if (resolvedPathAlias) {
6335
- const absSource = join(this.root, resolvedPathAlias);
6336
- const foundFile = this.findFile(absSource, checkDirectory);
6337
- const isFileAlias = sourceForAlias in this.aliases && !sourceForAlias.endsWith("/");
6338
- if (!foundFile && !this.notFound.has(absSource.replace(/\/$/, ""))) {
6339
- this.notFound.add(absSource.replace(/\/$/, ""));
6340
- Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" was resolved to "${resolvedPathAlias}", but the file is missing.`);
6341
- }
6342
- return {
6343
- path: foundFile ?? absSource,
6344
- exists: !!foundFile,
6345
- suffix,
6346
- isFileAlias,
6347
- isDirAlias: !isFileAlias
6348
- };
6349
- }
6350
- if (!source.startsWith(".")) {
6351
- const resolverResult = nodeModulesResolver.sync(this.root, source);
6352
- if (resolverResult.path) return {
6353
- path: resolverResult.path,
6354
- suffix,
6355
- exists: true,
6356
- isPackage: true
6357
- };
6358
- }
6359
- if (source.startsWith("./") || source.startsWith("../")) {
6360
- if (!this.notFound.has(absSource)) {
6361
- this.notFound.add(absSource);
6362
- Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" points to a non-existent file.`);
6363
- }
6364
- return {
6365
- path: absSource,
6366
- suffix,
6367
- exists: false
6368
- };
6369
- }
6370
- }
6371
- resolveAlias(source) {
6372
- return Resolver.resolvePathAlias(source, this.aliases);
6373
- }
6374
- normalize(filePath) {
6375
- return normalize(filePath);
6376
- }
6377
- static isFile(filePath) {
6378
- try {
6379
- return statSync(filePath).isFile();
6380
- } catch (error) {
6381
- const code = error.code;
6382
- if (code === "ENOENT" || code === "ENOTDIR") return false;
6383
- throw error;
6384
- }
6385
- }
6386
- /** Aliased path to path */
6387
- static resolvePathAlias(filePath, aliases) {
6388
- for (const [key, value] of Object.entries(aliases)) {
6389
- if (key.endsWith("/")) {
6390
- if (!filePath.startsWith(key)) continue;
6391
- return filePath.replace(key, value);
6392
- }
6393
- if (filePath === key) return value;
6394
- }
6395
- }
6396
- /** Path to aliased path */
6397
- static resolveAliasPath(filePath, aliases) {
6398
- let shortest;
6399
- for (const [key, value] of Object.entries(aliases)) {
6400
- if (key.endsWith("/")) {
6401
- if (!filePath.startsWith(value)) continue;
6402
- const aliased = filePath.replace(value, key);
6403
- if (!shortest || aliased.length < shortest.length) shortest = aliased;
6404
- continue;
6405
- }
6406
- if (filePath === value && (!shortest || key.length < shortest.length)) shortest = key;
6407
- }
6408
- return shortest ?? filePath;
6409
- }
6410
- /** Path to aliased path */
6411
- aliasPath(filePath) {
6412
- return Resolver.resolveAliasPath(filePath, this.aliases);
6413
- }
6414
- findFile(filePath, checkDirectory = false) {
6415
- if (this.files.has(filePath)) return filePath;
6416
- if (Resolver.isFile(filePath)) {
6417
- this.files.add(filePath);
6418
- return filePath;
6419
- }
6420
- const extension = extname(filePath);
6421
- if (!extension) {
6422
- for (const candidateExtension of [...Resolver.JS_EXTENSIONS, ...Resolver.HTML_EXTENSIONS]) {
6423
- const candidate = replaceExtension(filePath, candidateExtension);
6424
- if (this.files.has(candidate)) return candidate;
6425
- if (Resolver.isFile(candidate)) {
6426
- this.files.add(candidate);
6427
- return candidate;
6428
- }
6429
- }
6430
- const withIndex = join(filePath, "index");
6431
- for (const candidateExtension of Resolver.HTML_EXTENSIONS) {
6432
- const candidate = replaceExtension(withIndex, candidateExtension);
6433
- if (this.files.has(candidate)) return candidate;
6434
- if (Resolver.isFile(candidate)) {
6435
- this.files.add(candidate);
6436
- return candidate;
6437
- }
6438
- }
6439
- if (checkDirectory) {
6440
- if (this.directories.has(filePath)) return filePath;
6441
- if (existsSync(filePath)) {
6442
- this.directories.add(filePath);
6443
- return filePath;
6444
- }
6445
- }
6446
- return;
6447
- }
6448
- if (Resolver.JS_EXTENSIONS.has(extension)) {
6449
- for (const jsExtension of Resolver.JS_EXTENSIONS) {
6450
- const candidate = replaceExtension(filePath, jsExtension);
6451
- if (Resolver.isFile(candidate)) {
6452
- this.files.add(candidate);
6453
- return candidate;
6454
- }
6455
- }
6456
- return;
6457
- }
6458
- }
6459
- };
6460
-
6461
6507
  //#endregion
6462
6508
  //#region src/main.ts
6463
6509
  var App = class {