kss-modern 1.2.0-beta.3 → 1.2.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,10 @@
1
1
  import path from 'node:path';
2
- import { performance } from 'node:perf_hooks';
3
2
  import process from 'node:process';
4
3
  import { fileURLToPath } from 'node:url';
5
4
  import fs from 'fs-extra';
6
5
  import { glob } from 'tinyglobby';
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';
6
+ 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.D8n3gEE1.mjs';
7
+ export { f as createLogger } from '../shared/kss-modern.D8n3gEE1.mjs';
9
8
  import htmlLang from '@shikijs/langs/html';
10
9
  import markdownLang from '@shikijs/langs/markdown';
11
10
  import scssLang from '@shikijs/langs/scss';
@@ -1037,17 +1036,6 @@ const graph = new PugDependencyGraph();
1037
1036
  function getPugDependencyGraph() {
1038
1037
  return graph;
1039
1038
  }
1040
- let lastCompileTimings = { read: 0, parse: 0, render: 0, a11y: 0, sections: 0 };
1041
- function accumulateTimings(timings) {
1042
- lastCompileTimings.read += timings.read;
1043
- lastCompileTimings.parse += timings.parse;
1044
- lastCompileTimings.render += timings.render;
1045
- lastCompileTimings.a11y += timings.a11y;
1046
- lastCompileTimings.sections += 1;
1047
- }
1048
- function getLastCompileTimings() {
1049
- return lastCompileTimings;
1050
- }
1051
1039
  const __filename$1 = fileURLToPath(import.meta.url);
1052
1040
  const __dirname$1 = path.dirname(__filename$1);
1053
1041
  const workerFilePath = __dirname$1.includes("dist/") ? "./pug/worker.mjs" : "./worker.ts";
@@ -1114,9 +1102,6 @@ function runPinned(id, input) {
1114
1102
  });
1115
1103
  return run;
1116
1104
  }
