@stati/core 1.19.0 → 1.20.1

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.
Files changed (46) hide show
  1. package/dist/core/build.d.ts.map +1 -1
  2. package/dist/core/build.js +51 -7
  3. package/dist/core/dev.d.ts.map +1 -1
  4. package/dist/core/dev.js +17 -10
  5. package/dist/core/index.d.ts +1 -0
  6. package/dist/core/index.d.ts.map +1 -1
  7. package/dist/core/index.js +2 -0
  8. package/dist/core/markdown.d.ts +9 -0
  9. package/dist/core/markdown.d.ts.map +1 -1
  10. package/dist/core/markdown.js +12 -0
  11. package/dist/core/utils/html.utils.d.ts +35 -0
  12. package/dist/core/utils/html.utils.d.ts.map +1 -0
  13. package/dist/core/utils/html.utils.js +46 -0
  14. package/dist/core/utils/index.d.ts +2 -1
  15. package/dist/core/utils/index.d.ts.map +1 -1
  16. package/dist/core/utils/index.js +3 -1
  17. package/dist/core/utils/paths.utils.d.ts +27 -0
  18. package/dist/core/utils/paths.utils.d.ts.map +1 -1
  19. package/dist/core/utils/paths.utils.js +45 -0
  20. package/dist/metrics/recorder.d.ts.map +1 -1
  21. package/dist/metrics/types.d.ts +1 -0
  22. package/dist/metrics/types.d.ts.map +1 -1
  23. package/dist/search/auto-inject.d.ts +21 -0
  24. package/dist/search/auto-inject.d.ts.map +1 -0
  25. package/dist/search/auto-inject.js +33 -0
  26. package/dist/search/constants.d.ts +28 -0
  27. package/dist/search/constants.d.ts.map +1 -0
  28. package/dist/search/constants.js +27 -0
  29. package/dist/search/generator.d.ts +101 -0
  30. package/dist/search/generator.d.ts.map +1 -0
  31. package/dist/search/generator.js +278 -0
  32. package/dist/search/index.d.ts +24 -0
  33. package/dist/search/index.d.ts.map +1 -0
  34. package/dist/search/index.js +22 -0
  35. package/dist/seo/auto-inject.d.ts.map +1 -1
  36. package/dist/seo/auto-inject.js +5 -18
  37. package/dist/types/config.d.ts +3 -0
  38. package/dist/types/config.d.ts.map +1 -1
  39. package/dist/types/content.d.ts +6 -0
  40. package/dist/types/content.d.ts.map +1 -1
  41. package/dist/types/index.d.ts +1 -0
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/dist/types/search.d.ts +121 -0
  44. package/dist/types/search.d.ts.map +1 -0
  45. package/dist/types/search.js +5 -0
  46. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAgDA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAMP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8BAA8B;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,iCAAiC;IACjC,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,wDAAwD;IACxD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAW5E"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/core/build.ts"],"names":[],"mappings":"AAsDA,OAAO,KAAK,EAEV,UAAU,EACV,MAAM,EAQP,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,iDAAiD;IACjD,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,uCAAuC;IACvC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8BAA8B;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+BAA+B;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,iCAAiC;IACjC,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,wDAAwD;IACxD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AA4FD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC,CAW5E"}
@@ -3,12 +3,13 @@ import { join, dirname, relative, posix } from 'node:path';
3
3
  import { performance } from 'node:perf_hooks';
4
4
  import { loadConfig } from '../config/loader.js';
5
5
  import { loadContent } from './content.js';
6
- import { createMarkdownProcessor, renderMarkdown } from './markdown.js';
6
+ import { createMarkdownProcessor, renderMarkdown, extractToc } from './markdown.js';
7
7
  import { createTemplateEngine, renderPage } from './templates.js';
8
8
  import { buildNavigation } from './navigation.js';
9
9
  import { loadCacheManifest, saveCacheManifest, shouldRebuildPage, createCacheEntry, updateCacheEntry, withBuildLock, computeNavigationHash, } from './isg/index.js';
10
10
  import { generateSitemap, generateRobotsTxtFromConfig, autoInjectSEO, } from '../seo/index.js';
