@staticbolt/core 1.0.0-beta.11 → 1.0.0-beta.13
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/lib/cli/index.mjs +1 -1
- package/lib/{logger-BfIn1ytK.mjs → common-Bkh8-tjA.mjs} +10 -10
- package/lib/common-Bkh8-tjA.mjs.map +1 -0
- package/lib/index.d.mts +5 -3
- package/lib/index.d.mts.map +1 -1
- package/lib/index.mjs +3 -3
- package/lib/index.mjs.map +1 -1
- package/lib/plugins/index.d.mts +2 -2
- package/lib/plugins/index.mjs +315 -268
- package/lib/plugins/index.mjs.map +1 -1
- package/lib/{utilities-CZmLMi93.mjs → utilities-Bu5rdDC9.mjs} +306 -54
- package/lib/utilities-Bu5rdDC9.mjs.map +1 -0
- package/package.json +5 -4
- package/lib/logger-BfIn1ytK.mjs.map +0 -1
- package/lib/utilities-CZmLMi93.mjs.map +0 -1
- /package/lib/{chunk-C7Uep-_p.mjs → chunk-DXywRVcq.mjs} +0 -0
package/lib/plugins/index.mjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import { _ as
|
|
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();
|
|
@@ -1170,7 +1134,8 @@ function copyAssetsPlugin(options = {}) {
|
|
|
1170
1134
|
const publicFiles = globSync("**/*", {
|
|
1171
1135
|
ignore,
|
|
1172
1136
|
nodir: true,
|
|
1173
|
-
cwd: join(this.root, publicDirectory)
|
|
1137
|
+
cwd: join(this.root, publicDirectory),
|
|
1138
|
+
dot: true
|
|
1174
1139
|
});
|
|
1175
1140
|
for (const file of publicFiles) {
|
|
1176
1141
|
const inputFile = join(this.root, publicDirectory, file);
|
|
@@ -1583,20 +1548,6 @@ async function loadPrettier(filePath) {
|
|
|
1583
1548
|
}
|
|
1584
1549
|
}
|
|
1585
1550
|
|
|
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
1551
|
//#endregion
|
|
1601
1552
|
//#region src/plugins/i18n/get-locales.ts
|
|
1602
1553
|
function getLocals(options) {
|
|
@@ -3067,6 +3018,28 @@ function htmlBuildTimeScript(options = {}) {
|
|
|
3067
3018
|
}
|
|
3068
3019
|
for (const node of metadata.ast.querySelectorAll(query)) node.remove();
|
|
3069
3020
|
}
|
|
3021
|
+
},
|
|
3022
|
+
lspHtmlData() {
|
|
3023
|
+
return {
|
|
3024
|
+
version: 1.1,
|
|
3025
|
+
tags: [{
|
|
3026
|
+
name: "script",
|
|
3027
|
+
attributes: [
|
|
3028
|
+
{
|
|
3029
|
+
name: buildAttribute,
|
|
3030
|
+
description: "This attribute is used to mark the script as build-time script."
|
|
3031
|
+
},
|
|
3032
|
+
{
|
|
3033
|
+
name: fullDomAttribute,
|
|
3034
|
+
description: "Opt into a full DOM context using `jsdom`. When not present, the lighter `@staticbolt/node-html-parser` is used instead."
|
|
3035
|
+
},
|
|
3036
|
+
{
|
|
3037
|
+
name: contextAttribute,
|
|
3038
|
+
description: "Pass global context object as JSON to be available in the script during execution."
|
|
3039
|
+
}
|
|
3040
|
+
]
|
|
3041
|
+
}]
|
|
3042
|
+
};
|
|
3070
3043
|
}
|
|
3071
3044
|
};
|
|
3072
3045
|
}
|
|
@@ -3326,6 +3299,32 @@ function htmlBundleScriptPlugin(options = {}) {
|
|
|
3326
3299
|
node.textContent = "";
|
|
3327
3300
|
this.addMetadata(newScriptMetadata);
|
|
3328
3301
|
}
|
|
3302
|
+
},
|
|
3303
|
+
lspHtmlData() {
|
|
3304
|
+
return {
|
|
3305
|
+
version: 1.1,
|
|
3306
|
+
tags: [{
|
|
3307
|
+
name: "script",
|
|
3308
|
+
attributes: [
|
|
3309
|
+
{
|
|
3310
|
+
name: bundleAttribute,
|
|
3311
|
+
description: "Enable script bundling."
|
|
3312
|
+
},
|
|
3313
|
+
{
|
|
3314
|
+
name: bundleOutAttribute,
|
|
3315
|
+
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."
|
|
3316
|
+
},
|
|
3317
|
+
{
|
|
3318
|
+
name: externalsAttribute,
|
|
3319
|
+
description: `Glob patterns list to treat as external during bundling. (semicolon-separated)\n\nDefaults to "${defaultExternal.join(";")}".`
|
|
3320
|
+
},
|
|
3321
|
+
{
|
|
3322
|
+
name: externalsExcludeAttribute,
|
|
3323
|
+
description: `Glob patterns that exempt files from being treated as external, even if they match \`externals\`. (semicolon-separated)\n\nDefaults to "${defaultExternalExclude.join(";")}".`
|
|
3324
|
+
}
|
|
3325
|
+
]
|
|
3326
|
+
}]
|
|
3327
|
+
};
|
|
3329
3328
|
}
|
|
3330
3329
|
};
|
|
3331
3330
|
}
|
|
@@ -3395,6 +3394,24 @@ function htmlBundleStylePlugin(options = {}) {
|
|
|
3395
3394
|
continue;
|
|
3396
3395
|
}
|
|
3397
3396
|
}
|
|
3397
|
+
},
|
|
3398
|
+
lspHtmlData() {
|
|
3399
|
+
return {
|
|
3400
|
+
version: 1.1,
|
|
3401
|
+
tags: [{
|
|
3402
|
+
name: "link",
|
|
3403
|
+
attributes: [{
|
|
3404
|
+
name: bundleAttribute,
|
|
3405
|
+
description: "Enable style bundling."
|
|
3406
|
+
}]
|
|
3407
|
+
}, {
|
|
3408
|
+
name: "style",
|
|
3409
|
+
attributes: [{
|
|
3410
|
+
name: bundleAttribute,
|
|
3411
|
+
description: "Enable style bundling."
|
|
3412
|
+
}]
|
|
3413
|
+
}]
|
|
3414
|
+
};
|
|
3398
3415
|
}
|
|
3399
3416
|
};
|
|
3400
3417
|
}
|
|
@@ -3409,6 +3426,16 @@ function htmlFragmentPlugin(options = {}) {
|
|
|
3409
3426
|
if (!isHtmlMetadata(metadata)) return;
|
|
3410
3427
|
const elements = metadata.ast.querySelectorAll(tag);
|
|
3411
3428
|
for (const node of elements) node.replaceWith(node.innerHTML.trim());
|
|
3429
|
+
},
|
|
3430
|
+
lspHtmlData() {
|
|
3431
|
+
return {
|
|
3432
|
+
version: 1.1,
|
|
3433
|
+
tags: [{
|
|
3434
|
+
name: tag,
|
|
3435
|
+
description: "At build time, this tag is replaced with its contents.",
|
|
3436
|
+
attributes: []
|
|
3437
|
+
}]
|
|
3438
|
+
};
|
|
3412
3439
|
}
|
|
3413
3440
|
};
|
|
3414
3441
|
}
|
|
@@ -3504,6 +3531,18 @@ function htmlIifeScriptPlugin(options = {}) {
|
|
|
3504
3531
|
continue;
|
|
3505
3532
|
}
|
|
3506
3533
|
}
|
|
3534
|
+
},
|
|
3535
|
+
lspHtmlData() {
|
|
3536
|
+
return {
|
|
3537
|
+
version: 1.1,
|
|
3538
|
+
tags: [{
|
|
3539
|
+
name: "script",
|
|
3540
|
+
attributes: [{
|
|
3541
|
+
name: iifeAttribute,
|
|
3542
|
+
description: "Enabling this will wrap the script content in an IIFE (Immediately Invoked Function Expression).\n\nWorks only with inline global scripts."
|
|
3543
|
+
}]
|
|
3544
|
+
}]
|
|
3545
|
+
};
|
|
3507
3546
|
}
|
|
3508
3547
|
};
|
|
3509
3548
|
}
|
|
@@ -3550,6 +3589,18 @@ function htmlInlineScriptPlugin(options = {}) {
|
|
|
3550
3589
|
metadata.scriptsMetadataList.set(metadataID, scriptMetadataClone);
|
|
3551
3590
|
scriptTag.removeAttribute("src");
|
|
3552
3591
|
}
|
|
3592
|
+
},
|
|
3593
|
+
lspHtmlData() {
|
|
3594
|
+
return {
|
|
3595
|
+
version: 1.1,
|
|
3596
|
+
tags: [{
|
|
3597
|
+
name: "script",
|
|
3598
|
+
attributes: [{
|
|
3599
|
+
name: inlineAttribute,
|
|
3600
|
+
description: "Enable inlining external scripts directly into the HTML at build time. It supports local files, remote URLs."
|
|
3601
|
+
}]
|
|
3602
|
+
}]
|
|
3603
|
+
};
|
|
3553
3604
|
}
|
|
3554
3605
|
};
|
|
3555
3606
|
}
|
|
@@ -3615,6 +3666,18 @@ function htmlInlineStylePlugin(options = {}) {
|
|
|
3615
3666
|
const attributesString = Object.entries(linkTag.attrs).map(([name, value]) => `${name}="${value}"`).join(" ");
|
|
3616
3667
|
linkTag.replaceWith(`<style ${attributesString}></style>`);
|
|
3617
3668
|
}
|
|
3669
|
+
},
|
|
3670
|
+
lspHtmlData() {
|
|
3671
|
+
return {
|
|
3672
|
+
version: 1.1,
|
|
3673
|
+
tags: [{
|
|
3674
|
+
name: "link",
|
|
3675
|
+
attributes: [{
|
|
3676
|
+
name: inlineAttribute,
|
|
3677
|
+
description: "Enable inlining external stylesheets directly into the HTML at build time. It supports both local files and remote URLs."
|
|
3678
|
+
}]
|
|
3679
|
+
}]
|
|
3680
|
+
};
|
|
3618
3681
|
}
|
|
3619
3682
|
};
|
|
3620
3683
|
}
|
|
@@ -3689,6 +3752,18 @@ function HtmlInlineSvgPlugin(options = {}) {
|
|
|
3689
3752
|
for (const [attribute, value] of Object.entries(node.attrs)) svgElement.setAttribute(attribute, value);
|
|
3690
3753
|
node.replaceWith(svgElement);
|
|
3691
3754
|
}
|
|
3755
|
+
},
|
|
3756
|
+
lspHtmlData() {
|
|
3757
|
+
return {
|
|
3758
|
+
version: 1.1,
|
|
3759
|
+
tags: [{
|
|
3760
|
+
name: "svg",
|
|
3761
|
+
attributes: [{
|
|
3762
|
+
name: inlineAttribute,
|
|
3763
|
+
description: "Enable inlining external SVGs directly into the HTML at build time. It supports both local files and remote URLs."
|
|
3764
|
+
}]
|
|
3765
|
+
}]
|
|
3766
|
+
};
|
|
3692
3767
|
}
|
|
3693
3768
|
};
|
|
3694
3769
|
}
|
|
@@ -3787,6 +3862,22 @@ function htmlInlineTextPlugin(options = {}) {
|
|
|
3787
3862
|
const importers = deps.getImporters(id);
|
|
3788
3863
|
for (const importer of importers) compileSet.add(importer);
|
|
3789
3864
|
}
|
|
3865
|
+
},
|
|
3866
|
+
lspHtmlData() {
|
|
3867
|
+
return {
|
|
3868
|
+
version: 1.1,
|
|
3869
|
+
tags: [{
|
|
3870
|
+
name: tag,
|
|
3871
|
+
description: "At build time, this tag is replaced with the contents of the external text file.",
|
|
3872
|
+
attributes: [{
|
|
3873
|
+
name: sourceAttribute,
|
|
3874
|
+
description: "The path to the external text file."
|
|
3875
|
+
}, {
|
|
3876
|
+
name: noEscapeAttribute,
|
|
3877
|
+
description: "Disable HTML escaping."
|
|
3878
|
+
}]
|
|
3879
|
+
}]
|
|
3880
|
+
};
|
|
3790
3881
|
}
|
|
3791
3882
|
};
|
|
3792
3883
|
}
|
|
@@ -3845,6 +3936,35 @@ function htmlInsertPlugin(options = {}) {
|
|
|
3845
3936
|
filePath: metadata.id
|
|
3846
3937
|
});
|
|
3847
3938
|
}
|
|
3939
|
+
},
|
|
3940
|
+
lspHtmlData() {
|
|
3941
|
+
return {
|
|
3942
|
+
version: 1.1,
|
|
3943
|
+
tags: [{
|
|
3944
|
+
name: tag,
|
|
3945
|
+
description: "At build time, inject HTML content into any target element on the page using a CSS selector at build time.",
|
|
3946
|
+
attributes: [
|
|
3947
|
+
{
|
|
3948
|
+
name: selectorAttribute,
|
|
3949
|
+
description: "The CSS selector of the target element."
|
|
3950
|
+
},
|
|
3951
|
+
{
|
|
3952
|
+
name: replaceAttribute,
|
|
3953
|
+
description: "Replace the target element with the contents of the custom insert element."
|
|
3954
|
+
},
|
|
3955
|
+
{
|
|
3956
|
+
name: whereAttribute,
|
|
3957
|
+
description: "The position of the inserted element.",
|
|
3958
|
+
values: [
|
|
3959
|
+
{ name: "beforebegin" },
|
|
3960
|
+
{ name: "afterbegin" },
|
|
3961
|
+
{ name: "beforeend" },
|
|
3962
|
+
{ name: "afterend" }
|
|
3963
|
+
]
|
|
3964
|
+
}
|
|
3965
|
+
]
|
|
3966
|
+
}]
|
|
3967
|
+
};
|
|
3848
3968
|
}
|
|
3849
3969
|
};
|
|
3850
3970
|
}
|
|
@@ -3892,14 +4012,14 @@ function executeExpression$1(expressionString, data) {
|
|
|
3892
4012
|
//#endregion
|
|
3893
4013
|
//#region src/plugins/html-layout/html-layout-plugin.ts
|
|
3894
4014
|
function htmlLayoutPlugin(options = {}) {
|
|
3895
|
-
const
|
|
4015
|
+
const layoutTags = options.tags ?? ["layout", "part"];
|
|
3896
4016
|
const sourceAttribute = options.layoutSourceAttribute ?? "src";
|
|
3897
4017
|
const dataSourceAttribute = options.dataSourceAttribute ?? "dataSource";
|
|
3898
4018
|
const dataJsonAttribute = options.dataJsonAttribute ?? "dataJson";
|
|
3899
4019
|
const alwaysIncludeAttribute = options.alwaysIncludeAttribute ?? "always-include";
|
|
3900
4020
|
const addAttributeAttribute = options.addAttributeAttribute ?? "add-attr";
|
|
3901
4021
|
const removeAttributeAttribute = options.removeAttributeAttribute ?? "remove-attr";
|
|
3902
|
-
const query =
|
|
4022
|
+
const query = layoutTags.join(",");
|
|
3903
4023
|
const printFmtError = PrintFormattedError.create({ function: htmlLayoutPlugin });
|
|
3904
4024
|
const htmlLayoutMetadataCache = [];
|
|
3905
4025
|
/**
|
|
@@ -3909,12 +4029,12 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
3909
4029
|
const dataSourceCache = /* @__PURE__ */ new Map();
|
|
3910
4030
|
function isLayoutPath(path) {
|
|
3911
4031
|
const fileName = basename(path);
|
|
3912
|
-
return
|
|
4032
|
+
return layoutTags.some((tag) => fileName.endsWith(`.${tag}.html`));
|
|
3913
4033
|
}
|
|
3914
4034
|
return {
|
|
3915
4035
|
name: "html-layout",
|
|
3916
4036
|
load(content, relativePath, { type }) {
|
|
3917
|
-
if (type && !
|
|
4037
|
+
if (type && !layoutTags.includes(type)) return;
|
|
3918
4038
|
if (!isLayoutPath(relativePath)) return;
|
|
3919
4039
|
const textAssetMetadata = {
|
|
3920
4040
|
type: METADATA_TYPES.TextAsset,
|
|
@@ -3953,7 +4073,7 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
3953
4073
|
}
|
|
3954
4074
|
if (isMarkdownMetadata(metadata)) for (const [key, source] of Object.entries(metadata.ast.frontmatter)) {
|
|
3955
4075
|
if (!source) continue;
|
|
3956
|
-
if (
|
|
4076
|
+
if (layoutTags.includes(key) || key === dataSourceAttribute) sources.push({
|
|
3957
4077
|
get source() {
|
|
3958
4078
|
return source;
|
|
3959
4079
|
},
|
|
@@ -4178,7 +4298,7 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
4178
4298
|
return;
|
|
4179
4299
|
}
|
|
4180
4300
|
if (isMarkdownMetadata(metadata)) {
|
|
4181
|
-
const tag = Object.keys(metadata.ast.frontmatter).find((key) =>
|
|
4301
|
+
const tag = Object.keys(metadata.ast.frontmatter).find((key) => layoutTags.includes(key));
|
|
4182
4302
|
if (!tag) return;
|
|
4183
4303
|
let attributesString = "";
|
|
4184
4304
|
for (const [key, value] of Object.entries(metadata.ast.frontmatter)) attributesString += `${key === tag ? sourceAttribute : key}="${value}" `;
|
|
@@ -4190,6 +4310,56 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
4190
4310
|
};
|
|
4191
4311
|
return;
|
|
4192
4312
|
}
|
|
4313
|
+
},
|
|
4314
|
+
lspHtmlData() {
|
|
4315
|
+
const attributes = [
|
|
4316
|
+
{
|
|
4317
|
+
name: sourceAttribute,
|
|
4318
|
+
description: "The path to the layout to use."
|
|
4319
|
+
},
|
|
4320
|
+
{
|
|
4321
|
+
name: dataSourceAttribute,
|
|
4322
|
+
description: "The path for a JSON file containing data for the layout."
|
|
4323
|
+
},
|
|
4324
|
+
{
|
|
4325
|
+
name: dataJsonAttribute,
|
|
4326
|
+
description: "The layout data in JSON format."
|
|
4327
|
+
}
|
|
4328
|
+
];
|
|
4329
|
+
const alwaysInclude = {
|
|
4330
|
+
name: alwaysIncludeAttribute,
|
|
4331
|
+
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."
|
|
4332
|
+
};
|
|
4333
|
+
const tags = [
|
|
4334
|
+
{
|
|
4335
|
+
name: "script",
|
|
4336
|
+
attributes: [alwaysInclude]
|
|
4337
|
+
},
|
|
4338
|
+
{
|
|
4339
|
+
name: "link",
|
|
4340
|
+
attributes: [alwaysInclude]
|
|
4341
|
+
},
|
|
4342
|
+
{
|
|
4343
|
+
name: "style",
|
|
4344
|
+
attributes: [alwaysInclude]
|
|
4345
|
+
}
|
|
4346
|
+
];
|
|
4347
|
+
for (const tag of layoutTags) tags.push({
|
|
4348
|
+
name: tag,
|
|
4349
|
+
description: `This tag allows inlining a \`${tag}\` file.`,
|
|
4350
|
+
attributes
|
|
4351
|
+
});
|
|
4352
|
+
return {
|
|
4353
|
+
version: 1.1,
|
|
4354
|
+
tags,
|
|
4355
|
+
globalAttributes: [{
|
|
4356
|
+
name: addAttributeAttribute,
|
|
4357
|
+
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."
|
|
4358
|
+
}, {
|
|
4359
|
+
name: removeAttributeAttribute,
|
|
4360
|
+
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."
|
|
4361
|
+
}]
|
|
4362
|
+
};
|
|
4193
4363
|
}
|
|
4194
4364
|
};
|
|
4195
4365
|
}
|
|
@@ -4257,7 +4427,22 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4257
4427
|
});
|
|
4258
4428
|
continue;
|
|
4259
4429
|
}
|
|
4260
|
-
|
|
4430
|
+
const asHtmlString = await markdownMetadata.ast.render();
|
|
4431
|
+
const htmlMetadata = await this.load(metadata.filePath, {
|
|
4432
|
+
code: asHtmlString,
|
|
4433
|
+
type: "html"
|
|
4434
|
+
});
|
|
4435
|
+
if (!isHtmlMetadata(htmlMetadata)) {
|
|
4436
|
+
printFmtError("Invalid HTML file:", metadata.filePath, {
|
|
4437
|
+
node,
|
|
4438
|
+
filePath: metadata.id
|
|
4439
|
+
});
|
|
4440
|
+
continue;
|
|
4441
|
+
}
|
|
4442
|
+
const metadataList = await this.resolveAndLoad(htmlMetadata);
|
|
4443
|
+
this.addMetadata(metadataList.slice(1));
|
|
4444
|
+
await this.transformAndSync(metadataList);
|
|
4445
|
+
node.set_content(htmlMetadata.ast.children);
|
|
4261
4446
|
}
|
|
4262
4447
|
const currentSources = /* @__PURE__ */ new Set();
|
|
4263
4448
|
const markdowns = metadata.ast.querySelectorAll(markdownTag);
|
|
@@ -4281,8 +4466,23 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4281
4466
|
continue;
|
|
4282
4467
|
}
|
|
4283
4468
|
currentSources.add(sourceRelative);
|
|
4284
|
-
const
|
|
4285
|
-
|
|
4469
|
+
const asHtmlString = await markdownMetadata.ast.render();
|
|
4470
|
+
const htmlMetadata = await this.load(sourceRelative, {
|
|
4471
|
+
code: asHtmlString,
|
|
4472
|
+
type: "html"
|
|
4473
|
+
});
|
|
4474
|
+
if (!isHtmlMetadata(htmlMetadata)) {
|
|
4475
|
+
printFmtError("Invalid HTML file:", sourceRelative, {
|
|
4476
|
+
node,
|
|
4477
|
+
filePath: metadata.id
|
|
4478
|
+
});
|
|
4479
|
+
continue;
|
|
4480
|
+
}
|
|
4481
|
+
const metadataList = await this.resolveAndLoad(htmlMetadata);
|
|
4482
|
+
this.addMetadata(metadataList.slice(1));
|
|
4483
|
+
await this.transformAndSync(metadataList);
|
|
4484
|
+
await this.rebase(htmlMetadata, join(this.root, metadata.filePath));
|
|
4485
|
+
node.replaceWith(...htmlMetadata.ast.children);
|
|
4286
4486
|
}
|
|
4287
4487
|
deps.update(metadata.id, currentSources);
|
|
4288
4488
|
},
|
|
@@ -4295,6 +4495,23 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4295
4495
|
const importers = deps.getImporters(id);
|
|
4296
4496
|
for (const importer of importers) compileSet.add(importer);
|
|
4297
4497
|
}
|
|
4498
|
+
},
|
|
4499
|
+
lspHtmlData() {
|
|
4500
|
+
return {
|
|
4501
|
+
version: 1.1,
|
|
4502
|
+
globalAttributes: [{
|
|
4503
|
+
name: mdAttribute,
|
|
4504
|
+
description: "Render the contents of this element as markdown."
|
|
4505
|
+
}],
|
|
4506
|
+
tags: [{
|
|
4507
|
+
name: markdownTag,
|
|
4508
|
+
description: "This tag lets you render Markdown files inside HTML.",
|
|
4509
|
+
attributes: [{
|
|
4510
|
+
name: sourceAttribute,
|
|
4511
|
+
description: "The path to the external markdown file."
|
|
4512
|
+
}]
|
|
4513
|
+
}]
|
|
4514
|
+
};
|
|
4298
4515
|
}
|
|
4299
4516
|
};
|
|
4300
4517
|
}
|
|
@@ -4900,8 +5117,8 @@ function getPreloadInfo(filePath) {
|
|
|
4900
5117
|
//#region src/plugins/html-preload/html-preload-plugin.ts
|
|
4901
5118
|
function htmlPreloadPlugin(options = {}) {
|
|
4902
5119
|
const preloadAttribute = options.preloadAttribute ?? "preload";
|
|
4903
|
-
const includeAttribute = options.includeAttribute ?? "include";
|
|
4904
|
-
const excludeAttribute = options.excludeAttribute ?? "exclude";
|
|
5120
|
+
const includeAttribute = options.includeAttribute ?? "preload-include";
|
|
5121
|
+
const excludeAttribute = options.excludeAttribute ?? "preload-exclude";
|
|
4905
5122
|
const asTypes = [
|
|
4906
5123
|
"script",
|
|
4907
5124
|
"style",
|
|
@@ -4980,6 +5197,37 @@ function htmlPreloadPlugin(options = {}) {
|
|
|
4980
5197
|
head.insertAdjacentHTML("beforeend", linkTags.join("\n"));
|
|
4981
5198
|
}
|
|
4982
5199
|
}
|
|
5200
|
+
},
|
|
5201
|
+
lspHtmlData() {
|
|
5202
|
+
const attributes = [
|
|
5203
|
+
{
|
|
5204
|
+
name: preloadAttribute,
|
|
5205
|
+
description: `Enable preloading.
|
|
5206
|
+
Automatically generates \`<link rel="preload">\` tags for the dependencies of your scripts and stylesheets.
|
|
5207
|
+
This tells the browser to start fetching those files early, before they are discovered through normal parsing.
|
|
5208
|
+
|
|
5209
|
+
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.`,
|
|
5210
|
+
values: asTypes.map((type) => ({ name: type }))
|
|
5211
|
+
},
|
|
5212
|
+
{
|
|
5213
|
+
name: includeAttribute,
|
|
5214
|
+
description: `Glob patterns list to include when using the \`${preloadAttribute}\` attribute. (semicolon-separated)`
|
|
5215
|
+
},
|
|
5216
|
+
{
|
|
5217
|
+
name: excludeAttribute,
|
|
5218
|
+
description: `Glob patterns list to exclude when using the \`${preloadAttribute}\` attribute. (semicolon-separated)`
|
|
5219
|
+
}
|
|
5220
|
+
];
|
|
5221
|
+
return {
|
|
5222
|
+
version: 1.1,
|
|
5223
|
+
tags: [{
|
|
5224
|
+
name: "link",
|
|
5225
|
+
attributes
|
|
5226
|
+
}, {
|
|
5227
|
+
name: "script",
|
|
5228
|
+
attributes
|
|
5229
|
+
}]
|
|
5230
|
+
};
|
|
4983
5231
|
}
|
|
4984
5232
|
};
|
|
4985
5233
|
}
|
|
@@ -6257,207 +6505,6 @@ function printExecutionTime(executionTime) {
|
|
|
6257
6505
|
console.log();
|
|
6258
6506
|
}
|
|
6259
6507
|
|
|
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
6508
|
//#endregion
|
|
6462
6509
|
//#region src/main.ts
|
|
6463
6510
|
var App = class {
|