1117
- function getPugPoolInfo() {
1118
- return { cpus: os.cpus().length, maxPoolSize: MAX_POOL_SIZE, workers: allWorkers.size };
1119
- }
1120
1105
  async function terminatePugWorkers() {
1121
1106
  const workers = [...allWorkers];
1122
1107
  allWorkers.clear();
@@ -1147,9 +1132,8 @@ function recordFailure(mode, repository, errors, pugError) {
1147
1132
  async function compileInline(mode, contentDir, repository, id, errors) {
1148
1133
  const markupSource = repository.get(id).markup;
1149
1134
  try {
1150
- const { html, dependencies, timings } = await compileMarkup(contentDir, mode, markupSource, id);
1135
+ const { html, dependencies } = await compileMarkup(contentDir, mode, markupSource, id);
1151
1136
  repository.set(id, { markup: html });
1152
- accumulateTimings(timings);
1153
1137
  await storeResult(id, markupSource, html, dependencies);
1154
1138
  } catch (error) {
1155
1139
  const message = error instanceof Error ? error.message : String(error);
@@ -1177,7 +1161,6 @@ async function compileViaWorkerPool(mode, contentDir, repository, ids, errors) {
1177
1161
  return;
1178
1162
  }
1179
1163
  repository.set(id, { markup: result.html });
1180
- accumulateTimings(result.timings);
1181
1164
  await storeResult(id, markupSource, result.html, result.dependencies);
1182
1165
  });
1183
1166
  await Promise.all(tasks);
@@ -1202,7 +1185,6 @@ async function compileIds(mode, contentDir, repository, ids) {
1202
1185
  if (misses.length === 0)
1203
1186
  return clonedRepository;
1204
1187
  const errors = [];
1205
- lastCompileTimings = { read: 0, parse: 0, render: 0, a11y: 0, sections: 0 };
1206
1188
  const useInline = mode === "development" && misses.length <= INLINE_THRESHOLD;
1207
1189
  if (useInline) {
1208
1190
  await Promise.all(misses.map((id) => compileInline(mode, contentDir, clonedRepository, id, errors)));
@@ -1227,6 +1209,13 @@ async function compilePugMarkupIncremental(mode, contentDir, repository, ids) {
1227
1209
  return compileIds(mode, contentDir, repository, wanted);
1228
1210
  }
1229
1211
 
1212
+ const TRANSIENT_FS_ERROR_CODES = /* @__PURE__ */ new Set(["ENOENT", "EBUSY", "EPERM", "EACCES"]);
1213
+ function isTransientFsError(error) {
1214
+ if (typeof error !== "object" || error === null)
1215
+ return false;
1216
+ const { code } = error;
1217
+ return code !== void 0 && TRANSIENT_FS_ERROR_CODES.has(code);
1218
+ }
1230
1219
  async function logicalWriteFile(filepath, content) {
1231
1220
  const dir = path.dirname(filepath);
1232
1221
  await fs.ensureDir(dir);
@@ -2296,13 +2285,25 @@ function matchArraysEqual(a, b) {
2296
2285
  return a.every((value, index) => value === b[index]);
2297
2286
  }
2298
2287
  const kssSectionRegex = /\/\*{1,2}[\s\S]*?Styleguide[\s\S]*?\*\//g;
2288
+ function tryReadFileSync(filePath) {
2289
+ try {
2290
+ return readFileSync(filePath, "utf8");
2291
+ } catch (error) {
2292
+ if (isTransientFsError(error))
2293
+ return void 0;
2294
+ throw error;
2295
+ }
2296
+ }
2299
2297
  function watchStyleguideForChanges(watchPath, handlers) {
2300
2298
  if (typeof handlers.onStructuralChange !== "function" || typeof handlers.onMarkupChange !== "function") {
2301
2299
  throw new TypeError("styleguide watch requires onStructuralChange and onMarkupChange callbacks");
2302
2300
  }
2303
2301
  const regexFileContents = /* @__PURE__ */ new Map();
2304
2302
  const handleCssAdd = (filePath) => {
2305
- const currentFileMatches = readFileSync(filePath, "utf8").match(kssSectionRegex);
2303
+ const contents = tryReadFileSync(filePath);
2304
+ if (contents === void 0)
2305
+ return;
2306
+ const currentFileMatches = contents.match(kssSectionRegex);
2306
2307
  if (currentFileMatches === null) {
2307
2308
  return;
2308
2309
  }
@@ -2312,7 +2313,10 @@ function watchStyleguideForChanges(watchPath, handlers) {
2312
2313
  const handleCssChange = (filePath) => {
2313
2314
  const previousFileMatches = regexFileContents.get(filePath);
2314
2315
  const hasFileBeenReadBefore = previousFileMatches !== void 0;
2315
- const currentFileMatches = readFileSync(filePath, "utf8").match(kssSectionRegex);
2316
+ const contents = tryReadFileSync(filePath);
2317
+ if (contents === void 0)
2318
+ return;
2319
+ const currentFileMatches = contents.match(kssSectionRegex);
2316
2320
  if (!hasFileBeenReadBefore) {
2317
2321
  regexFileContents.set(filePath, currentFileMatches);
2318
2322
  if (currentFileMatches === null) {
@@ -2643,21 +2647,17 @@ async function rebuildSections(config, context, changedSectionIds) {
2643
2647
  }
2644
2648
  if (subset.size === 0)
2645
2649
  return;
2646
- const startedAt = performance.now();
2647
- const workersBefore = getPugPoolInfo().workers;
2648
2650
  const recompiled = await compilePugMarkupIncremental(config.mode, config.contentDir, subset, subset.keys());
2649
2651
  for (const [id, entry] of recompiled) {
2650
2652
  context.compiledRepository.set(id, { markup: entry.markup });
2651
2653
  reindexInsertMarkupConsumer(context, id);
2652
2654
  }
2653
- const afterCompile = performance.now();
2654
2655
  const resolved = resolveInsertMarkupForSections(context.compiledRepository, context.sectionsById, affected);
2655
2656
  for (const [id, markup] of resolved) {
2656
2657
  const node = context.nodeById.get(id);
2657
2658
  if (node)
2658
2659
  node.markup = markup;
2659
2660
  }
2660
- const afterResolve = performance.now();
2661
2661
  const writeTasks = [];
2662
2662
  const previewsToWrite = /* @__PURE__ */ new Set();
2663
2663
  for (const id of affected) {
@@ -2675,16 +2675,6 @@ async function rebuildSections(config, context, changedSectionIds) {
2675
2675
  writeTasks.push(writePreviewFile(config, context, firstLevelIndex, secondLevelIndex));
2676
2676
  }
2677
2677
  await Promise.all(writeTasks);
2678
- const afterWrite = performance.now();
2679
- if (config.mode === "development") {
2680
- const ms = (value) => `${value.toFixed(1)}ms`;
2681
- const pool = getPugPoolInfo();
2682
- const spawned = pool.workers - workersBefore;
2683
- const t = getLastCompileTimings();
2684
- logger.info(
2685
- `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)`
2686
- );
2687
- }
2688
2678
  }
2689
2679
  async function watchStyleguide(config, onChange, onError) {
2690
2680
  const initialBuild = await buildAll(config);
@@ -1,17 +1,6 @@
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
- }
15
4
 
16
5
  interface PugWorkerInput {
17
6
  id: string;
@@ -23,7 +12,6 @@ interface PugWorkerSuccess {
23
12
  id: string;
24
13
  html: string;
25
14
  dependencies: string[];
26
- timings: CompileTimings;
27
15
  }
28
16
  interface PugWorkerError {
29
17
  id: string;
@@ -1,17 +1,6 @@
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
- }
15
4
 
16
5
  interface PugWorkerInput {
17
6
  id: string;
@@ -23,7 +12,6 @@ interface PugWorkerSuccess {
23
12
  id: string;
24
13
  html: string;
25
14
  dependencies: string[];
26
- timings: CompileTimings;
27
15
  }
28
16
  interface PugWorkerError {
29
17
  id: string;
@@ -1,9 +1,8 @@
1
1
  import { parentPort } from 'node:worker_threads';
2
- import { c as compileMarkup, p as pugErrorFile } from '../../shared/kss-modern.o1Fp758z.mjs';
2
+ import { c as compileMarkup, p as pugErrorFile } from '../../shared/kss-modern.D8n3gEE1.mjs';
3
3
  import 'node:fs';
4
4
  import 'node:fs/promises';
5
5
  import 'node:path';
6
- import 'node:perf_hooks';
7
6
  import 'pug';
8
7
  import 'consola';
9
8
  import 'consola/utils';
@@ -15,8 +14,8 @@ if (!parentPort) {
15
14
  parentPort.on("message", async (data) => {
16
15
  const { id, mode, html, contentDir } = data;
17
16
  try {
18
- const { html: compiled, dependencies, timings } = await compileMarkup(contentDir, mode, html, id);
19
- parentPort.postMessage({ id, html: compiled, dependencies, timings });
17
+ const { html: compiled, dependencies } = await compileMarkup(contentDir, mode, html, id);
18
+ parentPort.postMessage({ id, html: compiled, dependencies });
20
19
  } catch (error) {
21
20
  const message = error instanceof Error ? error.message : String(error);
22
21
  parentPort.postMessage({ id, error: message, file: pugErrorFile(error) });
@@ -1,7 +1,6 @@
1
1
  import { statSync, readFileSync } from 'node:fs';
2
2
  import fs from 'node:fs/promises';
3
3
  import path from 'node:path';
4
- import { performance } from 'node:perf_hooks';
5
4
  import pug from 'pug';
6
5
  import { createConsola } from 'consola';
7
6
  import { colors } from 'consola/utils';
@@ -176,19 +175,8 @@ function pugErrorFile(error) {
176
175
  const candidate = error;
177
176
  return candidate?.path ?? candidate?.filename;
178
177
  }
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
- }
186
178
  function compilePugFile(pugFilePath, mode, sectionId, extraLocals = {}) {
187
- const tRead0 = performance.now();
188
179
  const source = readFileSync(pugFilePath, "utf8");
189
- let readMs = performance.now() - tRead0;
190
- const includeReadBefore = includeReadMs;
191
- const tParse0 = performance.now();
192
180
  const pugFn = pug.compile(source, {
193
181
  filename: pugFilePath,
194
182
  // define doctype to avoid self-closing tags on wrong places
@@ -198,28 +186,19 @@ function compilePugFile(pugFilePath, mode, sectionId, extraLocals = {}) {
198
186
  // pug defaults this to true, which wraps the generated function in per-line try/catch +
199
187
  // line-mapping — measurably bloating codegen and `new Function`. We surface compile errors via
200
188
  // our own overlay, so the precise pug line in a runtime stack isn't worth the cost.
201
- compileDebug: false,
202
- plugins: [{ read: timedRead }]
189
+ compileDebug: false
203
190
  });
204
- const includeReads = includeReadMs - includeReadBefore;
205
- const parseMs = performance.now() - tParse0 - includeReads;
206
- readMs += includeReads;
207
191
  const dependencies = [path.resolve(pugFilePath), ...pugFn.dependencies.map((dep) => path.resolve(dep))];
208
- const tRender0 = performance.now();
209
192
  const html = pugFn({ ...extraLocals, useId: createUseId(sectionId) });
210
- const renderMs = performance.now() - tRender0;
211
- return { html, dependencies, readMs, parseMs, renderMs };
193
+ return { html, dependencies };
212
194
  }
213
195
  async function expandVitePugTags(contentDir, mode, html, sectionId) {
214
196
  const vitePugTags = html.match(INSERT_VITE_PUG_TAG_RE);
215
197
  if (!vitePugTags) {
216
- return { html, dependencies: [], timings: { read: 0, parse: 0, render: 0, a11y: 0 } };
198
+ return { html, dependencies: [] };
217
199
  }
218
200
  let markupOutput = html;
219
201
  const dependencies = [];
220
- let read = 0;
221
- let parse = 0;
222
- let render = 0;
223
202
  await Promise.all(vitePugTags.map(async (vitePugTag) => {
224
203
  const pugSourcePath = vitePugTag.match(PUG_SRC_RE)?.[1];
225
204
  if (!pugSourcePath) {
@@ -232,51 +211,35 @@ async function expandVitePugTags(contentDir, mode, html, sectionId) {
232
211
  const pugModifierClass = vitePugTag.match(PUG_MODIFIER_CLASS_RE);
233
212
  const pugLocals = pugModifierClass && pugModifierClass[1] ? { modifierClass: pugModifierClass[1] } : {};
234
213
  const pugFilePath = path.join(contentDir, pugSourcePath);
235
- const { html: pugOutput, dependencies: pugDependencies, readMs, parseMs, renderMs } = compilePugFile(pugFilePath, mode, sectionId, pugLocals);
214
+ const { html: pugOutput, dependencies: pugDependencies } = compilePugFile(pugFilePath, mode, sectionId, pugLocals);
236
215
  dependencies.push(...pugDependencies);
237
- read += readMs;
238
- parse += parseMs;
239
- render += renderMs;
240
216
  markupOutput = markupOutput.replaceAll(vitePugTag, pugOutput);
241
217
  }));
242
- return { html: markupOutput, dependencies, timings: { read, parse, render, a11y: 0 } };
218
+ return { html: markupOutput, dependencies };
243
219
  }
244
220
  async function compileMarkup(contentDir, mode, html, sectionId) {
245
221
  let result = html;
246
222
  const dependencies = [];
247
- let read = 0;
248
- let parse = 0;
249
- let render = 0;
250
223
  const trimmed = html.trim();
251
224
  const isBarePath = !trimmed.includes("<") && !trimmed.includes("\n");
252
225
  if (isBarePath && trimmed.endsWith(".html")) {
253
226
  const htmlFilePath = path.join(contentDir, trimmed);
254
- const t0 = performance.now();
255
227
  result = await fs.readFile(htmlFilePath, "utf-8");
256
- read += performance.now() - t0;
257
228
  dependencies.push(path.resolve(htmlFilePath));
258
229
  } else if (isBarePath && trimmed.endsWith(".pug")) {
259
230
  const pugFilePath = path.join(contentDir, trimmed);
260
231
  const compiled = compilePugFile(pugFilePath, mode, sectionId);
261
232
  result = compiled.html;
262
233
  dependencies.push(...compiled.dependencies);
263
- read += compiled.readMs;
264
- parse += compiled.parseMs;
265
- render += compiled.renderMs;
266
234
  }
267
235
  const expanded = await expandVitePugTags(contentDir, mode, result, sectionId);
268
236
  result = expanded.html;
269
237
  dependencies.push(...expanded.dependencies);
270
- read += expanded.timings.read;
271
- parse += expanded.timings.parse;
272
- render += expanded.timings.render;
273
238
  if (mode === "production") {
274
239
  result = await biomeFormat(result);
275
240
  }
276
- const tA11y = performance.now();
277
241
  result = fixAccessibilityIssues(result);
278
- const a11y = performance.now() - tA11y;
279
- return { html: result, dependencies: [...new Set(dependencies)], timings: { read, parse, render, a11y } };
242
+ return { html: result, dependencies: [...new Set(dependencies)] };
280
243
  }
281
244
 
282
245
  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 };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kss-modern",
3
3
  "type": "module",
4
- "version": "1.2.0-beta.3",
4
+ "version": "1.2.0-beta.5",
5
5
  "description": "Modern KSS compatible styleguide generator",
6
6
  "keywords": [
7
7
  "kss",