Fix: add workaround for limited html conversion, add documentation and cleanup some code

This commit is contained in:
Pieter Vander Vennet 2025-06-26 02:29:11 +02:00
parent 24cb539559
commit de402a7d84
2 changed files with 22 additions and 15 deletions

View file

@ -141,7 +141,9 @@ export class GenerateDocs extends Script {
this.WriteMarkdownFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), [
"src/UI/SpecialVisualizations.ts",
])
], {
tocMaxDepth: 3
})
if (!existsSync("./Docs/Themes")) {
mkdirSync("./Docs/Themes")
@ -217,7 +219,8 @@ export class GenerateDocs extends Script {
markdown: string,
autogenSource: string[],
options?: {
noTableOfContents?: boolean
noTableOfContents?: boolean,
tocMaxDepth?: number
}
): void {
for (const source of autogenSource) {
@ -236,7 +239,7 @@ export class GenerateDocs extends Script {
let md = markdown
if (options?.noTableOfContents !== false) {
md = TableOfContents.insertTocIntoMd(md)
md = TableOfContents.insertTocIntoMd(md, options?.tocMaxDepth)
}
md = md.replace(/\n\n\n+/g, "\n\n")

View file

@ -48,13 +48,21 @@ export default class TableOfContents {
return TableOfContents.mergeLevel(result)
}
public static insertTocIntoMd(md: string): string {
const htmlSource = <string>marked.parse(md)
public static insertTocIntoMd(md: string, maxDepth: number): string {
// parse_html has a limit on how much html it can parse. We strip away the actual content, only keeping the titles
const mdStripped = md.split("\n\n").filter(l => l.trim().startsWith("#")).join("\n\n")
const htmlSource = <string>marked.parse(mdStripped)
const el = parse_html(htmlSource)
const structure = TableOfContents.generateStructure(<any>el)
if(structure.length <= 1){
return md
}
const firstTitle = structure[1]
let minDepth = undefined
do {
// The document probably has a _single_ title at the top, denoting the title of the document
// We don't care for that title in the table of content; it'll just be clutter and use a single, valuable level
// So: we search this element, check if there indeed is only one and, if that is the case, erase it
minDepth = Math.min(...structure.map((s) => s.depth))
const minDepthCount = structure.filter((s) => s.depth === minDepth)
if (minDepthCount.length > 1) {
@ -65,6 +73,7 @@ export default class TableOfContents {
structure.findIndex((s) => s.depth === minDepth),
1
)
// As long as we have a lone top level, we continue cleaning up; hence the 'do-while'
} while (structure.length > 0)
if (structure.length <= 1) {
@ -84,7 +93,7 @@ export default class TableOfContents {
if (depthDiff === 0) {
topLevelCount++
toc += `${topLevelCount}. ${link}\n`
} else if (depthDiff <= 3) {
} else if (depthDiff <= 3 &&(maxDepth === undefined || depthDiff < maxDepth)) {
toc += `${separators[depthDiff]} ${link}\n`
}
}
@ -101,23 +110,18 @@ export default class TableOfContents {
}
public static generateStructure(
html: Element
html: Element | ChildNode
): { depth: number; title: string; el: Element }[] {
if (html === undefined) {
return []
}
return [].concat(
...Array.from(html.childNodes ?? []).map((child) => {
return Array.from(html.childNodes ?? []).flatMap((child) => {
const tag: string = child["tagName"]?.toLowerCase()
if (!tag) {
return []
}
if (tag.match(/h[0-9]/)) {
if (tag?.match(/h[0-9]/)) {
const depth = Number(tag.substring(1))
return [{ depth, title: child.textContent, el: child }]
return [{ depth, title: child.textContent, el: <Element> child }]
}
return TableOfContents.generateStructure(<Element>child)
})
)
}
}