11
11
  import { generateRSSFeeds, validateRSSConfig } from '../rss/index.js';
12
+ import { computeSearchIndexFilename, generateSearchIndex, writeSearchIndex, autoInjectSearchMeta, } from '../search/index.js';
12
13
  import { getEnv } from '../env.js';
13
14
  import { DEFAULT_OUT_DIR } from '../constants.js';
14
15
  import { createMetricRecorder, noopMetricRecorder } from '../metrics/index.js';
@@ -190,9 +191,10 @@ async function loadContentAndBuildNavigation(config, options, logger) {
190
191
  /**
191
192
  * Processes pages with ISG caching logic.
192
193
  */
193
- async function processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles, recorder = noopMetricRecorder) {
194
+ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles, recorder = noopMetricRecorder, searchIndexFilename) {
194
195
  let cacheHits = 0;
195
196
  let cacheMisses = 0;
197
+ const searchablePages = [];
196
198
  // Build context
197
199
  const buildContext = { config, pages };
198
200
  // Run beforeAll hook
@@ -249,6 +251,13 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
249
251
  }
250
252
  // Record page timing for cached pages (0ms render time)
251
253
  recorder.recordPageTiming(page.url, 0, true);
254
+ // Collect searchable page data for cached pages if search is enabled
255
+ // Extract TOC without full HTML rendering for efficiency
256
+ if (config.search?.enabled === true) {
257
+ const tocEnabled = config.markdown?.toc !== false;
258
+ const toc = tocEnabled ? extractToc(page.content, md) : [];
259
+ searchablePages.push({ page, toc, markdownContent: page.content });
260
+ }
252
261
  continue;
253
262
  }
254
263
  // Cache miss - need to rebuild
@@ -265,7 +274,14 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
265
274
  const { html: htmlContent, toc } = renderMarkdown(page.content, md, tocEnabled);
266
275
  // Compute matched bundle paths for this page
267
276
  const bundlePaths = getBundlePathsForPage(page.url, compiledBundles);
268
- const assets = bundlePaths.length > 0 ? { bundlePaths } : undefined;
277
+ // Build assets object with bundle paths and search index path
278
+ const assets = {
279
+ bundlePaths,
280
+ ...(config.search?.enabled === true &&
281
+ searchIndexFilename && {
282
+ searchIndexPath: `/${searchIndexFilename}`,
283
+ }),
284
+ };
269
285
  // Render with template
270
286
  const renderResult = await renderPage(page, htmlContent, config, eta, navigation, pages, assets, toc, logger);
271
287
  let finalHtml = renderResult.html;
@@ -284,9 +300,14 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
284
300
  }
285
301
  finalHtml = autoInjectSEO(finalHtml, injectOptions);
286
302
  }
303
+ // Auto-inject search index meta tag if enabled (default: true)
304
+ if (config.search?.enabled === true &&
305
+ searchIndexFilename &&
306
+ config.search?.autoInjectMetaTag !== false) {
307
+ finalHtml = autoInjectSearchMeta(finalHtml, `/${searchIndexFilename}`);
308
+ }
287
309
  // Auto-inject TypeScript bundle script tags if available and autoInject is enabled (default: true)
288
- const shouldAutoInject = config.typescript?.autoInject !== false;
289
- if (shouldAutoInject && assets && assets.bundlePaths.length > 0) {
310
+ if (config.typescript?.autoInject !== false && assets.bundlePaths.length > 0) {
290
311
  finalHtml = autoInjectBundles(finalHtml, assets.bundlePaths);
291
312
  }
292
313
  const renderTime = Math.round(performance.now() - startTime);
@@ -308,6 +329,11 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
308
329
  else {
309
330
  manifest.entries[cacheKey] = await createCacheEntry(page, config, buildTime);
310
331
  }
332
+ // Collect searchable page data if search is enabled
333
+ // Uses TOC entries and markdown content instead of parsing rendered HTML
334
+ if (config.search?.enabled === true) {
335
+ searchablePages.push({ page, toc, markdownContent: page.content });
336
+ }
311
337
  // Run afterRender hook
312
338
  if (config.hooks?.afterRender) {
313
339
  const hookStart = performance.now();
@@ -322,7 +348,7 @@ async function processPagesWithCache(pages, manifest, config, outDir, md, eta, n
322
348
  logger.clearRenderingTree();
323
349
  }
324
350
  }
325
- return { cacheHits, cacheMisses };
351
+ return { cacheHits, cacheMisses, searchablePages };
326
352
  }
