kss-modern 1.2.0-beta.1 → 1.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/node/lib/index.mjs +133 -66
- package/dist/node/lib/pug/worker.d.mts +12 -0
- package/dist/node/lib/pug/worker.d.ts +12 -0
- package/dist/node/lib/pug/worker.mjs +6 -4
- package/dist/node/shared/{kss-modern.C3thzyxO.mjs → kss-modern.o1Fp758z.mjs} +96 -10
- package/dist/styleguide-assets/.vite/manifest.json +15 -7
- package/dist/styleguide-assets/{axe-BUK9a7nX.js → axe-DInlcoey.js} +1 -1
- package/dist/styleguide-assets/{browser-bCxY1z1G.js → browser-DRrrjwZN.js} +1 -1
- package/dist/styleguide-assets/fullpage-Bm_FdpPi.js +193 -0
- package/dist/styleguide-assets/{html-validator-Cv_-JCAq.js → html-validator-B4XHcC9W.js} +22 -31
- package/dist/styleguide-assets/kss-modern-DW2ZdZvd.css +3 -0
- package/dist/styleguide-assets/{preview-8L8aaFj4.js → preview-w33XyCLZ.js} +1 -1
- package/dist/styleguide-assets/shared-hGcWlnRM.js +15 -0
- package/package.json +2 -1
- package/dist/styleguide-assets/fullpage-CVmYa-FG.js +0 -127
- package/dist/styleguide-assets/kss-modern-CjPjhHw0.css +0 -3
package/dist/node/lib/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { performance } from 'node:perf_hooks';
|
|
2
3
|
import process from 'node:process';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import fs from 'fs-extra';
|
|
5
6
|
import { glob } from 'tinyglobby';
|
|
6
|
-
import { l as logger, s as sanitizeSpecialCharacters, I as INSERT_VITE_PUG_TAG_RE, P as PUG_SRC_RE, c as compileMarkup, p as pugErrorFile,
|
|
7
|
-
export {
|
|
7
|
+
import { l as logger, s as sanitizeSpecialCharacters, I as INSERT_VITE_PUG_TAG_RE, P as PUG_SRC_RE, a as PUG_ERROR_OVERLAY_TAG, c as compileMarkup, p as pugErrorFile, b as sectionSanitizeId, d as stripPugErrorOverlay, e as ensureStartingSlash, g as generateId, r as replaceWrapperContent } from '../shared/kss-modern.o1Fp758z.mjs';
|
|
8
|
+
export { f as createLogger } from '../shared/kss-modern.o1Fp758z.mjs';
|
|
8
9
|
import { fromAsyncCodeToHtml } from '@shikijs/markdown-it/async';
|
|
9
10
|
import MarkdownItAsync from 'markdown-it-async';
|
|
10
11
|
import { codeToHtml } from 'shiki';
|
|
@@ -14,10 +15,10 @@ import fs$1 from 'node:fs/promises';
|
|
|
14
15
|
import { objectEntries } from '@antfu/utils';
|
|
15
16
|
import { readFileSync } from 'node:fs';
|
|
16
17
|
import chokidar from 'chokidar';
|
|
17
|
-
import '@biomejs/js-api';
|
|
18
18
|
import 'pug';
|
|
19
19
|
import 'consola';
|
|
20
20
|
import 'consola/utils';
|
|
21
|
+
import 'pug-load';
|
|
21
22
|
|
|
22
23
|
const HEX_COLOR_RE = /^#[0-9A-F]{6}$/i;
|
|
23
24
|
function isValidHexColor(hexCode) {
|
|
@@ -998,45 +999,116 @@ class PugDependencyGraph {
|
|
|
998
999
|
}
|
|
999
1000
|
}
|
|
1000
1001
|
|
|
1001
|
-
function renderPugErrorOverlay(error) {
|
|
1002
|
+
function renderPugErrorOverlay(error, lastHtml = "") {
|
|
1002
1003
|
const id = escape(error.id);
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
style="box-sizing:border-box;width:100%;margin:0;padding:16px 18px;border:1px solid #f43f5e59;border-radius:12px;background:#1f1f23;font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;color:#e4e4e7;line-height:1.5;text-align:left;"
|
|
1009
|
-
>
|
|
1010
|
-
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">
|
|
1011
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#f43f5e" style="width:18px;height:18px;flex:none;" aria-hidden="true">
|
|
1012
|
-
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495ZM10 5a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 10 5Zm0 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z" clip-rule="evenodd" />
|
|
1013
|
-
</svg>
|
|
1014
|
-
<span style="font-weight:600;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#fb7185;">Pug compile error</span>
|
|
1015
|
-
</div>
|
|
1016
|
-
<h1 style="margin:0;font-size:16px;font-weight:600;color:#fafafa;">Section <code style="font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:#f43f5e1a;border-radius:5px;padding:1px 7px;color:#fda4af;">${id}</code> failed to compile</h1>
|
|
1017
|
-
${file ? `<p style="margin:8px 0 0;font-size:13px;color:#a1a1aa;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;">${file}</p>` : ""}
|
|
1018
|
-
<pre style="margin:12px 0 0;padding:12px 14px;background:#111113;border:1px solid #2a2a30;border-radius:8px;overflow:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.55;color:#f4f4f5;white-space:pre;"><code>${message}</code></pre>
|
|
1019
|
-
</div>`.trim();
|
|
1004
|
+
const message = escape(error.message).replace(/\r?\n/g, " ");
|
|
1005
|
+
const fileAttr = error.file ? ` error-file="${escape(error.file)}"` : "";
|
|
1006
|
+
const emptyAttr = lastHtml ? "" : " data-empty";
|
|
1007
|
+
const overlay = `<${PUG_ERROR_OVERLAY_TAG} error-id="${id}"${fileAttr} error-message="${message}"${emptyAttr}></${PUG_ERROR_OVERLAY_TAG}>`;
|
|
1008
|
+
return `${lastHtml}${overlay}`.trim();
|
|
1020
1009
|
}
|
|
1021
1010
|
|
|
1022
|
-
const MAX_POOL_SIZE = os.cpus().length;
|
|
1011
|
+
const MAX_POOL_SIZE = Math.max(2, os.cpus().length - 1);
|
|
1023
1012
|
const INLINE_THRESHOLD = 2;
|
|
1024
1013
|
const cache = new PugCompileCache();
|
|
1025
1014
|
const graph = new PugDependencyGraph();
|
|
1026
1015
|
function getPugDependencyGraph() {
|
|
1027
1016
|
return graph;
|
|
1028
1017
|
}
|
|
1018
|
+
let lastCompileTimings = { read: 0, parse: 0, render: 0, a11y: 0, sections: 0 };
|
|
1019
|
+
function accumulateTimings(timings) {
|
|
1020
|
+
lastCompileTimings.read += timings.read;
|
|
1021
|
+
lastCompileTimings.parse += timings.parse;
|
|
1022
|
+
lastCompileTimings.render += timings.render;
|
|
1023
|
+
lastCompileTimings.a11y += timings.a11y;
|
|
1024
|
+
lastCompileTimings.sections += 1;
|
|
1025
|
+
}
|
|
1026
|
+
function getLastCompileTimings() {
|
|
1027
|
+
return lastCompileTimings;
|
|
1028
|
+
}
|
|
1029
1029
|
const __filename$1 = fileURLToPath(import.meta.url);
|
|
1030
1030
|
const __dirname$1 = path.dirname(__filename$1);
|
|
1031
1031
|
const workerFilePath = __dirname$1.includes("dist/") ? "./pug/worker.mjs" : "./worker.ts";
|
|
1032
1032
|
const workerFilePathResolved = path.resolve(__dirname$1, workerFilePath);
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1033
|
+
const slots = Array.from({ length: MAX_POOL_SIZE }, () => ({ tail: Promise.resolve(), active: 0 }));
|
|
1034
|
+
const allWorkers = /* @__PURE__ */ new Set();
|
|
1035
|
+
function slotIndexFor(id) {
|
|
1036
|
+
let hash = 2166136261;
|
|
1037
|
+
for (let i = 0; i < id.length; i++) {
|
|
1038
|
+
hash ^= id.charCodeAt(i);
|
|
1039
|
+
hash = Math.imul(hash, 16777619);
|
|
1040
|
+
}
|
|
1041
|
+
return (hash >>> 0) % MAX_POOL_SIZE;
|
|
1042
|
+
}
|
|
1043
|
+
function spawnWorker(index) {
|
|
1044
|
+
const worker = new Worker(workerFilePathResolved, { name: `pug-worker-${index}` });
|
|
1045
|
+
allWorkers.add(worker);
|
|
1046
|
+
return worker;
|
|
1047
|
+
}
|
|
1048
|
+
function runOnWorker(worker, input) {
|
|
1049
|
+
return new Promise((resolve, reject) => {
|
|
1050
|
+
function cleanup() {
|
|
1051
|
+
worker.off("message", onMessage);
|
|
1052
|
+
worker.off("error", onError);
|
|
1053
|
+
}
|
|
1054
|
+
function onMessage(result) {
|
|
1055
|
+
cleanup();
|
|
1056
|
+
resolve(result);
|
|
1057
|
+
}
|
|
1058
|
+
function onError(error) {
|
|
1059
|
+
cleanup();
|
|
1060
|
+
reject(error);
|
|
1061
|
+
}
|
|
1062
|
+
worker.once("message", onMessage);
|
|
1063
|
+
worker.once("error", onError);
|
|
1064
|
+
worker.postMessage(input);
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
function runPinned(id, input) {
|
|
1068
|
+
const slot = slots[slotIndexFor(id)];
|
|
1069
|
+
slot.active++;
|
|
1070
|
+
const run = slot.tail.then(async () => {
|
|
1071
|
+
if (!slot.worker)
|
|
1072
|
+
slot.worker = spawnWorker(slots.indexOf(slot));
|
|
1073
|
+
const worker = slot.worker;
|
|
1074
|
+
worker.ref();
|
|
1075
|
+
try {
|
|
1076
|
+
return await runOnWorker(worker, input);
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
allWorkers.delete(worker);
|
|
1079
|
+
void worker.terminate().catch(() => {
|
|
1080
|
+
});
|
|
1081
|
+
if (slot.worker === worker)
|
|
1082
|
+
slot.worker = void 0;
|
|
1083
|
+
throw error;
|
|
1084
|
+
} finally {
|
|
1085
|
+
slot.active--;
|
|
1086
|
+
if (slot.active === 0)
|
|
1087
|
+
slot.worker?.unref();
|
|
1088
|
+
}
|
|
1089
|
+
});
|
|
1090
|
+
slot.tail = run.then(() => {
|
|
1091
|
+
}, () => {
|
|
1092
|
+
});
|
|
1093
|
+
return run;
|
|
1094
|
+
}
|
|
1095
|
+
function getPugPoolInfo() {
|
|
1096
|
+
return { cpus: os.cpus().length, maxPoolSize: MAX_POOL_SIZE, workers: allWorkers.size };
|
|
1097
|
+
}
|
|
1098
|
+
async function terminatePugWorkers() {
|
|
1099
|
+
const workers = [...allWorkers];
|
|
1100
|
+
allWorkers.clear();
|
|
1101
|
+
for (const slot of slots) {
|
|
1102
|
+
slot.worker = void 0;
|
|
1103
|
+
slot.tail = Promise.resolve();
|
|
1104
|
+
slot.active = 0;
|
|
1105
|
+
}
|
|
1106
|
+
await Promise.all(workers.map((worker) => worker.terminate()));
|
|
1037
1107
|
}
|
|
1038
1108
|
const signals = ["SIGINT", "SIGTERM", "SIGQUIT"];
|
|
1039
|
-
signals.forEach((signal) => process.on(signal,
|
|
1109
|
+
signals.forEach((signal) => process.on(signal, () => {
|
|
1110
|
+
void terminatePugWorkers();
|
|
1111
|
+
}));
|
|
1040
1112
|
async function storeResult(id, markupSource, html, dependencies) {
|
|
1041
1113
|
graph.setDependencies(id, dependencies);
|
|
1042
1114
|
const depSignatures = await computeDepSignatures(dependencies);
|
|
@@ -1046,14 +1118,16 @@ function recordFailure(mode, repository, errors, pugError) {
|
|
|
1046
1118
|
logger.error(`Pug markup failed to compile for section "${pugError.id}": ${pugError.message}`);
|
|
1047
1119
|
errors.push(pugError);
|
|
1048
1120
|
if (mode === "development") {
|
|
1049
|
-
|
|
1121
|
+
const lastHtml = cache.get(pugError.id)?.compiledHtml ?? "";
|
|
1122
|
+
repository.set(pugError.id, { markup: renderPugErrorOverlay(pugError, lastHtml) });
|
|
1050
1123
|
}
|
|
1051
1124
|
}
|
|
1052
1125
|
async function compileInline(mode, contentDir, repository, id, errors) {
|
|
1053
1126
|
const markupSource = repository.get(id).markup;
|
|
1054
1127
|
try {
|
|
1055
|
-
const { html, dependencies } = await compileMarkup(contentDir, mode, markupSource, id);
|
|
1128
|
+
const { html, dependencies, timings } = await compileMarkup(contentDir, mode, markupSource, id);
|
|
1056
1129
|
repository.set(id, { markup: html });
|
|
1130
|
+
accumulateTimings(timings);
|
|
1057
1131
|
await storeResult(id, markupSource, html, dependencies);
|
|
1058
1132
|
} catch (error) {
|
|
1059
1133
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1062,39 +1136,16 @@ async function compileInline(mode, contentDir, repository, id, errors) {
|
|
|
1062
1136
|
}
|
|
1063
1137
|
}
|
|
1064
1138
|
async function compileViaWorkerPool(mode, contentDir, repository, ids, errors) {
|
|
1065
|
-
const poolSize = Math.min(ids.length, MAX_POOL_SIZE);
|
|
1066
|
-
const waiters = [];
|
|
1067
|
-
const freeWorkers = [];
|
|
1068
|
-
function releaseWorker(worker) {
|
|
1069
|
-
const waiter = waiters.shift();
|
|
1070
|
-
if (waiter) {
|
|
1071
|
-
waiter(worker);
|
|
1072
|
-
} else {
|
|
1073
|
-
freeWorkers.push(worker);
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
function acquireWorker() {
|
|
1077
|
-
const worker = freeWorkers.pop();
|
|
1078
|
-
if (worker) {
|
|
1079
|
-
return Promise.resolve(worker);
|
|
1080
|
-
}
|
|
1081
|
-
return new Promise((resolve) => waiters.push(resolve));
|
|
1082
|
-
}
|
|
1083
|
-
workerPool = Array.from({ length: poolSize }, (_, index) => {
|
|
1084
|
-
const worker = new Worker(workerFilePathResolved, {
|
|
1085
|
-
name: `pug-worker-${index}`
|
|
1086
|
-
});
|
|
1087
|
-
freeWorkers.push(worker);
|
|
1088
|
-
return worker;
|
|
1089
|
-
});
|
|
1090
1139
|
const tasks = ids.map(async (id) => {
|
|
1091
1140
|
const markupSource = repository.get(id).markup;
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1141
|
+
let result;
|
|
1142
|
+
try {
|
|
1143
|
+
result = await runPinned(id, { id, mode, html: markupSource, contentDir });
|
|
1144
|
+
} catch (error) {
|
|
1145
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1146
|
+
recordFailure(mode, repository, errors, { id, message });
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1098
1149
|
if ("error" in result) {
|
|
1099
1150
|
recordFailure(mode, repository, errors, {
|
|
1100
1151
|
id,
|
|
@@ -1104,10 +1155,10 @@ async function compileViaWorkerPool(mode, contentDir, repository, ids, errors) {
|
|
|
1104
1155
|
return;
|
|
1105
1156
|
}
|
|
1106
1157
|
repository.set(id, { markup: result.html });
|
|
1158
|
+
accumulateTimings(result.timings);
|
|
1107
1159
|
await storeResult(id, markupSource, result.html, result.dependencies);
|
|
1108
1160
|
});
|
|
1109
1161
|
await Promise.all(tasks);
|
|
1110
|
-
await terminateAllWorkers();
|
|
1111
1162
|
}
|
|
1112
1163
|
async function compileIds(mode, contentDir, repository, ids) {
|
|
1113
1164
|
const clonedRepository = new Map(repository);
|
|
@@ -1129,6 +1180,7 @@ async function compileIds(mode, contentDir, repository, ids) {
|
|
|
1129
1180
|
if (misses.length === 0)
|
|
1130
1181
|
return clonedRepository;
|
|
1131
1182
|
const errors = [];
|
|
1183
|
+
lastCompileTimings = { read: 0, parse: 0, render: 0, a11y: 0, sections: 0 };
|
|
1132
1184
|
const useInline = mode === "development" && misses.length <= INLINE_THRESHOLD;
|
|
1133
1185
|
if (useInline) {
|
|
1134
1186
|
await Promise.all(misses.map((id) => compileInline(mode, contentDir, clonedRepository, id, errors)));
|
|
@@ -1189,7 +1241,7 @@ async function generateFullPageFile(data) {
|
|
|
1189
1241
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="${data.theme.light}">
|
|
1190
1242
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="${data.theme.dark}">
|
|
1191
1243
|
` : `<meta name="theme-color" content="${data.theme}">`}
|
|
1192
|
-
<script type="module" src="/styleguide-assets/fullpage-
|
|
1244
|
+
<script type="module" src="/styleguide-assets/fullpage-Bm_FdpPi.js"><\/script>
|
|
1193
1245
|
${computedStyleTags}
|
|
1194
1246
|
</head>
|
|
1195
1247
|
<body${data.page.bodyclass ? ` class="${data.page.bodyclass}"` : ""}>
|
|
@@ -1511,6 +1563,7 @@ ${html ?? ""}
|
|
|
1511
1563
|
`;
|
|
1512
1564
|
}
|
|
1513
1565
|
function getMainContentRegular(section, config) {
|
|
1566
|
+
const sourceCode = stripPugErrorOverlay(section.markup);
|
|
1514
1567
|
const openInEditorPaths = {};
|
|
1515
1568
|
if (config.mode === "development" && config.launchInEditor) {
|
|
1516
1569
|
const computedRootPath = config.launchInEditor && typeof config.launchInEditor === "object" && "rootDir" in config.launchInEditor ? config.launchInEditor.rootDir : process.cwd();
|
|
@@ -1612,7 +1665,7 @@ function getMainContentRegular(section, config) {
|
|
|
1612
1665
|
<button
|
|
1613
1666
|
class="inline-flex items-center gap-1.5 p-4 cursor-pointer active:scale-90 transition hover:text-styleguide-highlight duration-200"
|
|
1614
1667
|
type="button"
|
|
1615
|
-
data-clipboard-value="${encodeURIComponent(
|
|
1668
|
+
data-clipboard-value="${encodeURIComponent(sourceCode)}"
|
|
1616
1669
|
data-clipboard-uri-encoded="true"
|
|
1617
1670
|
>
|
|
1618
1671
|
<svg class="h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
|
@@ -1655,7 +1708,7 @@ function getMainContentRegular(section, config) {
|
|
|
1655
1708
|
<div
|
|
1656
1709
|
id="code-fullpage-${sectionSanitizeId(section.id)}"
|
|
1657
1710
|
class="overflow-x-auto w-full code-highlight"
|
|
1658
|
-
data-source-code="${encodeURIComponent(
|
|
1711
|
+
data-source-code="${encodeURIComponent(sourceCode)}"
|
|
1659
1712
|
data-source-lang="html"
|
|
1660
1713
|
></div>
|
|
1661
1714
|
</div>
|
|
@@ -1992,7 +2045,7 @@ async function generatePreviewFile(data) {
|
|
|
1992
2045
|
<meta name="theme-color" media="(prefers-color-scheme: light)" content="${data.theme.light}">
|
|
1993
2046
|
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="${data.theme.dark}">
|
|
1994
2047
|
` : `<meta name="theme-color" content="${data.theme}">`}
|
|
1995
|
-
<link rel="stylesheet" type="text/css" href="/styleguide-assets/kss-modern-
|
|
2048
|
+
<link rel="stylesheet" type="text/css" href="/styleguide-assets/kss-modern-DW2ZdZvd.css">
|
|
1996
2049
|
<script>
|
|
1997
2050
|
//#region client/lib/iframe-resize.ts
|
|
1998
2051
|
var e = [
|
|
@@ -2145,7 +2198,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
2145
2198
|
//#endregion
|
|
2146
2199
|
;
|
|
2147
2200
|
<\/script>
|
|
2148
|
-
<script type="module" src="/styleguide-assets/preview-
|
|
2201
|
+
<script type="module" src="/styleguide-assets/preview-w33XyCLZ.js"><\/script>
|
|
2149
2202
|
<link rel="preload" href="/styleguide-assets/fonts/geist-mono-latin-400-normal.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
|
2150
2203
|
<link rel="preload" href="/styleguide-assets/fonts/geist-mono-latin-600-normal.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
|
2151
2204
|
<link rel="preload" href="/styleguide-assets/fonts/geist-mono-latin-300-normal.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
|
@@ -2568,17 +2621,21 @@ async function rebuildSections(config, context, changedSectionIds) {
|
|
|
2568
2621
|
}
|
|
2569
2622
|
if (subset.size === 0)
|
|
2570
2623
|
return;
|
|
2624
|
+
const startedAt = performance.now();
|
|
2625
|
+
const workersBefore = getPugPoolInfo().workers;
|
|
2571
2626
|
const recompiled = await compilePugMarkupIncremental(config.mode, config.contentDir, subset, subset.keys());
|
|
2572
2627
|
for (const [id, entry] of recompiled) {
|
|
2573
2628
|
context.compiledRepository.set(id, { markup: entry.markup });
|
|
2574
2629
|
reindexInsertMarkupConsumer(context, id);
|
|
2575
2630
|
}
|
|
2631
|
+
const afterCompile = performance.now();
|
|
2576
2632
|
const resolved = resolveInsertMarkupForSections(context.compiledRepository, context.sectionsById, affected);
|
|
2577
2633
|
for (const [id, markup] of resolved) {
|
|
2578
2634
|
const node = context.nodeById.get(id);
|
|
2579
2635
|
if (node)
|
|
2580
2636
|
node.markup = markup;
|
|
2581
2637
|
}
|
|
2638
|
+
const afterResolve = performance.now();
|
|
2582
2639
|
const writeTasks = [];
|
|
2583
2640
|
const previewsToWrite = /* @__PURE__ */ new Set();
|
|
2584
2641
|
for (const id of affected) {
|
|
@@ -2596,6 +2653,16 @@ async function rebuildSections(config, context, changedSectionIds) {
|
|
|
2596
2653
|
writeTasks.push(writePreviewFile(config, context, firstLevelIndex, secondLevelIndex));
|
|
2597
2654
|
}
|
|
2598
2655
|
await Promise.all(writeTasks);
|
|
2656
|
+
const afterWrite = performance.now();
|
|
2657
|
+
if (config.mode === "development") {
|
|
2658
|
+
const ms = (value) => `${value.toFixed(1)}ms`;
|
|
2659
|
+
const pool = getPugPoolInfo();
|
|
2660
|
+
const spawned = pool.workers - workersBefore;
|
|
2661
|
+
const t = getLastCompileTimings();
|
|
2662
|
+
logger.info(
|
|
2663
|
+
`Incremental rebuild: ${affected.size} section(s), ${writeTasks.length} file(s) in ${ms(afterWrite - startedAt)} (compile ${ms(afterCompile - startedAt)}, insert-markup ${ms(afterResolve - afterCompile)}, write ${ms(afterWrite - afterResolve)}) [cpus=${pool.cpus}, pool=${pool.maxPoolSize}, workers=${pool.workers}${spawned > 0 ? `, +${spawned} cold-spawned` : ""}] compile breakdown over ${t.sections} section(s): read ${ms(t.read)}, parse ${ms(t.parse)}, render ${ms(t.render)}, a11y ${ms(t.a11y)} (summed per-section; read=disk I/O, parse=lex/parse/codegen)`
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2599
2666
|
}
|
|
2600
2667
|
async function watchStyleguide(config, onChange, onError) {
|
|
2601
2668
|
const initialBuild = await buildAll(config);
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { StyleguideConfiguration } from '../index.mjs';
|
|
2
2
|
|
|
3
3
|
type Mode = StyleguideConfiguration['mode'];
|
|
4
|
+
/** Where a section's compile time went, summed over the entry file and any <insert-vite-pug> tags. */
|
|
5
|
+
interface CompileTimings {
|
|
6
|
+
/** Reading the entry file + all includes/extends off disk (file I/O only). */
|
|
7
|
+
read: number;
|
|
8
|
+
/** pug lex + parse + codegen (CPU; excludes the include reads). */
|
|
9
|
+
parse: number;
|
|
10
|
+
/** Executing the compiled template function (pure render). */
|
|
11
|
+
render: number;
|
|
12
|
+
/** `fixAccessibilityIssues` post-processing. */
|
|
13
|
+
a11y: number;
|
|
14
|
+
}
|
|
4
15
|
|
|
5
16
|
interface PugWorkerInput {
|
|
6
17
|
id: string;
|
|
@@ -12,6 +23,7 @@ interface PugWorkerSuccess {
|
|
|
12
23
|
id: string;
|
|
13
24
|
html: string;
|
|
14
25
|
dependencies: string[];
|
|
26
|
+
timings: CompileTimings;
|
|
15
27
|
}
|
|
16
28
|
interface PugWorkerError {
|
|
17
29
|
id: string;
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { StyleguideConfiguration } from '../index.js';
|
|
2
2
|
|
|
3
3
|
type Mode = StyleguideConfiguration['mode'];
|
|
4
|
+
/** Where a section's compile time went, summed over the entry file and any <insert-vite-pug> tags. */
|
|
5
|
+
interface CompileTimings {
|
|
6
|
+
/** Reading the entry file + all includes/extends off disk (file I/O only). */
|
|
7
|
+
read: number;
|
|
8
|
+
/** pug lex + parse + codegen (CPU; excludes the include reads). */
|
|
9
|
+
parse: number;
|
|
10
|
+
/** Executing the compiled template function (pure render). */
|
|
11
|
+
render: number;
|
|
12
|
+
/** `fixAccessibilityIssues` post-processing. */
|
|
13
|
+
a11y: number;
|
|
14
|
+
}
|
|
4
15
|
|
|
5
16
|
interface PugWorkerInput {
|
|
6
17
|
id: string;
|
|
@@ -12,6 +23,7 @@ interface PugWorkerSuccess {
|
|
|
12
23
|
id: string;
|
|
13
24
|
html: string;
|
|
14
25
|
dependencies: string[];
|
|
26
|
+
timings: CompileTimings;
|
|
15
27
|
}
|
|
16
28
|
interface PugWorkerError {
|
|
17
29
|
id: string;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { parentPort } from 'node:worker_threads';
|
|
2
|
-
import { c as compileMarkup, p as pugErrorFile } from '../../shared/kss-modern.
|
|
2
|
+
import { c as compileMarkup, p as pugErrorFile } from '../../shared/kss-modern.o1Fp758z.mjs';
|
|
3
|
+
import 'node:fs';
|
|
3
4
|
import 'node:fs/promises';
|
|
4
5
|
import 'node:path';
|
|
5
|
-
import '
|
|
6
|
+
import 'node:perf_hooks';
|
|
6
7
|
import 'pug';
|
|
7
8
|
import 'consola';
|
|
8
9
|
import 'consola/utils';
|
|
10
|
+
import 'pug-load';
|
|
9
11
|
|
|
10
12
|
if (!parentPort) {
|
|
11
13
|
throw new Error("This file must be run as a worker thread");
|
|
@@ -13,8 +15,8 @@ if (!parentPort) {
|
|
|
13
15
|
parentPort.on("message", async (data) => {
|
|
14
16
|
const { id, mode, html, contentDir } = data;
|
|
15
17
|
try {
|
|
16
|
-
const { html: compiled, dependencies } = await compileMarkup(contentDir, mode, html, id);
|
|
17
|
-
parentPort.postMessage({ id, html: compiled, dependencies });
|
|
18
|
+
const { html: compiled, dependencies, timings } = await compileMarkup(contentDir, mode, html, id);
|
|
19
|
+
parentPort.postMessage({ id, html: compiled, dependencies, timings });
|
|
18
20
|
} catch (error) {
|
|
19
21
|
const message = error instanceof Error ? error.message : String(error);
|
|
20
22
|
parentPort.postMessage({ id, error: message, file: pugErrorFile(error) });
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { statSync, readFileSync } from 'node:fs';
|
|
1
2
|
import fs from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
+
import { performance } from 'node:perf_hooks';
|
|
4
5
|
import pug from 'pug';
|
|
5
6
|
import { createConsola } from 'consola';
|
|
6
7
|
import { colors } from 'consola/utils';
|
|
8
|
+
import pugLoad from 'pug-load';
|
|
7
9
|
|
|
8
10
|
const sectionSanitizeId = (id2) => id2.toLowerCase().replaceAll(".", "-");
|
|
9
11
|
|
|
@@ -25,6 +27,11 @@ const logger = createLogger();
|
|
|
25
27
|
const INSERT_VITE_PUG_TAG_RE = /<insert-vite-pug src="(.+?)".*(?:[\n\r\u2028\u2029]\s*)?(modifierClass="(.+?)")? *><\/insert-vite-pug>/g;
|
|
26
28
|
const PUG_SRC_RE = /src="(.+?)"/;
|
|
27
29
|
const PUG_MODIFIER_CLASS_RE = /modifierClass="(.+?)"/;
|
|
30
|
+
const PUG_ERROR_OVERLAY_TAG = "pug-error-overlay";
|
|
31
|
+
const PUG_ERROR_OVERLAY_RE = new RegExp(`<${PUG_ERROR_OVERLAY_TAG}\\b[^>]*></${PUG_ERROR_OVERLAY_TAG}>`, "g");
|
|
32
|
+
function stripPugErrorOverlay(html) {
|
|
33
|
+
return html.replace(PUG_ERROR_OVERLAY_RE, "");
|
|
34
|
+
}
|
|
28
35
|
function fixAccessibilityIssues(html) {
|
|
29
36
|
let parsedMarkup = html;
|
|
30
37
|
const omitValue = [
|
|
@@ -80,9 +87,46 @@ function generateId() {
|
|
|
80
87
|
return value;
|
|
81
88
|
}
|
|
82
89
|
|
|
90
|
+
const parseCache = /* @__PURE__ */ new Map();
|
|
91
|
+
function signatureOf(filename) {
|
|
92
|
+
try {
|
|
93
|
+
const stat = statSync(filename);
|
|
94
|
+
return `${stat.mtimeMs}:${stat.size}`;
|
|
95
|
+
} catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
let installed = false;
|
|
100
|
+
const originalLoadString = pugLoad.string;
|
|
101
|
+
function installPugParseCache() {
|
|
102
|
+
if (installed)
|
|
103
|
+
return;
|
|
104
|
+
installed = true;
|
|
105
|
+
pugLoad.string = function cachedLoadString(src, options) {
|
|
106
|
+
const filename = options?.filename;
|
|
107
|
+
if (filename && typeof options.lex === "function" && typeof options.parse === "function") {
|
|
108
|
+
const sig = signatureOf(filename);
|
|
109
|
+
if (sig !== null) {
|
|
110
|
+
let parsed;
|
|
111
|
+
const cached = parseCache.get(filename);
|
|
112
|
+
if (cached && cached.sig === sig) {
|
|
113
|
+
parsed = cached.ast;
|
|
114
|
+
} else {
|
|
115
|
+
parsed = options.parse(options.lex(src, options), options);
|
|
116
|
+
parseCache.set(filename, { sig, ast: parsed });
|
|
117
|
+
}
|
|
118
|
+
return pugLoad(parsed, options);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return originalLoadString(src, options);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
installPugParseCache();
|
|
83
126
|
let biomePromise;
|
|
84
127
|
function getBiome() {
|
|
85
128
|
biomePromise ??= (async () => {
|
|
129
|
+
const { Biome, Distribution } = await import('@biomejs/js-api');
|
|
86
130
|
const biome = await Biome.create({ distribution: Distribution.NODE });
|
|
87
131
|
const { projectKey } = biome.openProject(".");
|
|
88
132
|
biome.applyConfiguration(projectKey, {
|
|
@@ -118,7 +162,7 @@ async function biomeFormat(content) {
|
|
|
118
162
|
}
|
|
119
163
|
}
|
|
120
164
|
function createUseId(sectionId) {
|
|
121
|
-
const namespace = sectionSanitizeId(sectionId)
|
|
165
|
+
const namespace = `id-${sectionSanitizeId(sectionId)}`;
|
|
122
166
|
let autoCounter = 0;
|
|
123
167
|
return (key) => {
|
|
124
168
|
if (key === void 0) {
|
|
@@ -132,24 +176,50 @@ function pugErrorFile(error) {
|
|
|
132
176
|
const candidate = error;
|
|
133
177
|
return candidate?.path ?? candidate?.filename;
|
|
134
178
|
}
|
|
179
|
+
let includeReadMs = 0;
|
|
180
|
+
function timedRead(filePath) {
|
|
181
|
+
const t0 = performance.now();
|
|
182
|
+
const content = readFileSync(filePath, "utf8");
|
|
183
|
+
includeReadMs += performance.now() - t0;
|
|
184
|
+
return content;
|
|
185
|
+
}
|
|
135
186
|
function compilePugFile(pugFilePath, mode, sectionId, extraLocals = {}) {
|
|
136
|
-
const
|
|
187
|
+
const tRead0 = performance.now();
|
|
188
|
+
const source = readFileSync(pugFilePath, "utf8");
|
|
189
|
+
let readMs = performance.now() - tRead0;
|
|
190
|
+
const includeReadBefore = includeReadMs;
|
|
191
|
+
const tParse0 = performance.now();
|
|
192
|
+
const pugFn = pug.compile(source, {
|
|
193
|
+
filename: pugFilePath,
|
|
137
194
|
// define doctype to avoid self-closing tags on wrong places
|
|
138
195
|
doctype: "html",
|
|
139
196
|
// pretty output in dev keeps the "Show code" view readable without Biome
|
|
140
|
-
pretty: mode === "development"
|
|
197
|
+
pretty: mode === "development",
|
|
198
|
+
// pug defaults this to true, which wraps the generated function in per-line try/catch +
|
|
199
|
+
// line-mapping — measurably bloating codegen and `new Function`. We surface compile errors via
|
|
200
|
+
// our own overlay, so the precise pug line in a runtime stack isn't worth the cost.
|
|
201
|
+
compileDebug: false,
|
|
202
|
+
plugins: [{ read: timedRead }]
|
|
141
203
|
});
|
|
204
|
+
const includeReads = includeReadMs - includeReadBefore;
|
|
205
|
+
const parseMs = performance.now() - tParse0 - includeReads;
|
|
206
|
+
readMs += includeReads;
|
|
142
207
|
const dependencies = [path.resolve(pugFilePath), ...pugFn.dependencies.map((dep) => path.resolve(dep))];
|
|
208
|
+
const tRender0 = performance.now();
|
|
143
209
|
const html = pugFn({ ...extraLocals, useId: createUseId(sectionId) });
|
|
144
|
-
|
|
210
|
+
const renderMs = performance.now() - tRender0;
|
|
211
|
+
return { html, dependencies, readMs, parseMs, renderMs };
|
|
145
212
|
}
|
|
146
213
|
async function expandVitePugTags(contentDir, mode, html, sectionId) {
|
|
147
214
|
const vitePugTags = html.match(INSERT_VITE_PUG_TAG_RE);
|
|
148
215
|
if (!vitePugTags) {
|
|
149
|
-
return { html, dependencies: [] };
|
|
216
|
+
return { html, dependencies: [], timings: { read: 0, parse: 0, render: 0, a11y: 0 } };
|
|
150
217
|
}
|
|
151
218
|
let markupOutput = html;
|
|
152
219
|
const dependencies = [];
|
|
220
|
+
let read = 0;
|
|
221
|
+
let parse = 0;
|
|
222
|
+
let render = 0;
|
|
153
223
|
await Promise.all(vitePugTags.map(async (vitePugTag) => {
|
|
154
224
|
const pugSourcePath = vitePugTag.match(PUG_SRC_RE)?.[1];
|
|
155
225
|
if (!pugSourcePath) {
|
|
@@ -162,35 +232,51 @@ async function expandVitePugTags(contentDir, mode, html, sectionId) {
|
|
|
162
232
|
const pugModifierClass = vitePugTag.match(PUG_MODIFIER_CLASS_RE);
|
|
163
233
|
const pugLocals = pugModifierClass && pugModifierClass[1] ? { modifierClass: pugModifierClass[1] } : {};
|
|
164
234
|
const pugFilePath = path.join(contentDir, pugSourcePath);
|
|
165
|
-
const { html: pugOutput, dependencies: pugDependencies } = compilePugFile(pugFilePath, mode, sectionId, pugLocals);
|
|
235
|
+
const { html: pugOutput, dependencies: pugDependencies, readMs, parseMs, renderMs } = compilePugFile(pugFilePath, mode, sectionId, pugLocals);
|
|
166
236
|
dependencies.push(...pugDependencies);
|
|
237
|
+
read += readMs;
|
|
238
|
+
parse += parseMs;
|
|
239
|
+
render += renderMs;
|
|
167
240
|
markupOutput = markupOutput.replaceAll(vitePugTag, pugOutput);
|
|
168
241
|
}));
|
|
169
|
-
return { html: markupOutput, dependencies };
|
|
242
|
+
return { html: markupOutput, dependencies, timings: { read, parse, render, a11y: 0 } };
|
|
170
243
|
}
|
|
171
244
|
async function compileMarkup(contentDir, mode, html, sectionId) {
|
|
172
245
|
let result = html;
|
|
173
246
|
const dependencies = [];
|
|
247
|
+
let read = 0;
|
|
248
|
+
let parse = 0;
|
|
249
|
+
let render = 0;
|
|
174
250
|
const trimmed = html.trim();
|
|
175
251
|
const isBarePath = !trimmed.includes("<") && !trimmed.includes("\n");
|
|
176
252
|
if (isBarePath && trimmed.endsWith(".html")) {
|
|
177
253
|
const htmlFilePath = path.join(contentDir, trimmed);
|
|
254
|
+
const t0 = performance.now();
|
|
178
255
|
result = await fs.readFile(htmlFilePath, "utf-8");
|
|
256
|
+
read += performance.now() - t0;
|
|
179
257
|
dependencies.push(path.resolve(htmlFilePath));
|
|
180
258
|
} else if (isBarePath && trimmed.endsWith(".pug")) {
|
|
181
259
|
const pugFilePath = path.join(contentDir, trimmed);
|
|
182
260
|
const compiled = compilePugFile(pugFilePath, mode, sectionId);
|
|
183
261
|
result = compiled.html;
|
|
184
262
|
dependencies.push(...compiled.dependencies);
|
|
263
|
+
read += compiled.readMs;
|
|
264
|
+
parse += compiled.parseMs;
|
|
265
|
+
render += compiled.renderMs;
|
|
185
266
|
}
|
|
186
267
|
const expanded = await expandVitePugTags(contentDir, mode, result, sectionId);
|
|
187
268
|
result = expanded.html;
|
|
188
269
|
dependencies.push(...expanded.dependencies);
|
|
270
|
+
read += expanded.timings.read;
|
|
271
|
+
parse += expanded.timings.parse;
|
|
272
|
+
render += expanded.timings.render;
|
|
189
273
|
if (mode === "production") {
|
|
190
274
|
result = await biomeFormat(result);
|
|
191
275
|
}
|
|
276
|
+
const tA11y = performance.now();
|
|
192
277
|
result = fixAccessibilityIssues(result);
|
|
193
|
-
|
|
278
|
+
const a11y = performance.now() - tA11y;
|
|
279
|
+
return { html: result, dependencies: [...new Set(dependencies)], timings: { read, parse, render, a11y } };
|
|
194
280
|
}
|
|
195
281
|
|
|
196
|
-
export { INSERT_VITE_PUG_TAG_RE as I, PUG_SRC_RE as P,
|
|
282
|
+
export { INSERT_VITE_PUG_TAG_RE as I, PUG_SRC_RE as P, PUG_ERROR_OVERLAY_TAG as a, sectionSanitizeId as b, compileMarkup as c, stripPugErrorOverlay as d, ensureStartingSlash as e, createLogger as f, generateId as g, logger as l, pugErrorFile as p, replaceWrapperContent as r, sanitizeSpecialCharacters as s };
|