@staticbolt/core 1.0.0-beta.10 → 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.
- 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 -267
- 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();
|
|
@@ -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
|
}
|
|
@@ -3249,6 +3221,8 @@ function htmlBundleScriptPlugin(options = {}) {
|
|
|
3249
3221
|
node.textContent = "";
|
|
3250
3222
|
if (this.findMetadata({ filePath: outfile })) {
|
|
3251
3223
|
this.log.info(`The entry point "${entryPoint}" is already bundled in "${outfile}", skipping...`);
|
|
3224
|
+
if (scriptMetadataID) metadata.scriptsMetadataList.delete(scriptMetadataID);
|
|
3225
|
+
node.setAttribute("src", relative(dirname(filePath), outfile));
|
|
3252
3226
|
continue;
|
|
3253
3227
|
}
|
|
3254
3228
|
entryPoint = outfile;
|
|
@@ -3324,6 +3298,32 @@ function htmlBundleScriptPlugin(options = {}) {
|
|
|
3324
3298
|
node.textContent = "";
|
|
3325
3299
|
this.addMetadata(newScriptMetadata);
|
|
3326
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
|
+
};
|
|
3327
3327
|
}
|
|
3328
3328
|
};
|
|
3329
3329
|
}
|
|
@@ -3393,6 +3393,24 @@ function htmlBundleStylePlugin(options = {}) {
|
|
|
3393
3393
|
continue;
|
|
3394
3394
|
}
|
|
3395
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
|
+
};
|
|
3396
3414
|
}
|
|
3397
3415
|
};
|
|
3398
3416
|
}
|
|
@@ -3407,6 +3425,16 @@ function htmlFragmentPlugin(options = {}) {
|
|
|
3407
3425
|
if (!isHtmlMetadata(metadata)) return;
|
|
3408
3426
|
const elements = metadata.ast.querySelectorAll(tag);
|
|
3409
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
|
+
};
|
|
3410
3438
|
}
|
|
3411
3439
|
};
|
|
3412
3440
|
}
|
|
@@ -3502,6 +3530,18 @@ function htmlIifeScriptPlugin(options = {}) {
|
|
|
3502
3530
|
continue;
|
|
3503
3531
|
}
|
|
3504
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
|
+
};
|
|
3505
3545
|
}
|
|
3506
3546
|
};
|
|
3507
3547
|
}
|
|
@@ -3548,6 +3588,18 @@ function htmlInlineScriptPlugin(options = {}) {
|
|
|
3548
3588
|
metadata.scriptsMetadataList.set(metadataID, scriptMetadataClone);
|
|
3549
3589
|
scriptTag.removeAttribute("src");
|
|
3550
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
|
+
};
|
|
3551
3603
|
}
|
|
3552
3604
|
};
|
|
3553
3605
|
}
|
|
@@ -3613,6 +3665,18 @@ function htmlInlineStylePlugin(options = {}) {
|
|
|
3613
3665
|
const attributesString = Object.entries(linkTag.attrs).map(([name, value]) => `${name}="${value}"`).join(" ");
|
|
3614
3666
|
linkTag.replaceWith(`<style ${attributesString}></style>`);
|
|
3615
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
|
+
};
|
|
3616
3680
|
}
|
|
3617
3681
|
};
|
|
3618
3682
|
}
|
|
@@ -3687,6 +3751,18 @@ function HtmlInlineSvgPlugin(options = {}) {
|
|
|
3687
3751
|
for (const [attribute, value] of Object.entries(node.attrs)) svgElement.setAttribute(attribute, value);
|
|
3688
3752
|
node.replaceWith(svgElement);
|
|
3689
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
|
+
};
|
|
3690
3766
|
}
|
|
3691
3767
|
};
|
|
3692
3768
|
}
|
|
@@ -3785,6 +3861,22 @@ function htmlInlineTextPlugin(options = {}) {
|
|
|
3785
3861
|
const importers = deps.getImporters(id);
|
|
3786
3862
|
for (const importer of importers) compileSet.add(importer);
|
|
3787
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
|
+
};
|
|
3788
3880
|
}
|
|
3789
3881
|
};
|
|
3790
3882
|
}
|
|
@@ -3843,6 +3935,35 @@ function htmlInsertPlugin(options = {}) {
|
|
|
3843
3935
|
filePath: metadata.id
|
|
3844
3936
|
});
|
|
3845
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
|
+
};
|
|
3846
3967
|
}
|
|
3847
3968
|
};
|
|
3848
3969
|
}
|
|
@@ -3890,14 +4011,14 @@ function executeExpression$1(expressionString, data) {
|
|
|
3890
4011
|
//#endregion
|
|
3891
4012
|
//#region src/plugins/html-layout/html-layout-plugin.ts
|
|
3892
4013
|
function htmlLayoutPlugin(options = {}) {
|
|
3893
|
-
const
|
|
4014
|
+
const layoutTags = options.tags ?? ["layout", "part"];
|
|
3894
4015
|
const sourceAttribute = options.layoutSourceAttribute ?? "src";
|
|
3895
4016
|
const dataSourceAttribute = options.dataSourceAttribute ?? "dataSource";
|
|
3896
4017
|
const dataJsonAttribute = options.dataJsonAttribute ?? "dataJson";
|
|
3897
4018
|
const alwaysIncludeAttribute = options.alwaysIncludeAttribute ?? "always-include";
|
|
3898
4019
|
const addAttributeAttribute = options.addAttributeAttribute ?? "add-attr";
|
|
3899
4020
|
const removeAttributeAttribute = options.removeAttributeAttribute ?? "remove-attr";
|
|
3900
|
-
const query =
|
|
4021
|
+
const query = layoutTags.join(",");
|
|
3901
4022
|
const printFmtError = PrintFormattedError.create({ function: htmlLayoutPlugin });
|
|
3902
4023
|
const htmlLayoutMetadataCache = [];
|
|
3903
4024
|
/**
|
|
@@ -3907,12 +4028,12 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
3907
4028
|
const dataSourceCache = /* @__PURE__ */ new Map();
|
|
3908
4029
|
function isLayoutPath(path) {
|
|
3909
4030
|
const fileName = basename(path);
|
|
3910
|
-
return
|
|
4031
|
+
return layoutTags.some((tag) => fileName.endsWith(`.${tag}.html`));
|
|
3911
4032
|
}
|
|
3912
4033
|
return {
|
|
3913
4034
|
name: "html-layout",
|
|
3914
4035
|
load(content, relativePath, { type }) {
|
|
3915
|
-
if (type && !
|
|
4036
|
+
if (type && !layoutTags.includes(type)) return;
|
|
3916
4037
|
if (!isLayoutPath(relativePath)) return;
|
|
3917
4038
|
const textAssetMetadata = {
|
|
3918
4039
|
type: METADATA_TYPES.TextAsset,
|
|
@@ -3951,7 +4072,7 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
3951
4072
|
}
|
|
3952
4073
|
if (isMarkdownMetadata(metadata)) for (const [key, source] of Object.entries(metadata.ast.frontmatter)) {
|
|
3953
4074
|
if (!source) continue;
|
|
3954
|
-
if (
|
|
4075
|
+
if (layoutTags.includes(key) || key === dataSourceAttribute) sources.push({
|
|
3955
4076
|
get source() {
|
|
3956
4077
|
return source;
|
|
3957
4078
|
},
|
|
@@ -4176,7 +4297,7 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
4176
4297
|
return;
|
|
4177
4298
|
}
|
|
4178
4299
|
if (isMarkdownMetadata(metadata)) {
|
|
4179
|
-
const tag = Object.keys(metadata.ast.frontmatter).find((key) =>
|
|
4300
|
+
const tag = Object.keys(metadata.ast.frontmatter).find((key) => layoutTags.includes(key));
|
|
4180
4301
|
if (!tag) return;
|
|
4181
4302
|
let attributesString = "";
|
|
4182
4303
|
for (const [key, value] of Object.entries(metadata.ast.frontmatter)) attributesString += `${key === tag ? sourceAttribute : key}="${value}" `;
|
|
@@ -4188,6 +4309,56 @@ function htmlLayoutPlugin(options = {}) {
|
|
|
4188
4309
|
};
|
|
4189
4310
|
return;
|
|
4190
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
|
+
};
|
|
4191
4362
|
}
|
|
4192
4363
|
};
|
|
4193
4364
|
}
|
|
@@ -4255,7 +4426,22 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4255
4426
|
});
|
|
4256
4427
|
continue;
|
|
4257
4428
|
}
|
|
4258
|
-
|
|
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);
|
|
4259
4445
|
}
|
|
4260
4446
|
const currentSources = /* @__PURE__ */ new Set();
|
|
4261
4447
|
const markdowns = metadata.ast.querySelectorAll(markdownTag);
|
|
@@ -4279,8 +4465,23 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4279
4465
|
continue;
|
|
4280
4466
|
}
|
|
4281
4467
|
currentSources.add(sourceRelative);
|
|
4282
|
-
const
|
|
4283
|
-
|
|
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);
|
|
4284
4485
|
}
|
|
4285
4486
|
deps.update(metadata.id, currentSources);
|
|
4286
4487
|
},
|
|
@@ -4293,6 +4494,23 @@ function htmlMarkdownPlugin(options = {}) {
|
|
|
4293
4494
|
const importers = deps.getImporters(id);
|
|
4294
4495
|
for (const importer of importers) compileSet.add(importer);
|
|
4295
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
|
+
};
|
|
4296
4514
|
}
|
|
4297
4515
|
};
|
|
4298
4516
|
}
|
|
@@ -4898,8 +5116,8 @@ function getPreloadInfo(filePath) {
|
|
|
4898
5116
|
//#region src/plugins/html-preload/html-preload-plugin.ts
|
|
4899
5117
|
function htmlPreloadPlugin(options = {}) {
|
|
4900
5118
|
const preloadAttribute = options.preloadAttribute ?? "preload";
|
|
4901
|
-
const includeAttribute = options.includeAttribute ?? "include";
|
|
4902
|
-
const excludeAttribute = options.excludeAttribute ?? "exclude";
|
|
5119
|
+
const includeAttribute = options.includeAttribute ?? "preload-include";
|
|
5120
|
+
const excludeAttribute = options.excludeAttribute ?? "preload-exclude";
|
|
4903
5121
|
const asTypes = [
|
|
4904
5122
|
"script",
|
|
4905
5123
|
"style",
|
|
@@ -4978,6 +5196,37 @@ function htmlPreloadPlugin(options = {}) {
|
|
|
4978
5196
|
head.insertAdjacentHTML("beforeend", linkTags.join("\n"));
|
|
4979
5197
|
}
|
|
4980
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
|
+
};
|
|
4981
5230
|
}
|
|
4982
5231
|
};
|
|
4983
5232
|
}
|
|
@@ -6255,207 +6504,6 @@ function printExecutionTime(executionTime) {
|
|
|
6255
6504
|
console.log();
|
|
6256
6505
|
}
|
|
6257
6506
|
|
|
6258
|
-
//#endregion
|
|
6259
|
-
//#region src/resolver/get-aliases.ts
|
|
6260
|
-
/** Gets path aliases from `tsconfig.json` */
|
|
6261
|
-
function getPathAliases(root) {
|
|
6262
|
-
const [tsconfig, tsconfigParseError] = readTsconfig(root);
|
|
6263
|
-
if (tsconfigParseError !== null) return [null, tsconfigParseError];
|
|
6264
|
-
const paths = tsconfig.paths ?? {};
|
|
6265
|
-
const alias = {};
|
|
6266
|
-
for (const key in paths) {
|
|
6267
|
-
const aliasName = key.replace(/\*$/, "");
|
|
6268
|
-
alias[aliasName] = paths[key][0].replace(/\*$/, "");
|
|
6269
|
-
}
|
|
6270
|
-
return [alias, null];
|
|
6271
|
-
}
|
|
6272
|
-
function readTsconfig(root) {
|
|
6273
|
-
const [tsconfig, tsconfigParseError] = readJsonFile(join(root, "tsconfig.json"));
|
|
6274
|
-
if (tsconfigParseError !== null) return [null, tsconfigParseError];
|
|
6275
|
-
if (!tsconfig.compilerOptions) return [null, /* @__PURE__ */ new Error("[readTsconfig] No compilerOptions found in tsconfig.json")];
|
|
6276
|
-
return [tsconfig.compilerOptions, null];
|
|
6277
|
-
}
|
|
6278
|
-
|
|
6279
|
-
//#endregion
|
|
6280
|
-
//#region src/resolver/resolver.ts
|
|
6281
|
-
const nodeModulesResolver = new ResolverFactory({
|
|
6282
|
-
conditionNames: [
|
|
6283
|
-
"browser",
|
|
6284
|
-
"import",
|
|
6285
|
-
"default"
|
|
6286
|
-
],
|
|
6287
|
-
extensions: [
|
|
6288
|
-
".js",
|
|
6289
|
-
".json",
|
|
6290
|
-
".node",
|
|
6291
|
-
".css"
|
|
6292
|
-
],
|
|
6293
|
-
symlinks: false
|
|
6294
|
-
});
|
|
6295
|
-
var Resolver = class Resolver {
|
|
6296
|
-
root;
|
|
6297
|
-
aliases = {};
|
|
6298
|
-
notFound = /* @__PURE__ */ new Set();
|
|
6299
|
-
files = /* @__PURE__ */ new Set();
|
|
6300
|
-
directories = /* @__PURE__ */ new Set();
|
|
6301
|
-
static JS_EXTENSIONS = new Set([
|
|
6302
|
-
".js",
|
|
6303
|
-
".mjs",
|
|
6304
|
-
".cjs",
|
|
6305
|
-
".jsx",
|
|
6306
|
-
".ts",
|
|
6307
|
-
".mts",
|
|
6308
|
-
".cts",
|
|
6309
|
-
".tsx"
|
|
6310
|
-
]);
|
|
6311
|
-
static HTML_EXTENSIONS = new Set([".html", ".md"]);
|
|
6312
|
-
constructor(root) {
|
|
6313
|
-
this.root = root;
|
|
6314
|
-
const [aliases] = getPathAliases(root);
|
|
6315
|
-
if (aliases) this.aliases = aliases;
|
|
6316
|
-
}
|
|
6317
|
-
resolve(sourceOrLink, filePath) {
|
|
6318
|
-
if (!isValidRelativePath(sourceOrLink)) return;
|
|
6319
|
-
const absFilePath = isAbsolute(filePath) ? filePath : join(this.root, filePath);
|
|
6320
|
-
const [source, suffix] = splitHtmlLink(sourceOrLink);
|
|
6321
|
-
if (isAbsolute(source)) return;
|
|
6322
|
-
const checkDirectory = suffix === "/";
|
|
6323
|
-
const absSource = join(dirname(absFilePath), source);
|
|
6324
|
-
const foundFile = this.findFile(absSource, checkDirectory);
|
|
6325
|
-
if (foundFile) return {
|
|
6326
|
-
path: foundFile,
|
|
6327
|
-
exists: true,
|
|
6328
|
-
suffix
|
|
6329
|
-
};
|
|
6330
|
-
const sourceForAlias = suffix === "/" ? source + "/" : source;
|
|
6331
|
-
const resolvedPathAlias = Resolver.resolvePathAlias(sourceForAlias, this.aliases);
|
|
6332
|
-
if (resolvedPathAlias) {
|
|
6333
|
-
const absSource = join(this.root, resolvedPathAlias);
|
|
6334
|
-
const foundFile = this.findFile(absSource, checkDirectory);
|
|
6335
|
-
const isFileAlias = sourceForAlias in this.aliases && !sourceForAlias.endsWith("/");
|
|
6336
|
-
if (!foundFile && !this.notFound.has(absSource.replace(/\/$/, ""))) {
|
|
6337
|
-
this.notFound.add(absSource.replace(/\/$/, ""));
|
|
6338
|
-
Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" was resolved to "${resolvedPathAlias}", but the file is missing.`);
|
|
6339
|
-
}
|
|
6340
|
-
return {
|
|
6341
|
-
path: foundFile ?? absSource,
|
|
6342
|
-
exists: !!foundFile,
|
|
6343
|
-
suffix,
|
|
6344
|
-
isFileAlias,
|
|
6345
|
-
isDirAlias: !isFileAlias
|
|
6346
|
-
};
|
|
6347
|
-
}
|
|
6348
|
-
if (!source.startsWith(".")) {
|
|
6349
|
-
const resolverResult = nodeModulesResolver.sync(this.root, source);
|
|
6350
|
-
if (resolverResult.path) return {
|
|
6351
|
-
path: resolverResult.path,
|
|
6352
|
-
suffix,
|
|
6353
|
-
exists: true,
|
|
6354
|
-
isPackage: true
|
|
6355
|
-
};
|
|
6356
|
-
}
|
|
6357
|
-
if (source.startsWith("./") || source.startsWith("../")) {
|
|
6358
|
-
if (!this.notFound.has(absSource)) {
|
|
6359
|
-
this.notFound.add(absSource);
|
|
6360
|
-
Log.warn(`[resolver] Source "${sourceOrLink}" found in "${filePath}" points to a non-existent file.`);
|
|
6361
|
-
}
|
|
6362
|
-
return {
|
|
6363
|
-
path: absSource,
|
|
6364
|
-
suffix,
|
|
6365
|
-
exists: false
|
|
6366
|
-
};
|
|
6367
|
-
}
|
|
6368
|
-
}
|
|
6369
|
-
resolveAlias(source) {
|
|
6370
|
-
return Resolver.resolvePathAlias(source, this.aliases);
|
|
6371
|
-
}
|
|
6372
|
-
normalize(filePath) {
|
|
6373
|
-
return normalize(filePath);
|
|
6374
|
-
}
|
|
6375
|
-
static isFile(filePath) {
|
|
6376
|
-
try {
|
|
6377
|
-
return statSync(filePath).isFile();
|
|
6378
|
-
} catch (error) {
|
|
6379
|
-
const code = error.code;
|
|
6380
|
-
if (code === "ENOENT" || code === "ENOTDIR") return false;
|
|
6381
|
-
throw error;
|
|
6382
|
-
}
|
|
6383
|
-
}
|
|
6384
|
-
/** Aliased path to path */
|
|
6385
|
-
static resolvePathAlias(filePath, aliases) {
|
|
6386
|
-
for (const [key, value] of Object.entries(aliases)) {
|
|
6387
|
-
if (key.endsWith("/")) {
|
|
6388
|
-
if (!filePath.startsWith(key)) continue;
|
|
6389
|
-
return filePath.replace(key, value);
|
|
6390
|
-
}
|
|
6391
|
-
if (filePath === key) return value;
|
|
6392
|
-
}
|
|
6393
|
-
}
|
|
6394
|
-
/** Path to aliased path */
|
|
6395
|
-
static resolveAliasPath(filePath, aliases) {
|
|
6396
|
-
let shortest;
|
|
6397
|
-
for (const [key, value] of Object.entries(aliases)) {
|
|
6398
|
-
if (key.endsWith("/")) {
|
|
6399
|
-
if (!filePath.startsWith(value)) continue;
|
|
6400
|
-
const aliased = filePath.replace(value, key);
|
|
6401
|
-
if (!shortest || aliased.length < shortest.length) shortest = aliased;
|
|
6402
|
-
continue;
|
|
6403
|
-
}
|
|
6404
|
-
if (filePath === value && (!shortest || key.length < shortest.length)) shortest = key;
|
|
6405
|
-
}
|
|
6406
|
-
return shortest ?? filePath;
|
|
6407
|
-
}
|
|
6408
|
-
/** Path to aliased path */
|
|
6409
|
-
aliasPath(filePath) {
|
|
6410
|
-
return Resolver.resolveAliasPath(filePath, this.aliases);
|
|
6411
|
-
}
|
|
6412
|
-
findFile(filePath, checkDirectory = false) {
|
|
6413
|
-
if (this.files.has(filePath)) return filePath;
|
|
6414
|
-
if (Resolver.isFile(filePath)) {
|
|
6415
|
-
this.files.add(filePath);
|
|
6416
|
-
return filePath;
|
|
6417
|
-
}
|
|
6418
|
-
const extension = extname(filePath);
|
|
6419
|
-
if (!extension) {
|
|
6420
|
-
for (const candidateExtension of [...Resolver.JS_EXTENSIONS, ...Resolver.HTML_EXTENSIONS]) {
|
|
6421
|
-
const candidate = replaceExtension(filePath, candidateExtension);
|
|
6422
|
-
if (this.files.has(candidate)) return candidate;
|
|
6423
|
-
if (Resolver.isFile(candidate)) {
|
|
6424
|
-
this.files.add(candidate);
|
|
6425
|
-
return candidate;
|
|
6426
|
-
}
|
|
6427
|
-
}
|
|
6428
|
-
const withIndex = join(filePath, "index");
|
|
6429
|
-
for (const candidateExtension of Resolver.HTML_EXTENSIONS) {
|
|
6430
|
-
const candidate = replaceExtension(withIndex, candidateExtension);
|
|
6431
|
-
if (this.files.has(candidate)) return candidate;
|
|
6432
|
-
if (Resolver.isFile(candidate)) {
|
|
6433
|
-
this.files.add(candidate);
|
|
6434
|
-
return candidate;
|
|
6435
|
-
}
|
|
6436
|
-
}
|
|
6437
|
-
if (checkDirectory) {
|
|
6438
|
-
if (this.directories.has(filePath)) return filePath;
|
|
6439
|
-
if (existsSync(filePath)) {
|
|
6440
|
-
this.directories.add(filePath);
|
|
6441
|
-
return filePath;
|
|
6442
|
-
}
|
|
6443
|
-
}
|
|
6444
|
-
return;
|
|
6445
|
-
}
|
|
6446
|
-
if (Resolver.JS_EXTENSIONS.has(extension)) {
|
|
6447
|
-
for (const jsExtension of Resolver.JS_EXTENSIONS) {
|
|
6448
|
-
const candidate = replaceExtension(filePath, jsExtension);
|
|
6449
|
-
if (Resolver.isFile(candidate)) {
|
|
6450
|
-
this.files.add(candidate);
|
|
6451
|
-
return candidate;
|
|
6452
|
-
}
|
|
6453
|
-
}
|
|
6454
|
-
return;
|
|
6455
|
-
}
|
|
6456
|
-
}
|
|
6457
|
-
};
|
|
6458
|
-
|
|
6459
6507
|
//#endregion
|
|
6460
6508
|
//#region src/main.ts
|
|
6461
6509
|
var App = class {
|