327
353
  /**
328
354
  * Copies static assets and returns the count.
@@ -453,16 +479,34 @@ async function buildInternal(options = {}) {
453
479
  });
454
480
  endTsSpan();
455
481
  }
482
+ // Pre-compute search index filename if search is enabled
483
+ let searchIndexFilename;
484
+ if (config.search?.enabled) {
485
+ searchIndexFilename = computeSearchIndexFilename(config.search, buildStartTime.toString());
486
+ }
456
487
  // Process pages with ISG caching logic
457
488
  if (logger.step) {
458
489
  console.log(); // Add spacing before page processing
459
490
  }
460
491
  const endPageRenderSpan = recorder.startSpan('pageRenderingMs');
461
492
  const buildTime = new Date();
462
- const pageProcessingResult = await processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles, recorder);
493
+ const pageProcessingResult = await processPagesWithCache(pages, manifest, config, outDir, md, eta, navigation, buildTime, options, logger, compiledBundles, recorder, searchIndexFilename);
463
494
  endPageRenderSpan();
464
495
  cacheHits = pageProcessingResult.cacheHits;
465
496
  cacheMisses = pageProcessingResult.cacheMisses;
497
+ const searchablePages = pageProcessingResult.searchablePages;
498
+ // Generate search index if enabled
499
+ // Uses markdown content and TOC entries
500
+ let searchIndexMetadata;
501
+ if (config.search?.enabled && searchablePages.length > 0 && searchIndexFilename) {
502
+ logger.info('');
503
+ logger.info(`Generating search index to ${searchIndexFilename}`);
504
+ const endSearchIndexSpan = recorder.startSpan('searchIndexGenerationMs');
505
+ const searchIndex = generateSearchIndex(searchablePages, config.search);
506
+ searchIndexMetadata = await writeSearchIndex(searchIndex, outDir, searchIndexFilename);
507
+ endSearchIndexSpan();
508
+ logger.success(`Generated search index with ${searchIndexMetadata.documentCount} documents`);
509
+ }
466
510
  // Record page rendering counts
467
511
  recorder.increment('renderedPages', cacheMisses);
468
512
  recorder.increment('cachedPages', cacheHits);
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA2B7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAiXD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAudxF"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/core/dev.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAe,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA4B7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAuXD,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,SAAS,CAAC,CAudxF"}
package/dist/core/dev.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createServer } from 'node:http';
2
- import { join, extname, posix } from 'node:path';
2
+ import { join, extname } from 'node:path';
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { WebSocketServer } from 'ws';
5
5
  import chokidar from 'chokidar';
@@ -9,7 +9,7 @@ import { loadConfig } from '../config/loader.js';
9
9
  import { loadCacheManifest, saveCacheManifest, computeNavigationHash } from './isg/index.js';
10
10
  import { loadContent } from './content.js';
11
11
  import { buildNavigation } from './navigation.js';
12
- import { resolveDevPaths, resolveCacheDir, resolvePrettyUrl, createErrorOverlay, parseErrorDetails, TemplateError, createFallbackLogger, mergeServerOptions, createTypeScriptWatcher, } from './utils/index.js';
12
+ import { resolveDevPaths, resolveCacheDir, resolvePrettyUrl, createErrorOverlay, parseErrorDetails, TemplateError, createFallbackLogger, mergeServerOptions, createTypeScriptWatcher, normalizePathForComparison, } from './utils/index.js';
13
13
  import { setEnv, getEnv } from '../env.js';
14
14
  import { DEFAULT_DEV_PORT, DEFAULT_DEV_HOST, TEMPLATE_EXTENSION, DEFAULT_OUT_DIR, } from '../constants.js';
15
15
  /**
@@ -180,7 +180,9 @@ async function performIncrementalRebuild(changedPath, eventType, configPath, sta
180
180
  }
181
181
  }
182
182
  /**
183
- * Handles template/partial file changes by invalidating affected pages
183
+ * Handles template/partial file changes by invalidating affected pages.
184
+ * Uses proper path normalization to ensure reliable matching between
185
+ * file watcher paths and cached dependency paths.
184
186
  */
