@@ -5,6 +5,18 @@ import styles from './Search.module.css';
55
66const allModules = import . meta. glob ( '/src/content/**/*.md' , { query : '?raw' , import : 'default' } ) ;
77
8+ function stripMarkdown ( text ) {
9+ return text
10+ . replace ( / < [ ^ > ] + > / g, ' ' ) // HTML tags
11+ . replace ( / # + \s + / g, '' ) // headings
12+ . replace ( / [ * _ ~ ` ] + / g, '' ) // bold/italic/code markers
13+ . replace ( / \[ ( [ ^ \] ] * ) \] \( [ ^ ) ] * \) / g, '$1' ) // [text](url) → text
14+ . replace ( / ! \[ [ ^ \] ] * \] \( [ ^ ) ] * \) / g, '' ) // images
15+ . replace ( / & [ a - z ] + ; / gi, ' ' ) // HTML entities
16+ . replace ( / \s + / g, ' ' )
17+ . trim ( ) ;
18+ }
19+
820function getTitle ( content , path ) {
921 const firstLine = content . split ( '\n' ) . find ( l => l . startsWith ( '# ' ) ) ;
1022 if ( firstLine ) return firstLine . replace ( / ^ # \s + / , '' ) ;
@@ -13,10 +25,11 @@ function getTitle(content, path) {
1325}
1426
1527function getSnippet ( content , query ) {
16- const lower = content . toLowerCase ( ) ;
28+ const clean = stripMarkdown ( content ) ;
29+ const lower = clean . toLowerCase ( ) ;
1730 const idx = lower . indexOf ( query . toLowerCase ( ) ) ;
18- const raw = idx === - 1 ? content . slice ( 0 , 120 ) : content . slice ( Math . max ( 0 , idx - 40 ) , idx + query . length + 80 ) ;
19- return ( idx > 40 ? '…' : '' ) + raw . replace ( / # + \s / g , '' ) . replace ( / \n + / g , ' ' ) + '…' ;
31+ const raw = idx === - 1 ? clean . slice ( 0 , 120 ) : clean . slice ( Math . max ( 0 , idx - 40 ) , idx + query . length + 80 ) ;
32+ return ( idx > 40 ? '…' : '' ) + raw + '…' ;
2033}
2134
2235function pathToRoute ( path ) {
@@ -47,7 +60,7 @@ const Search = ({ onClose }) => {
4760 const entries = await Promise . all (
4861 Object . entries ( allModules ) . map ( async ( [ path , loader ] ) => {
4962 const content = await loader ( ) ;
50- return { path, content, title : getTitle ( content , path ) , route : pathToRoute ( path ) } ;
63+ return { path, content, clean : stripMarkdown ( content ) , title : getTitle ( content , path ) , route : pathToRoute ( path ) } ;
5164 } )
5265 ) ;
5366 setLoading ( false ) ;
@@ -61,7 +74,7 @@ const Search = ({ onClose }) => {
6174 const entries = await buildIndex ( ) ;
6275 const q = query . toLowerCase ( ) ;
6376 const matched = entries
64- . filter ( e => e . title . toLowerCase ( ) . includes ( q ) || e . content . toLowerCase ( ) . includes ( q ) )
77+ . filter ( e => e . title . toLowerCase ( ) . includes ( q ) || e . clean . toLowerCase ( ) . includes ( q ) )
6578 . slice ( 0 , 7 )
6679 . map ( e => ( { title : e . title , route : e . route , snippet : getSnippet ( e . content , query ) } ) ) ;
6780 setResults ( matched ) ;
0 commit comments