@stati/core 1.24.3 → 1.24.4
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 +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;
|
|
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;AAqBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CA2BtE;AAKD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA8DtD;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;AAiBD,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,eAAe,UAAQ,GACtB,OAAO,CAAC,mBAAmB,CAAC,CAqC9B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAczF"}
|
package/dist/search/generator.js
CHANGED
|
@@ -17,6 +17,24 @@ import { SEARCH_INDEX_VERSION, SEARCH_DEFAULTS } from './constants.js';
|
|
|
17
17
|
export function generateContentHash(content) {
|
|
18
18
|
return createHash('md5').update(content).digest('hex').substring(0, 8);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* URL segments that read as acronyms and stay uppercase in breadcrumbs.
|
|
22
|
+
*/
|
|
23
|
+
const BREADCRUMB_ACRONYMS = new Set([
|
|
24
|
+
'ai',
|
|
25
|
+
'api',
|
|
26
|
+
'cli',
|
|
27
|
+
'css',
|
|
28
|
+
'faq',
|
|
29
|
+
'html',
|
|
30
|
+
'isg',
|
|
31
|
+
'json',
|
|
32
|
+
'rss',
|
|
33
|
+
'seo',
|
|
34
|
+
'ui',
|
|
35
|
+
'url',
|
|
36
|
+
'xml',
|
|
37
|
+
]);
|
|
20
38
|
/**
|
|
21
39
|
* Builds a breadcrumb string from a URL path.
|
|
22
40
|
*
|
|
@@ -32,15 +50,19 @@ export function buildBreadcrumb(url, pageTitle) {
|
|
|
32
50
|
if (segments.length === 0) {
|
|
33
51
|
return pageTitle;
|
|
34
52
|
}
|
|
35
|
-
// Convert slug segments to title case
|
|
53
|
+
// Convert slug segments to title case, keeping known acronyms uppercase
|
|
36
54
|
const crumbs = segments.slice(0, -1).map((segment) => segment
|
|
37
55
|
.split('-')
|
|
38
|
-
.map((word) =>
|
|
56
|
+
.map((word) => BREADCRUMB_ACRONYMS.has(word.toLowerCase())
|
|
57
|
+
? word.toUpperCase()
|
|
58
|
+
: word.charAt(0).toUpperCase() + word.slice(1))
|
|
39
59
|
.join(' '));
|
|
40
60
|
// Add the page title as the last crumb
|
|
41
61
|
crumbs.push(pageTitle);
|
|
42
62
|
return crumbs.join(' > ');
|
|
43
63
|
}
|
|
64
|
+
/** Private-use character that brackets inline code placeholders in stripMarkdown. */
|
|
65
|
+
const CODE_MARK = '';
|
|
44
66
|
/**
|
|
45
67
|
* Strips Markdown syntax to extract plain text for search indexing.
|
|
46
68
|
* Handles code blocks, links, images, emphasis, etc.
|
|
@@ -50,9 +72,21 @@ export function buildBreadcrumb(url, pageTitle) {
|
|
|
50
72
|
*/
|
|
51
73
|
export function stripMarkdown(markdown) {
|
|
52
74
|
let text = markdown;
|
|
53
|
-
// Remove code blocks
|
|
54
|
-
|
|
55
|
-
text = text.replace(
|
|
75
|
+
// Remove fenced code blocks. Fences sit at the start of a line, so inline
|
|
76
|
+
// spans written with three or more backticks are left for the step below.
|
|
77
|
+
text = text.replace(/^[ \t>]*(`{3,}|~{3,})[^\n]*\n[\s\S]*?^[ \t>]*\1[`~]*[ \t]*$/gm, ' ');
|
|
78
|
+
// Keep inline code text (identifiers are what people search for), shielded
|
|
79
|
+
// from the emphasis and HTML stripping below and restored at the end.
|
|
80
|
+
// A span closes on a backtick run of the same length as its opener, so
|
|
81
|
+
// ``a `b` c`` is one span; one padding space on each side is dropped.
|
|
82
|
+
const inlineCode = [];
|
|
83
|
+
text = text.replace(/(`+)([\s\S]*?[^`])\1(?!`)/g, (_match, _fence, code) => {
|
|
84
|
+
inlineCode.push(/^ [\s\S]* $/.test(code) && code.trim() ? code.slice(1, -1) : code);
|
|
85
|
+
return `${CODE_MARK}${inlineCode.length - 1}${CODE_MARK}`;
|
|
86
|
+
});
|
|
87
|
+
// Remove table delimiter rows and cell pipes
|
|
88
|
+
text = text.replace(/^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$/gm, '');
|
|
89
|
+
text = text.replace(/\s*\|\s*/g, ' ');
|
|
56
90
|
// Remove images 
|
|
57
91
|
text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, ' ');
|
|
58
92
|
// Convert links [text](url) to just text
|
|
@@ -74,6 +108,8 @@ export function stripMarkdown(markdown) {
|
|
|
74
108
|
// Remove list markers
|
|
75
109
|
text = text.replace(/^[\s]*[-*+]\s+/gm, '');
|
|
76
110
|
text = text.replace(/^[\s]*\d+\.\s+/gm, '');
|
|
111
|
+
// Restore inline code
|
|
112
|
+
text = text.replace(new RegExp(`${CODE_MARK}(\\d+)${CODE_MARK}`, 'g'), (_match, index) => inlineCode[Number(index)] ?? '');
|
|
77
113
|
// Normalize whitespace
|
|
78
114
|
text = text.replace(/\s+/g, ' ').trim();
|
|
79
115
|
return text;
|