185
187
  async function handleTemplateChange(templatePath, configPath, logger) {
186
188
  const cacheDir = resolveCacheDir();
@@ -197,16 +199,21 @@ async function handleTemplateChange(templatePath, configPath, logger) {
197
199
  });
198
200
  return;
199
201
  }
202
+ // Normalize the changed template path to absolute POSIX format for reliable comparison
203
+ // This handles cases where the watcher provides relative paths, Windows paths, or different
204
+ // path representations than what's stored in the cache manifest
205
+ const normalizedTemplatePath = normalizePathForComparison(templatePath);
200
206
  // Find pages that depend on this template
201
207
  let affectedPagesCount = 0;
202
- const normalizedTemplatePath = posix.normalize(templatePath.replace(/\\/g, '/'));
203
208
  for (const [pagePath, entry] of Object.entries(cacheManifest.entries)) {
204
- if (entry.deps.some((dep) => {
205
- const normalizedDep = posix.normalize(dep.replace(/\\/g, '/'));
206
- // Use endsWith for more precise matching to avoid false positives
207
- return (normalizedDep === normalizedTemplatePath ||
208
- normalizedDep.endsWith('/' + normalizedTemplatePath));
209
- })) {
209
+ // Check if any of the page's dependencies match the changed template
210
+ const hasMatchingDep = entry.deps.some((dep) => {
211
+ // Normalize the cached dependency path to the same format
212
+ const normalizedDep = normalizePathForComparison(dep);
213
+ // Direct path comparison - both paths are now in consistent format
214
+ return normalizedDep === normalizedTemplatePath;
215
+ });
216
+ if (hasMatchingDep) {
210
217
  affectedPagesCount++;
211
218
  // Remove from cache to force rebuild
212
219
  delete cacheManifest.entries[pagePath];
@@ -10,4 +10,5 @@ export { createPreviewServer } from './preview.js';
10
10
  export type { PreviewServerOptions } from './preview.js';
11
11
  export { invalidate } from './invalidate.js';
12
12
  export type { InvalidationResult } from './invalidate.js';
13
+ export { injectBeforeHeadClose, findHeadClosePosition } from './utils/index.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG5E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG5E,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -10,3 +10,5 @@ export { createDevServer } from './dev.js';
10
10
  export { createPreviewServer } from './preview.js';
11
11
  // Cache invalidation
12
12
  export { invalidate } from './invalidate.js';
13
+ // HTML utilities
14
+ export { injectBeforeHeadClose, findHeadClosePosition } from './utils/index.js';
@@ -14,6 +14,15 @@ export interface MarkdownResult {
14
14
  * Supports both plugin array format and configure function format.
15
15
  */
16
16
  export declare function createMarkdownProcessor(config: StatiConfig): Promise<MarkdownIt>;
17
+ /**
18
+ * Extracts table of contents entries from markdown content without rendering HTML.
19
+ * This is more efficient than renderMarkdown when only TOC data is needed.
20
+ *
21
+ * @param content - The markdown content to extract TOC from
22
+ * @param md - The configured MarkdownIt instance
23
+ * @returns Array of TOC entries extracted from headings (levels 2-6)
24
+ */
25
+ export declare function extractToc(content: string, md: MarkdownIt): TocEntry[];
17
26
  /**
18
27
  * Renders markdown content to HTML with optional TOC extraction.
19
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAKrC,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG/D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB;AAmBD;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuCtF;AA6ED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,UAAU,EACd,UAAU,GAAE,OAAc,GACzB,cAAc,CAWhB"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/core/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAKrC,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG/D;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,GAAG,EAAE,QAAQ,EAAE,CAAC;CACjB;AAmBD;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuCtF;AA6ED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,QAAQ,EAAE,CAGtE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,EAAE,EAAE,UAAU,EACd,UAAU,GAAE,OAAc,GACzB,cAAc,CAWhB"}
@@ -127,6 +127,18 @@ function extractAndInjectAnchors(tokens, tocEnabled) {
127
127
  }
128
128
  return toc;
129
129
  }
130
+ /**
131
+ * Extracts table of contents entries from markdown content without rendering HTML.
132
+ * This is more efficient than renderMarkdown when only TOC data is needed.
133
+ *
134
+ * @param content - The markdown content to extract TOC from
135
+ * @param md - The configured MarkdownIt instance
136
+ * @returns Array of TOC entries extracted from headings (levels 2-6)
137
+ */
138
+ export function extractToc(content, md) {
139
+ const tokens = md.parse(content, {});
140
+ return extractAndInjectAnchors(tokens, true);
141
+ }
130
142
  /**
131
143
  * Renders markdown content to HTML with optional TOC extraction.
132
144
  *
@@ -0,0 +1,35 @@
1
+ /**
2
+ * HTML manipulation utilities.
3
+ * @module core/utils/html
4
+ */
5
+ /**
6
+ * Finds the position to inject content before </head>.
7
+ * Performs a case-insensitive search for the closing head tag.
8
+ *
9
+ * @param html - HTML content
10
+ * @returns Position index or -1 if not found
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const html = '<html><head><title>Test</title></head><body></body></html>';
15
+ * const pos = findHeadClosePosition(html);
16
+ * // pos is the index just before </head>
17
+ * ```
18
+ */
19
+ export declare function findHeadClosePosition(html: string): number;
20
+ /**
21
+ * Injects content before the </head> tag with proper indentation.
22
+ *
23
+ * @param html - HTML content
24
+ * @param content - Content to inject
25
+ * @param indent - Indentation string (default: 4 spaces)
26
+ * @returns HTML with injected content, or original HTML if </head> not found
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const html = '<html><head><title>Test</title></head><body></body></html>';
31
+ * const result = injectBeforeHeadClose(html, '<meta name="test" content="value">');
32
+ * ```
33
+ */
34
+ export declare function injectBeforeHeadClose(html: string, content: string, indent?: string): string;
35
+ //# sourceMappingURL=html.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/html.utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAe,GACtB,MAAM,CAWR"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * HTML manipulation utilities.
3
+ * @module core/utils/html
4
+ */
5
+ /**
6
+ * Finds the position to inject content before </head>.
7
+ * Performs a case-insensitive search for the closing head tag.
8
+ *
9
+ * @param html - HTML content
10
+ * @returns Position index or -1 if not found
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const html = '<html><head><title>Test</title></head><body></body></html>';
15
+ * const pos = findHeadClosePosition(html);
16
+ * // pos is the index just before </head>
17
+ * ```
18
+ */
19
+ export function findHeadClosePosition(html) {
20
+ // Case-insensitive search for </head>
21
+ const match = html.match(/<\/head>/i);
22
+ return match ? (match.index ?? -1) : -1;
23
+ }
24
+ /**
25
+ * Injects content before the </head> tag with proper indentation.
26
+ *
27
+ * @param html - HTML content
28
+ * @param content - Content to inject
29
+ * @param indent - Indentation string (default: 4 spaces)
30
+ * @returns HTML with injected content, or original HTML if </head> not found
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const html = '<html><head><title>Test</title></head><body></body></html>';
35
+ * const result = injectBeforeHeadClose(html, '<meta name="test" content="value">');
36
+ * ```
37
+ */
38
+ export function injectBeforeHeadClose(html, content, indent = ' ') {
39
+ const headClosePos = findHeadClosePosition(html);
40
+ if (headClosePos === -1) {
41
+ return html;
42
+ }
43
+ const before = html.substring(0, headClosePos);
44
+ const after = html.substring(headClosePos);
45
+ return `${before}${indent}${content}\n${after}`;
46
+ }
@@ -3,7 +3,7 @@
3
3
  * @module core/utils
4
4
  */
5
5
  export { readFile, writeFile, pathExists, ensureDir, remove, copyFile, readdir, stat, } from './fs.utils.js';
6
- export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolveDevPaths, normalizeTemplatePath, resolveSrcPath, resolveOutPath, resolveStaticPath, } from './paths.utils.js';
6
+ export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolveDevPaths, normalizeTemplatePath, resolveSrcPath, resolveOutPath, resolveStaticPath, normalizePathForComparison, } from './paths.utils.js';
7
7
  export { discoverLayout, isCollectionIndexPage, getCollectionPathForPage, } from './template-discovery.utils.js';
8
8
  export { propValue } from './template.utils.js';
9
9
  export { slugify } from './slugify.utils.js';
@@ -24,4 +24,5 @@ export type { CompiledBundleInfo } from './bundle-matching.utils.js';
24
24
  export { createFallbackLogger } from './logger.utils.js';
25
25
  export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, } from './typescript.utils.js';
26
26
  export type { CompileOptions, WatchOptions } from './typescript.utils.js';
27
+ export { findHeadClosePosition, injectBeforeHeadClose } from './html.utils.js';
27
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,OAAO,EACP,IAAI,GACL,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAG9E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3F,YAAY,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACzE,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACjF,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGpE,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -5,7 +5,7 @@
5
5
  // File system utilities
6
6
  export { readFile, writeFile, pathExists, ensureDir, remove, copyFile, readdir, stat, } from './fs.utils.js';
7
7
  // Path resolution utilities
8
- export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolveDevPaths, normalizeTemplatePath, resolveSrcPath, resolveOutPath, resolveStaticPath, } from './paths.utils.js';
8
+ export { resolveSrcDir, resolveOutDir, resolveStaticDir, resolveCacheDir, resolveDevPaths, normalizeTemplatePath, resolveSrcPath, resolveOutPath, resolveStaticPath, normalizePathForComparison, } from './paths.utils.js';
9
9
  // Template discovery utilities
