@@ -173,13 +173,13 @@ export async function exporter(argument: ProjectExportArguments, json: any) {
173173 ${ toLinkCard ( argument , course . collection [ j ] , true ) }
174174 </div>`
175175 } else {
176- let { html, json, searchEntries } = await toCard (
176+ let { html, json, searchEntry } = await toCard (
177177 argument ,
178178 course . collection [ j ] ,
179179 true ,
180180 )
181181
182- searchIndex . push ( ... searchEntries )
182+ if ( searchEntry ) searchIndex . push ( searchEntry )
183183 subCards += `<div class='col-sm-6 col-md-4 col-lg-3 ${
184184 course . grid ? 'mb-3' : ''
185185 } '>
@@ -227,10 +227,10 @@ export async function exporter(argument: ProjectExportArguments, json: any) {
227227 } else if ( course . link ) {
228228 cards += "<div class='col'>" + toLinkCard ( argument , course ) + '</div>'
229229 } else {
230- let { html, json, searchEntries } = await toCard ( argument , course )
230+ let { html, json, searchEntry } = await toCard ( argument , course )
231231
232232 cards += "<div class='col'>" + html + '</div>'
233- searchIndex . push ( ... searchEntries )
233+ if ( searchEntry ) searchIndex . push ( searchEntry )
234234 itemList . push ( json )
235235 }
236236 }
@@ -447,9 +447,26 @@ export async function exporter(argument: ProjectExportArguments, json: any) {
447447 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
448448 <script src="https://cdn.jsdelivr.net/npm/fuse.js@7.0.0/dist/fuse.min.js"></script>
449449 <script>
450+ // Compact index: [{t, g, i, u, s: [[sectionTitle, sectionContent, indentation], ...]}]
451+ // Denormalize into flat records for Fuse
450452 var SEARCH_INDEX = ${ JSON . stringify ( searchIndex ) } ;
453+ var FLAT_INDEX = [];
454+ SEARCH_INDEX.forEach(function(course) {
455+ for (var n = 0; n < course.s.length; n++) {
456+ var sec = course.s[n];
457+ FLAT_INDEX.push({
458+ courseTitle: course.t,
459+ sectionTitle: sec[0],
460+ sectionContent: sec[1],
461+ tags: course.g,
462+ image: course.i,
463+ url: course.u + '#' + (n + 1),
464+ indentation: sec[2],
465+ });
466+ }
467+ });
451468
452- var fuse = new Fuse(SEARCH_INDEX , {
469+ var fuse = new Fuse(FLAT_INDEX , {
453470 keys: [
454471 { name: 'courseTitle', weight: 0.35 },
455472 { name: 'sectionTitle', weight: 0.30 },
@@ -694,17 +711,24 @@ function markdownToText(md: string): string {
694711}
695712
696713/**
697- * Builds per-course search index entries from the parsed LiaScript data.
698- * Each section becomes one entry containing: course title, section title,
699- * section content (cleaned), tags, image, url, and indentation level.
714+ * Builds a compact course object for the search index.
715+ * Shared fields (courseTitle, tags, image, baseUrl) are stored once per course.
716+ * Per-section data is stored as a minimal array: [sectionTitle, sectionContent, indentation].
717+ * The browser denormalizes this into flat records before passing to Fuse.
700718 */
701- function buildCourseSearchEntries ( course : any ) : any [ ] {
719+ function buildCourseSearchEntry ( course : any ) : any | null {
702720 const lia = course . data ?. lia
703- if ( ! lia ) return [ ]
721+ if ( ! lia ) return null
704722
705723 const courseTitle = overwrite ( course . title , lia . str_title ) || ''
706- const courseUrl = 'https://LiaScript.github.io/course/?' + lia . readme
707- const image = overwrite ( course . logo , lia . definition ?. logo ) || ''
724+ const readmeUrl = lia . readme as string
725+ const baseUrl = 'https://LiaScript.github.io/course/?' + readmeUrl
726+ let image : string = overwrite ( course . logo , lia . definition ?. logo ) || ''
727+ if ( image && ! image . startsWith ( 'http:' ) && ! image . startsWith ( 'https:' ) ) {
728+ try {
729+ image = new URL ( image , readmeUrl ) . toString ( )
730+ } catch ( _ ) { }
731+ }
708732
709733 let tags : string [ ] = [ ]
710734 try {
@@ -716,25 +740,14 @@ function buildCourseSearchEntries(course: any): any[] {
716740 tags = [ ]
717741 }
718742
719- const entries : any [ ] = [ ]
720743 const sections : any [ ] = lia . sections ? Array . from ( lia . sections ) : [ ]
744+ const s = sections . map ( ( sec : any ) => [
745+ inlineToText ( sec . title ) . trim ( ) ,
746+ markdownToText ( sec . code || '' ) ,
747+ sec . indentation ?? 1 ,
748+ ] )
721749
722- for ( let i = 0 ; i < sections . length ; i ++ ) {
723- const sec = sections [ i ]
724- const sectionTitle = inlineToText ( sec . title ) . trim ( )
725- const sectionContent = markdownToText ( sec . code || '' )
726- entries . push ( {
727- courseTitle,
728- sectionTitle,
729- sectionContent,
730- tags,
731- image,
732- url : courseUrl + '#' + ( i + 1 ) ,
733- indentation : sec . indentation ?? 1 ,
734- } )
735- }
736-
737- return entries
750+ return { t : courseTitle , g : tags , i : image , u : baseUrl , s }
738751}
739752
740753function meta ( json : any ) {
@@ -824,7 +837,7 @@ async function toCard(
824837 argument : any ,
825838 course : any ,
826839 small : boolean = false ,
827- ) : Promise < { html : string ; json : any ; searchEntries : any [ ] } > {
840+ ) : Promise < { html : string ; json : any ; searchEntry : any | null } > {
828841 // if other parameters are defined for a specific course
829842 // then they are treated
830843
@@ -996,7 +1009,7 @@ async function toCard(
9961009 overwrite ( course . logo , course . data . lia . definition . logo ) ,
9971010 ) ,
9981011 json : await RDF . parse ( argument , course . data ) ,
999- searchEntries : buildCourseSearchEntries ( course ) ,
1012+ searchEntry : buildCourseSearchEntry ( course ) ,
10001013 }
10011014
10021015 return rslt
0 commit comments