@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.
- package/dist/core/build.d.ts.map +1 -1
- package/dist/core/build.js +51 -7
- package/dist/core/dev.d.ts.map +1 -1
- package/dist/core/dev.js +17 -10
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -0
- package/dist/core/markdown.d.ts +9 -0
- package/dist/core/markdown.d.ts.map +1 -1
- package/dist/core/markdown.js +12 -0
- package/dist/core/utils/html.utils.d.ts +35 -0
- package/dist/core/utils/html.utils.d.ts.map +1 -0
- package/dist/core/utils/html.utils.js +46 -0
- package/dist/core/utils/index.d.ts +2 -1
- package/dist/core/utils/index.d.ts.map +1 -1
- package/dist/core/utils/index.js +3 -1
- package/dist/core/utils/paths.utils.d.ts +27 -0
- package/dist/core/utils/paths.utils.d.ts.map +1 -1
- package/dist/core/utils/paths.utils.js +45 -0
- package/dist/metrics/recorder.d.ts.map +1 -1
- package/dist/metrics/types.d.ts +1 -0
- package/dist/metrics/types.d.ts.map +1 -1
- package/dist/search/auto-inject.d.ts +21 -0
- package/dist/search/auto-inject.d.ts.map +1 -0
- package/dist/search/auto-inject.js +33 -0
- package/dist/search/constants.d.ts +28 -0
- package/dist/search/constants.d.ts.map +1 -0
- package/dist/search/constants.js +27 -0
- package/dist/search/generator.d.ts +101 -0
- package/dist/search/generator.d.ts.map +1 -0
- package/dist/search/generator.js +278 -0
- package/dist/search/index.d.ts +24 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +22 -0
- package/dist/seo/auto-inject.d.ts.map +1 -1
- package/dist/seo/auto-inject.js +5 -18
- package/dist/types/config.d.ts +3 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/content.d.ts +6 -0
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/search.d.ts +121 -0
- package/dist/types/search.d.ts.map +1 -0
- package/dist/types/search.js +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
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 const SEARCH_INDEX_META_NAME = 'stati:search-index';
|
|
7
|
+
/** Current schema version for the search index */
|
|
8
|
+
export const SEARCH_INDEX_VERSION = '1.0.0';
|
|
9
|
+
/** Default configuration values for search index generation */
|
|
10
|
+
export const SEARCH_DEFAULTS = {
|
|
11
|
+
/** Default base filename for the search index */
|
|
12
|
+
indexName: 'search-index',
|
|
13
|
+
/** Whether to include content hash in filename by default */
|
|
14
|
+
hashFilename: true,
|
|
15
|
+
/** Default maximum content length per section (in characters) */
|
|
16
|
+
maxContentLength: 1000,
|
|
17
|
+
/** Default maximum preview length for page-level entries (in characters) */
|
|
18
|
+
maxPreviewLength: 500,
|
|
19
|
+
/** Default heading levels to include in the index */
|
|
20
|
+
headingLevels: [2, 3, 4, 5, 6],
|
|
21
|
+
/** Default exclude patterns */
|
|
22
|
+
exclude: [],
|
|
23
|
+
/** Whether to include the home page by default */
|
|
24
|
+
includeHomePage: false,
|
|
25
|
+
/** Whether to auto-inject search index meta tag by default */
|
|
26
|
+
autoInjectMetaTag: true,
|
|
27
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search index generator utilities.
|
|
3
|
+
* @module search/generator
|
|
4
|
+
*/
|
|
5
|
+
import type { PageModel, TocEntry } from '../types/content.js';
|
|
6
|
+
import type { SearchConfig, SearchDocument, SearchIndex, SearchIndexMetadata } from '../types/search.js';
|
|
7
|
+
/**
|
|
8
|
+
* Generates a short content hash for cache busting.
|
|
9
|
+
* Uses MD5 and returns first 8 characters.
|
|
10
|
+
*
|
|
11
|
+
* @param content - Content to hash
|
|
12
|
+
* @returns 8-character hash string
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateContentHash(content: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Builds a breadcrumb string from a URL path.
|
|
17
|
+
*
|
|
18
|
+
* @param url - Page URL path (e.g., '/getting-started/installation')
|
|
19
|
+
* @param pageTitle - Page title to use as the last segment
|
|
20
|
+
* @returns Breadcrumb string (e.g., 'Getting Started > Installation')
|
|
21
|
+
*/
|
|
22
|
+
export declare function buildBreadcrumb(url: string, pageTitle: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Strips Markdown syntax to extract plain text for search indexing.
|
|
25
|
+
* Handles code blocks, links, images, emphasis, etc.
|
|
26
|
+
*
|
|
27
|
+
* @param markdown - Raw markdown content
|
|
28
|
+
* @returns Plain text content
|
|
29
|
+
*/
|
|
30
|
+
export declare function stripMarkdown(markdown: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Extracts searchable sections from page data using TOC entries and markdown content.
|
|
33
|
+
* This is more efficient than parsing rendered HTML as it uses structured data
|
|
34
|
+
* already available from the markdown processing pipeline.
|
|
35
|
+
*
|
|
36
|
+
* @param toc - Table of contents entries with heading IDs, text, and levels
|
|
37
|
+
* @param markdownContent - Raw markdown content of the page
|
|
38
|
+
* @param pageUrl - Page URL path
|
|
39
|
+
* @param pageTitle - Page title from frontmatter
|
|
40
|
+
* @param tags - Optional tags from frontmatter
|
|
41
|
+
* @param config - Search configuration
|
|
42
|
+
* @returns Array of SearchDocument objects
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractSectionsFromMarkdown(toc: TocEntry[], markdownContent: string, pageUrl: string, pageTitle: string, tags: readonly string[] | undefined, config: SearchConfig): SearchDocument[];
|
|
45
|
+
/**
|
|
46
|
+
* Checks if a page should be excluded from the search index.
|
|
47
|
+
*
|
|
48
|
+
* @param page - Page model to check
|
|
49
|
+
* @param config - Search configuration
|
|
50
|
+
* @returns true if the page should be excluded
|
|
51
|
+
*/
|
|
52
|
+
export declare function shouldExcludePage(page: PageModel, config: SearchConfig): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Page data for search indexing using markdown and TOC entries.
|
|
55
|
+
* Uses structured data already available from the markdown processing pipeline.
|
|
56
|
+
*/
|
|
57
|
+
export interface SearchablePage {
|
|
58
|
+
/** The page model with metadata */
|
|
59
|
+
page: PageModel;
|
|
60
|
+
/** Table of contents entries extracted during markdown rendering */
|
|
61
|
+
toc: TocEntry[];
|
|
62
|
+
/** Raw markdown content for section extraction */
|
|
63
|
+
markdownContent: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Generates a search index from searchable pages using markdown and TOC data.
|
|
67
|
+
*
|
|
68
|
+
* @param searchablePages - Array of pages with TOC and markdown content
|
|
69
|
+
* @param config - Search configuration
|
|
70
|
+
* @returns SearchIndex object
|
|
71
|
+
*/
|
|
72
|
+
export declare function generateSearchIndex(searchablePages: SearchablePage[], config: SearchConfig): SearchIndex;
|
|
73
|
+
/**
|
|
74
|
+
* Writes the search index to a JSON file.
|
|
75
|
+
*
|
|
76
|
+
* @param searchIndex - The search index to write
|
|
77
|
+
* @param outDir - Output directory path
|
|
78
|
+
* @param filename - Pre-computed filename (from computeSearchIndexFilename)
|
|
79
|
+
* @returns Metadata about the written search index
|
|
80
|
+
*/
|
|
81
|
+
export declare function writeSearchIndex(searchIndex: SearchIndex, outDir: string, filename: string): Promise<SearchIndexMetadata>;
|
|
82
|
+
/**
|
|
83
|
+
* Computes the search index filename based on configuration.
|
|
84
|
+
* When hashFilename is true, generates a deterministic hash based on the build ID.
|
|
85
|
+
* This allows the filename to be known before the index is generated,
|
|
86
|
+
* enabling meta tag injection during initial template render.
|
|
87
|
+
*
|
|
88
|
+
* @param config - Search configuration
|
|
89
|
+
* @param buildId - Unique identifier for this build (e.g., timestamp or build ID)
|
|
90
|
+
* @returns The search index filename (without leading slash)
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // At build start, compute the filename
|
|
95
|
+
* const filename = computeSearchIndexFilename(config.search, Date.now().toString());
|
|
96
|
+
* // filename: 'search-index-a1b2c3d4.json' (when hashFilename is true)
|
|
97
|
+
* // filename: 'search-index.json' (when hashFilename is false)
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function computeSearchIndexFilename(config: SearchConfig, buildId?: string): string;
|
|
101
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/search/generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAuBtE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA0CtD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,QAAQ,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACnC,MAAM,EAAE,YAAY,GACnB,cAAc,EAAE,CAiGlB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAsBhF;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,IAAI,EAAE,SAAS,CAAC;IAChB,oEAAoE;IACpE,GAAG,EAAE,QAAQ,EAAE,CAAC;IAChB,kDAAkD;IAClD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,cAAc,EAAE,EACjC,MAAM,EAAE,YAAY,GACnB,WAAW,CA6Bb;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,mBAAmB,CAAC,CAgB9B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAczF"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search index generator utilities.
|
|
3
|
+
* @module search/generator
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { minimatch } from 'minimatch';
|
|
8
|
+
import { writeFile, ensureDir } from '../core/utils/fs.utils.js';
|
|
9
|
+
import { SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
10
|
+
/**
|
|
11
|
+
* Generates a short content hash for cache busting.
|
|
12
|
+
* Uses MD5 and returns first 8 characters.
|
|
13
|
+
*
|
|
14
|
+
* @param content - Content to hash
|
|
15
|
+
* @returns 8-character hash string
|
|
16
|
+
*/
|
|
17
|
+
export function generateContentHash(content) {
|
|
18
|
+
return createHash('md5').update(content).digest('hex').substring(0, 8);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Builds a breadcrumb string from a URL path.
|
|
22
|
+
*
|
|
23
|
+
* @param url - Page URL path (e.g., '/getting-started/installation')
|
|
24
|
+
* @param pageTitle - Page title to use as the last segment
|
|
25
|
+
* @returns Breadcrumb string (e.g., 'Getting Started > Installation')
|
|
26
|
+
*/
|
|
27
|
+
export function buildBreadcrumb(url, pageTitle) {
|
|
28
|
+
if (url === '/' || url === '') {
|
|
29
|
+
return pageTitle;
|
|
30
|
+
}
|
|
31
|
+
const segments = url.split('/').filter(Boolean);
|
|
32
|
+
if (segments.length === 0) {
|
|
33
|
+
return pageTitle;
|
|
34
|
+
}
|
|
35
|
+
// Convert slug segments to title case
|
|
36
|
+
const crumbs = segments.slice(0, -1).map((segment) => segment
|
|
37
|
+
.split('-')
|
|
38
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
39
|
+
.join(' '));
|
|
40
|
+
// Add the page title as the last crumb
|
|
41
|
+
crumbs.push(pageTitle);
|
|
42
|
+
return crumbs.join(' > ');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Strips Markdown syntax to extract plain text for search indexing.
|
|
46
|
+
* Handles code blocks, links, images, emphasis, etc.
|
|
47
|
+
*
|
|
48
|
+
* @param markdown - Raw markdown content
|
|
49
|
+
* @returns Plain text content
|
|
50
|
+
*/
|
|
51
|
+
export function stripMarkdown(markdown) {
|
|
52
|
+
let text = markdown;
|
|
53
|
+
// Remove code blocks (fenced and indented)
|
|
54
|
+
text = text.replace(/```[\s\S]*?```/g, ' ');
|
|
55
|
+
text = text.replace(/`[^`]+`/g, ' ');
|
|
56
|
+
// Remove images 
|
|
57
|
+
text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, ' ');
|
|
58
|
+
// Convert links [text](url) to just text
|
|
59
|
+
text = text.replace(/\[([^\]]*)\]\([^)]*\)/g, '$1');
|
|
60
|
+
// Remove reference-style link definitions [id]: url
|
|
61
|
+
text = text.replace(/^\[[^\]]+\]:\s*\S+.*$/gm, '');
|
|
62
|
+
// Remove HTML tags
|
|
63
|
+
text = text.replace(/<[^>]+>/g, ' ');
|
|
64
|
+
// Remove emphasis markers (bold, italic)
|
|
65
|
+
text = text.replace(/[*_]{1,3}([^*_]+)[*_]{1,3}/g, '$1');
|
|
66
|
+
// Remove strikethrough
|
|
67
|
+
text = text.replace(/~~([^~]+)~~/g, '$1');
|
|
68
|
+
// Remove headings markers (but keep the text)
|
|
69
|
+
text = text.replace(/^#{1,6}\s+/gm, '');
|
|
70
|
+
// Remove blockquote markers
|
|
71
|
+
text = text.replace(/^>\s*/gm, '');
|
|
72
|
+
// Remove horizontal rules
|
|
73
|
+
text = text.replace(/^[-*_]{3,}\s*$/gm, '');
|
|
74
|
+
// Remove list markers
|
|
75
|
+
text = text.replace(/^[\s]*[-*+]\s+/gm, '');
|
|
76
|
+
text = text.replace(/^[\s]*\d+\.\s+/gm, '');
|
|
77
|
+
// Normalize whitespace
|
|
78
|
+
text = text.replace(/\s+/g, ' ').trim();
|
|
79
|
+
return text;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Extracts searchable sections from page data using TOC entries and markdown content.
|
|
83
|
+
* This is more efficient than parsing rendered HTML as it uses structured data
|
|
84
|
+
* already available from the markdown processing pipeline.
|
|
85
|
+
*
|
|
86
|
+
* @param toc - Table of contents entries with heading IDs, text, and levels
|
|
87
|
+
* @param markdownContent - Raw markdown content of the page
|
|
88
|
+
* @param pageUrl - Page URL path
|
|
89
|
+
* @param pageTitle - Page title from frontmatter
|
|
90
|
+
* @param tags - Optional tags from frontmatter
|
|
91
|
+
* @param config - Search configuration
|
|
92
|
+
* @returns Array of SearchDocument objects
|
|
93
|
+
*/
|
|
94
|
+
export function extractSectionsFromMarkdown(toc, markdownContent, pageUrl, pageTitle, tags, config) {
|
|
95
|
+
const documents = [];
|
|
96
|
+
const headingLevels = config.headingLevels ?? SEARCH_DEFAULTS.headingLevels;
|
|
97
|
+
const maxContentLength = config.maxContentLength ?? SEARCH_DEFAULTS.maxContentLength;
|
|
98
|
+
const maxPreviewLength = config.maxPreviewLength ?? SEARCH_DEFAULTS.maxPreviewLength;
|
|
99
|
+
const breadcrumb = buildBreadcrumb(pageUrl, pageTitle);
|
|
100
|
+
// Filter TOC entries to only include configured heading levels
|
|
101
|
+
const filteredToc = toc.filter((entry) => headingLevels.includes(entry.level));
|
|
102
|
+
// Find heading positions in markdown content
|
|
103
|
+
// Headings in markdown are lines starting with # symbols
|
|
104
|
+
const lines = markdownContent.split('\n');
|
|
105
|
+
const headingPositions = [];
|
|
106
|
+
// Build a map of heading text to TOC entries for matching
|
|
107
|
+
let charIndex = 0;
|
|
108
|
+
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
|
|
109
|
+
const line = lines[lineIndex] ?? '';
|
|
110
|
+
const headingMatch = line.match(/^(#{2,6})\s+(.+)$/);
|
|
111
|
+
if (headingMatch) {
|
|
112
|
+
const headingText = headingMatch[2]?.trim() ?? '';
|
|
113
|
+
// Find matching TOC entry by text (case-insensitive, normalized)
|
|
114
|
+
const normalizedText = headingText.toLowerCase().replace(/[*_`[\]]/g, '');
|
|
115
|
+
const matchingEntry = filteredToc.find((entry) => entry.text.toLowerCase() === normalizedText || entry.text === headingText);
|
|
116
|
+
if (matchingEntry) {
|
|
117
|
+
headingPositions.push({
|
|
118
|
+
entry: matchingEntry,
|
|
119
|
+
lineIndex,
|
|
120
|
+
charIndex,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
charIndex += line.length + 1; // +1 for newline
|
|
125
|
+
}
|
|
126
|
+
// Extract content before first heading for page-level document
|
|
127
|
+
const firstHeadingChar = headingPositions[0]?.charIndex ?? markdownContent.length;
|
|
128
|
+
const pageContentMarkdown = markdownContent.substring(0, firstHeadingChar);
|
|
129
|
+
const pageContent = stripMarkdown(pageContentMarkdown).substring(0, maxPreviewLength);
|
|
130
|
+
// Create page-level document (level 1 = page title)
|
|
131
|
+
documents.push({
|
|
132
|
+
id: `${pageUrl}#top`,
|
|
133
|
+
url: pageUrl,
|
|
134
|
+
anchor: '',
|
|
135
|
+
title: pageTitle,
|
|
136
|
+
heading: pageTitle,
|
|
137
|
+
level: 1,
|
|
138
|
+
content: pageContent,
|
|
139
|
+
breadcrumb,
|
|
140
|
+
...(tags && tags.length > 0 ? { tags: [...tags] } : {}),
|
|
141
|
+
});
|
|
142
|
+
// Create documents for each heading section
|
|
143
|
+
for (let i = 0; i < headingPositions.length; i++) {
|
|
144
|
+
const pos = headingPositions[i];
|
|
145
|
+
if (!pos)
|
|
146
|
+
continue;
|
|
147
|
+
const nextPos = headingPositions[i + 1];
|
|
148
|
+
const sectionStart = pos.charIndex;
|
|
149
|
+
const sectionEnd = nextPos ? nextPos.charIndex : markdownContent.length;
|
|
150
|
+
// Extract section content (skip the heading line itself)
|
|
151
|
+
const sectionLines = markdownContent.substring(sectionStart, sectionEnd).split('\n');
|
|
152
|
+
const contentLines = sectionLines.slice(1); // Skip heading line
|
|
153
|
+
const sectionMarkdown = contentLines.join('\n');
|
|
154
|
+
const sectionContent = stripMarkdown(sectionMarkdown).substring(0, maxContentLength);
|
|
155
|
+
// Skip empty sections
|
|
156
|
+
if (!sectionContent.trim()) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
documents.push({
|
|
160
|
+
id: `${pageUrl}#${pos.entry.id}`,
|
|
161
|
+
url: pageUrl,
|
|
162
|
+
anchor: pos.entry.id,
|
|
163
|
+
title: pageTitle,
|
|
164
|
+
heading: pos.entry.text,
|
|
165
|
+
level: pos.entry.level,
|
|
166
|
+
content: sectionContent,
|
|
167
|
+
breadcrumb: `${breadcrumb} > ${pos.entry.text}`,
|
|
168
|
+
...(tags && tags.length > 0 ? { tags: [...tags] } : {}),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return documents;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Checks if a page should be excluded from the search index.
|
|
175
|
+
*
|
|
176
|
+
* @param page - Page model to check
|
|
177
|
+
* @param config - Search configuration
|
|
178
|
+
* @returns true if the page should be excluded
|
|
179
|
+
*/
|
|
180
|
+
export function shouldExcludePage(page, config) {
|
|
181
|
+
// Exclude drafts
|
|
182
|
+
if (page.frontMatter.draft) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
// Check home page exclusion
|
|
186
|
+
const isHomePage = page.url === '/' || page.url === '';
|
|
187
|
+
const includeHomePage = config.includeHomePage ?? SEARCH_DEFAULTS.includeHomePage;
|
|
188
|
+
if (isHomePage && !includeHomePage) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
// Check exclude patterns
|
|
192
|
+
const excludePatterns = config.exclude ?? SEARCH_DEFAULTS.exclude;
|
|
193
|
+
for (const pattern of excludePatterns) {
|
|
194
|
+
if (minimatch(page.url, pattern)) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Generates a search index from searchable pages using markdown and TOC data.
|
|
202
|
+
*
|
|
203
|
+
* @param searchablePages - Array of pages with TOC and markdown content
|
|
204
|
+
* @param config - Search configuration
|
|
205
|
+
* @returns SearchIndex object
|
|
206
|
+
*/
|
|
207
|
+
export function generateSearchIndex(searchablePages, config) {
|
|
208
|
+
const documents = [];
|
|
209
|
+
for (const { page, toc, markdownContent } of searchablePages) {
|
|
210
|
+
// Skip excluded pages
|
|
211
|
+
if (shouldExcludePage(page, config)) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
const pageTitle = page.frontMatter.title || page.slug;
|
|
215
|
+
const tags = page.frontMatter.tags;
|
|
216
|
+
const pageDocs = extractSectionsFromMarkdown(toc, markdownContent, page.url, pageTitle, tags, config);
|
|
217
|
+
documents.push(...pageDocs);
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
version: SEARCH_INDEX_VERSION,
|
|
221
|
+
generatedAt: new Date().toISOString(),
|
|
222
|
+
documentCount: documents.length,
|
|
223
|
+
documents,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Writes the search index to a JSON file.
|
|
228
|
+
*
|
|
229
|
+
* @param searchIndex - The search index to write
|
|
230
|
+
* @param outDir - Output directory path
|
|
231
|
+
* @param filename - Pre-computed filename (from computeSearchIndexFilename)
|
|
232
|
+
* @returns Metadata about the written search index
|
|
233
|
+
*/
|
|
234
|
+
export async function writeSearchIndex(searchIndex, outDir, filename) {
|
|
235
|
+
// Serialize index
|
|
236
|
+
const content = JSON.stringify(searchIndex, null, 0);
|
|
237
|
+
// Ensure output directory exists
|
|
238
|
+
await ensureDir(outDir);
|
|
239
|
+
// Write the file
|
|
240
|
+
const filePath = join(outDir, filename);
|
|
241
|
+
await writeFile(filePath, content, 'utf-8');
|
|
242
|
+
return {
|
|
243
|
+
enabled: true,
|
|
244
|
+
indexPath: `/${filename}`,
|
|
245
|
+
documentCount: searchIndex.documentCount,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Computes the search index filename based on configuration.
|
|
250
|
+
* When hashFilename is true, generates a deterministic hash based on the build ID.
|
|
251
|
+
* This allows the filename to be known before the index is generated,
|
|
252
|
+
* enabling meta tag injection during initial template render.
|
|
253
|
+
*
|
|
254
|
+
* @param config - Search configuration
|
|
255
|
+
* @param buildId - Unique identifier for this build (e.g., timestamp or build ID)
|
|
256
|
+
* @returns The search index filename (without leading slash)
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* // At build start, compute the filename
|
|
261
|
+
* const filename = computeSearchIndexFilename(config.search, Date.now().toString());
|
|
262
|
+
* // filename: 'search-index-a1b2c3d4.json' (when hashFilename is true)
|
|
263
|
+
* // filename: 'search-index.json' (when hashFilename is false)
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export function computeSearchIndexFilename(config, buildId) {
|
|
267
|
+
const indexName = config.indexName ?? SEARCH_DEFAULTS.indexName;
|
|
268
|
+
const hashFilename = config.hashFilename ?? SEARCH_DEFAULTS.hashFilename;
|
|
269
|
+
if (hashFilename) {
|
|
270
|
+
// Generate a deterministic hash based on build ID
|
|
271
|
+
// This allows the filename to be known before content is generated
|
|
272
|
+
const hashInput = buildId ?? Date.now().toString();
|
|
273
|
+
const hash = generateContentHash(hashInput);
|
|
274
|
+
return `${indexName}-${hash}.json`;
|
|
275
|
+
}
|
|
276
|
+
// Return base filename (without hash)
|
|
277
|
+
return `${indexName}.json`;
|
|
278
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search index generation module.
|
|
3
|
+
* Provides build-time search index generation for Stati sites.
|
|
4
|
+
*
|
|
5
|
+
* @module search
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { generateSearchIndex, writeSearchIndex, SEARCH_INDEX_META_NAME } from '@stati/core/search';
|
|
10
|
+
*
|
|
11
|
+
* // Generate search index from searchable pages
|
|
12
|
+
* const searchIndex = generateSearchIndex(searchablePages, config.search);
|
|
13
|
+
*
|
|
14
|
+
* // Write to output directory
|
|
15
|
+
* const metadata = await writeSearchIndex(searchIndex, outDir, config.search);
|
|
16
|
+
* console.log(`Generated search index at ${metadata.indexPath}`);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, } from './generator.js';
|
|
20
|
+
export type { SearchablePage } from './generator.js';
|
|
21
|
+
export { autoInjectSearchMeta } from './auto-inject.js';
|
|
22
|
+
export { SEARCH_INDEX_META_NAME, SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
23
|
+
export type { SearchConfig, SearchDocument, SearchIndex, SearchIndexMetadata, } from '../types/search.js';
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE/F,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,mBAAmB,GACpB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search index generation module.
|
|
3
|
+
* Provides build-time search index generation for Stati sites.
|
|
4
|
+
*
|
|
5
|
+
* @module search
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { generateSearchIndex, writeSearchIndex, SEARCH_INDEX_META_NAME } from '@stati/core/search';
|
|
10
|
+
*
|
|
11
|
+
* // Generate search index from searchable pages
|
|
12
|
+
* const searchIndex = generateSearchIndex(searchablePages, config.search);
|
|
13
|
+
*
|
|
14
|
+
* // Write to output directory
|
|
15
|
+
* const metadata = await writeSearchIndex(searchIndex, outDir, config.search);
|
|
16
|
+
* console.log(`Generated search index at ${metadata.indexPath}`);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export { generateSearchIndex, writeSearchIndex, extractSectionsFromMarkdown, stripMarkdown, shouldExcludePage, generateContentHash, buildBreadcrumb, computeSearchIndexFilename, } from './generator.js';
|
|
20
|
+
// Auto-injection
|
|
21
|
+
export { autoInjectSearchMeta } from './auto-inject.js';
|
|
22
|
+
export { SEARCH_INDEX_META_NAME, SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-inject.d.ts","sourceRoot":"","sources":["../../src/seo/auto-inject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"auto-inject.d.ts","sourceRoot":"","sources":["../../src/seo/auto-inject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,+CAA+C;IAC/C,IAAI,EAAE,SAAS,CAAC;IAChB,yBAAyB;IACzB,MAAM,EAAE,WAAW,CAAC;IACpB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAmBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CA0D9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAK/E"}
|
package/dist/seo/auto-inject.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { detectExistingSEOTags } from './utils/index.js';
|
|
6
6
|
import { generateSEOMetadata } from './generator.js';
|
|
7
|
+
import { injectBeforeHeadClose } from '../core/index.js';
|
|
7
8
|
/**
|
|
8
9
|
* Helper function to conditionally log debug messages for SEO auto-injection.
|
|
9
10
|
* Checks both the explicit debug flag and the config-level debug setting.
|
|
@@ -17,16 +18,6 @@ function logDebug(message, options) {
|
|
|
17
18
|
options.logger.warning(logMessage);
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Finds the position to inject SEO tags (before </head>)
|
|
22
|
-
* @param html - HTML content
|
|
23
|
-
* @returns Position index or -1 if not found
|
|
24
|
-
*/
|
|
25
|
-
function findHeadClosePosition(html) {
|
|
26
|
-
// Case-insensitive search for </head>
|
|
27
|
-
const match = html.match(/<\/head>/i);
|
|
28
|
-
return match ? (match.index ?? -1) : -1;
|
|
29
|
-
}
|
|
30
21
|
/**
|
|
31
22
|
* Automatically injects SEO metadata into HTML if not already present
|
|
32
23
|
* @param html - Rendered HTML content
|
|
@@ -77,17 +68,13 @@ export function autoInjectSEO(html, options) {
|
|
|
77
68
|
logDebug(`No tags to inject for ${page.url} (all exist)`, { debug, config, logger });
|
|
78
69
|
return html;
|
|
79
70
|
}
|
|
80
|
-
//
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
71
|
+
// Inject SEO metadata before </head>
|
|
72
|
+
const injected = injectBeforeHeadClose(html, seoMetadata);
|
|
73
|
+
// Check if injection was successful (</head> was found)
|
|
74
|
+
if (injected === html) {
|
|
83
75
|
logDebug(`No </head> tag found in ${page.url}, skipping injection`, { debug, config, logger });
|
|
84
76
|
return html;
|
|
85
77
|
}
|
|
86
|
-
// Inject SEO metadata before </head>
|
|
87
|
-
const before = html.substring(0, headClosePos);
|
|
88
|
-
const after = html.substring(headClosePos);
|
|
89
|
-
// Add proper indentation (4 spaces) and newline
|
|
90
|
-
const injected = `${before} ${seoMetadata}\n${after}`;
|
|
91
78
|
logDebug(`Injected ${existingTags.size === 0 ? 'all' : 'missing'} SEO tags into ${page.url}`, {
|
|
92
79
|
debug,
|
|
93
80
|
config,
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type MarkdownIt from 'markdown-it';
|
|
2
2
|
import type { SitemapConfig } from './sitemap.js';
|
|
3
3
|
import type { AuthorConfig } from './content.js';
|
|
4
|
+
import type { SearchConfig } from './search.js';
|
|
4
5
|
/**
|
|
5
6
|
* Configuration related type definitions
|
|
6
7
|
*/
|
|
@@ -78,6 +79,8 @@ export interface StatiConfig {
|
|
|
78
79
|
robots?: RobotsTxtConfig;
|
|
79
80
|
/** RSS feed generation configuration */
|
|
80
81
|
rss?: import('./rss.js').RSSConfig;
|
|
82
|
+
/** Search index generation configuration */
|
|
83
|
+
search?: SearchConfig;
|
|
81
84
|
/** TypeScript compilation settings */
|
|
82
85
|
typescript?: TypeScriptConfig;
|
|
83
86
|
/** Development server configuration */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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"}
|
package/dist/types/content.d.ts
CHANGED
|
@@ -22,6 +22,12 @@ export interface StatiAssets {
|
|
|
22
22
|
* Always an array, empty [] if no TypeScript enabled or no bundles match.
|
|
23
23
|
*/
|
|
24
24
|
bundlePaths: string[];
|
|
25
|
+
/**
|
|
26
|
+
* Path to the search index file (e.g., '/search-index-a1b2c3d4.json').
|
|
27
|
+
* Available when search index generation is enabled.
|
|
28
|
+
* Use this path in client-side JavaScript to fetch the search index.
|
|
29
|
+
*/
|
|
30
|
+
searchIndexPath?: string;
|
|
25
31
|
}
|
|
26
32
|
/**
|
|
27
33
|
* Table of contents entry extracted from page headings.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export type { SEOContext, SEOValidationResult } from './seo.js';
|
|
|
9
9
|
export { SEOTagType } from './seo.js';
|
|
10
10
|
export type { ChangeFrequency, SitemapEntry, SitemapConfig, SitemapGenerationResult, } from './sitemap.js';
|
|
11
11
|
export type { RSSConfig, RSSFeedConfig, RSSGenerationResult } from './rss.js';
|
|
12
|
+
export type { SearchConfig, SearchDocument, SearchIndex, SearchIndexMetadata } from './search.js';
|
|
12
13
|
export type { NavNode } from './navigation.js';
|
|
13
14
|
export type { Logger } from './logging.js';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGhF,YAAY,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,YAAY,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACb,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG9E,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGhF,YAAY,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,YAAY,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACd,eAAe,EACf,WAAW,EACX,eAAe,EACf,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,YAAY,EACV,eAAe,EACf,YAAY,EACZ,aAAa,EACb,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAG9E,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlG,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC"}
|