10
10
  export { discoverLayout, isCollectionIndexPage, getCollectionPathForPage, } from './template-discovery.utils.js';
11
11
  // Template utilities
@@ -36,3 +36,5 @@ export { matchBundlesForPage, getBundlePathsForPage, validateUniqueBundleNames,
36
36
  export { createFallbackLogger } from './logger.utils.js';
37
37
  // TypeScript compilation utilities
38
38
  export { compileTypeScript, createTypeScriptWatcher, compileStatiConfig, cleanupCompiledConfig, autoInjectBundles, } from './typescript.utils.js';
39
+ // HTML manipulation utilities
40
+ export { findHeadClosePosition, injectBeforeHeadClose } from './html.utils.js';
@@ -64,4 +64,31 @@ export declare function resolveOutPath(config: StatiConfig, relativePath: string
64
64
  * @returns Absolute path
65
65
  */
66
66
  export declare function resolveStaticPath(config: StatiConfig, relativePath: string): string;
67
+ /**
68
+ * Normalizes a file path to absolute POSIX format for consistent comparisons.
69
+ * Handles Windows paths, relative paths, and already-normalized paths.
70
+ *
71
+ * This utility ensures that paths from different sources (file watchers, cache manifest,
72
+ * glob results) can be reliably compared even when they use different representations.
73
+ *
74
+ * @param filePath - Path to normalize (can be relative or absolute, Windows or POSIX)
75
+ * @param basePath - Optional base path to resolve relative paths against (defaults to cwd)
76
+ * @returns Normalized absolute path with forward slashes and no trailing slashes
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * // Windows absolute path
81
+ * normalizePathForComparison('C:\\project\\site\\layout.eta')
82
+ * // Returns: 'C:/project/site/layout.eta'
83
+ *
84
+ * // Relative path
85
+ * normalizePathForComparison('site/layout.eta', '/project')
86
+ * // Returns: '/project/site/layout.eta'
87
+ *
88
+ * // Already POSIX path
89
+ * normalizePathForComparison('/project/site/layout.eta')
90
+ * // Returns: '/project/site/layout.eta'
91
+ * ```
92
+ */
93
+ export declare function normalizePathForComparison(filePath: string, basePath?: string): string;
67
94
  //# sourceMappingURL=paths.utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/paths.utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQxD;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW;;;;EAMlD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEnF"}
1
+ {"version":3,"file":"paths.utils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/paths.utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQxD;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAEzD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE5D;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW;;;;EAMlD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAEnF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAuBtF"}
@@ -83,3 +83,48 @@ export function resolveOutPath(config, relativePath) {
83
83
  export function resolveStaticPath(config, relativePath) {
84
84
  return join(resolveStaticDir(config), relativePath);
85
85
  }
86
+ /**
87
+ * Normalizes a file path to absolute POSIX format for consistent comparisons.
88
+ * Handles Windows paths, relative paths, and already-normalized paths.
89
+ *
90
+ * This utility ensures that paths from different sources (file watchers, cache manifest,
91
+ * glob results) can be reliably compared even when they use different representations.
92
+ *
93
+ * @param filePath - Path to normalize (can be relative or absolute, Windows or POSIX)
94
+ * @param basePath - Optional base path to resolve relative paths against (defaults to cwd)
95
+ * @returns Normalized absolute path with forward slashes and no trailing slashes
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * // Windows absolute path
100
+ * normalizePathForComparison('C:\\project\\site\\layout.eta')
101
+ * // Returns: 'C:/project/site/layout.eta'
102
+ *
103
+ * // Relative path
104
+ * normalizePathForComparison('site/layout.eta', '/project')
105
+ * // Returns: '/project/site/layout.eta'
106
+ *
107
+ * // Already POSIX path
108
+ * normalizePathForComparison('/project/site/layout.eta')
109
+ * // Returns: '/project/site/layout.eta'
110
+ * ```
111
+ */
112
+ export function normalizePathForComparison(filePath, basePath) {
113
+ // Convert backslashes to forward slashes for Windows compatibility
114
+ let normalized = filePath.replace(/\\/g, '/');
115
+ // Resolve to absolute path if relative
116
+ // Check if path is already absolute (starts with / or drive letter)
117
+ const isAbsolute = normalized.startsWith('/') || /^[a-zA-Z]:/.test(normalized);
118
+ if (!isAbsolute) {
119
+ const base = basePath || process.cwd();
120
+ // Use the already-normalized path to avoid reintroducing backslashes
121
+ normalized = join(base, normalized).replace(/\\/g, '/');
122
+ }
123
+ // Use posix.normalize to clean up any '..' or '.' segments and remove redundant separators
124
+ normalized = posix.normalize(normalized);
125
+ // Remove trailing slash (except for root path)
126
+ if (normalized.length > 1 && normalized.endsWith('/')) {
127
+ normalized = normalized.slice(0, -1);
128
+ }
129
+ return normalized;
130
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EAQtB,MAAM,YAAY,CAAC;AAoNpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAaxF"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../src/metrics/recorder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EAQtB,MAAM,YAAY,CAAC;AAqNpB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B,GAAG,cAAc,CAaxF"}
@@ -85,6 +85,7 @@ export interface MetricsPhases {
85
85
  readonly cacheManifestLoadMs?: number;
86
86
  readonly typescriptCompileMs?: number;
87
87
  readonly pageRenderingMs?: number;
88
+ readonly searchIndexGenerationMs?: number;
88
89
  readonly assetCopyMs?: number;
89
90
  readonly cacheManifestSaveMs?: number;
90
91
  readonly sitemapGenerationMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/metrics/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/metrics/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Search index auto-injection utilities.
3
+ * @module search/auto-inject
4
+ */
5
+ /**
6
+ * Injects a meta tag with the search index path into HTML.
7
+ * The meta tag allows client-side JavaScript to discover the search index location.
8
+ *
9
+ * @param html - Rendered HTML content
10
+ * @param searchIndexPath - Path to the search index file (e.g., '/search-index-a1b2c3d4.json')
11
+ * @returns HTML with injected search meta tag
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const html = '<html><head><title>Page</title></head><body>Content</body></html>';
16
+ * const enhanced = autoInjectSearchMeta(html, '/search-index-abc123.json');
17
+ * // Returns HTML with <meta name="stati:search-index" content="/search-index-abc123.json">
18
+ * ```
19
+ */
20
+ export declare function autoInjectSearchMeta(html: string, searchIndexPath: string): string;
21
+ //# sourceMappingURL=auto-inject.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-inject.d.ts","sourceRoot":"","sources":["../../src/search/auto-inject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,MAAM,CAgBlF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Search index auto-injection utilities.
3
+ * @module search/auto-inject
4
+ */
5
+ import { injectBeforeHeadClose } from '../core/index.js';
6
+ import { SEARCH_INDEX_META_NAME } from './constants.js';
7
+ /**
8
+ * Injects a meta tag with the search index path into HTML.
9
+ * The meta tag allows client-side JavaScript to discover the search index location.
10
+ *
11
+ * @param html - Rendered HTML content
12
+ * @param searchIndexPath - Path to the search index file (e.g., '/search-index-a1b2c3d4.json')
13
+ * @returns HTML with injected search meta tag
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const html = '<html><head><title>Page</title></head><body>Content</body></html>';
18
+ * const enhanced = autoInjectSearchMeta(html, '/search-index-abc123.json');
19
+ * // Returns HTML with <meta name="stati:search-index" content="/search-index-abc123.json">
20
+ * ```
21
+ */
22
+ export function autoInjectSearchMeta(html, searchIndexPath) {
23
+ // Check if meta tag already exists using regex to handle attribute order variations
24
+ // Matches: <meta name="stati:search-index" ...> or <meta content="..." name="stati:search-index" ...>
25
+ const existingMetaPattern = new RegExp(`<meta[^>]*name=["']${SEARCH_INDEX_META_NAME}["'][^>]*>`, 'i');
26
+ if (existingMetaPattern.test(html)) {
27
+ return html;
28
+ }
29
+ // Create the meta tag
30
+ const metaTag = `<meta name="${SEARCH_INDEX_META_NAME}" content="${searchIndexPath}">`;
31
+ // Inject before </head>
32
+ return injectBeforeHeadClose(html, metaTag);
33
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Search index constants.
3
+ * @module search/constants
4
+ */
5
+ /** Meta tag name used to expose the search index path to client-side code */
6
+ export declare const SEARCH_INDEX_META_NAME = "stati:search-index";
7
+ /** Current schema version for the search index */
8
+ export declare const SEARCH_INDEX_VERSION = "1.0.0";
9
+ /** Default configuration values for search index generation */
10
+ export declare const SEARCH_DEFAULTS: {
11
+ /** Default base filename for the search index */
12
+ readonly indexName: "search-index";
13
+ /** Whether to include content hash in filename by default */
14
+ readonly hashFilename: true;
15
+ /** Default maximum content length per section (in characters) */
16
+ readonly maxContentLength: 1000;
17
+ /** Default maximum preview length for page-level entries (in characters) */
18
+ readonly maxPreviewLength: 500;
19
+ /** Default heading levels to include in the index */
20
+ readonly headingLevels: readonly number[];
21
+ /** Default exclude patterns */
22
+ readonly exclude: readonly string[];
23
+ /** Whether to include the home page by default */
24
+ readonly includeHomePage: false;
25
+ /** Whether to auto-inject search index meta tag by default */
26
+ readonly autoInjectMetaTag: true;
27
+ };
28
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/search/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAE3D,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,UAAU,CAAC;AAE5C,+DAA+D;AAC/D,eAAO,MAAM,eAAe;IAC1B,iDAAiD;;IAEjD,6DAA6D;;IAE7D,iEAAiE;;IAEjE,4EAA4E;;IAE5E,qDAAqD;4BACnB,SAAS,MAAM,EAAE;IACnD,+BAA+B;sBAChB,SAAS,MAAM,EAAE;IAChC,kDAAkD;;IAElD,8DAA8D;;CAEtD,CAAC"}