forked from MapComplete/MapComplete
Fix: add workaround for limited html conversion, add documentation and cleanup some code
This commit is contained in:
parent
24cb539559
commit
de402a7d84
2 changed files with 22 additions and 15 deletions
|
@ -141,7 +141,9 @@ export class GenerateDocs extends Script {
|
||||||
|
|
||||||
this.WriteMarkdownFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), [
|
this.WriteMarkdownFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), [
|
||||||
"src/UI/SpecialVisualizations.ts",
|
"src/UI/SpecialVisualizations.ts",
|
||||||
])
|
], {
|
||||||
|
tocMaxDepth: 3
|
||||||
|
})
|
||||||
|
|
||||||
if (!existsSync("./Docs/Themes")) {
|
if (!existsSync("./Docs/Themes")) {
|
||||||
mkdirSync("./Docs/Themes")
|
mkdirSync("./Docs/Themes")
|
||||||
|
@ -217,7 +219,8 @@ export class GenerateDocs extends Script {
|
||||||
markdown: string,
|
markdown: string,
|
||||||
autogenSource: string[],
|
autogenSource: string[],
|
||||||
options?: {
|
options?: {
|
||||||
noTableOfContents?: boolean
|
noTableOfContents?: boolean,
|
||||||
|
tocMaxDepth?: number
|
||||||
}
|
}
|
||||||
): void {
|
): void {
|
||||||
for (const source of autogenSource) {
|
for (const source of autogenSource) {
|
||||||
|
@ -236,7 +239,7 @@ export class GenerateDocs extends Script {
|
||||||
let md = markdown
|
let md = markdown
|
||||||
|
|
||||||
if (options?.noTableOfContents !== false) {
|
if (options?.noTableOfContents !== false) {
|
||||||
md = TableOfContents.insertTocIntoMd(md)
|
md = TableOfContents.insertTocIntoMd(md, options?.tocMaxDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
md = md.replace(/\n\n\n+/g, "\n\n")
|
md = md.replace(/\n\n\n+/g, "\n\n")
|
||||||
|
|
|
@ -48,13 +48,21 @@ export default class TableOfContents {
|
||||||
return TableOfContents.mergeLevel(result)
|
return TableOfContents.mergeLevel(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static insertTocIntoMd(md: string): string {
|
public static insertTocIntoMd(md: string, maxDepth: number): string {
|
||||||
const htmlSource = <string>marked.parse(md)
|
// 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 el = parse_html(htmlSource)
|
||||||
const structure = TableOfContents.generateStructure(<any>el)
|
const structure = TableOfContents.generateStructure(<any>el)
|
||||||
|
if(structure.length <= 1){
|
||||||
|
return md
|
||||||
|
}
|
||||||
const firstTitle = structure[1]
|
const firstTitle = structure[1]
|
||||||
let minDepth = undefined
|
let minDepth = undefined
|
||||||
do {
|
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))
|
minDepth = Math.min(...structure.map((s) => s.depth))
|
||||||
const minDepthCount = structure.filter((s) => s.depth === minDepth)
|
const minDepthCount = structure.filter((s) => s.depth === minDepth)
|
||||||
if (minDepthCount.length > 1) {
|
if (minDepthCount.length > 1) {
|
||||||
|
@ -65,6 +73,7 @@ export default class TableOfContents {
|
||||||
structure.findIndex((s) => s.depth === minDepth),
|
structure.findIndex((s) => s.depth === minDepth),
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
// As long as we have a lone top level, we continue cleaning up; hence the 'do-while'
|
||||||
} while (structure.length > 0)
|
} while (structure.length > 0)
|
||||||
|
|
||||||
if (structure.length <= 1) {
|
if (structure.length <= 1) {
|
||||||
|
@ -84,7 +93,7 @@ export default class TableOfContents {
|
||||||
if (depthDiff === 0) {
|
if (depthDiff === 0) {
|
||||||
topLevelCount++
|
topLevelCount++
|
||||||
toc += `${topLevelCount}. ${link}\n`
|
toc += `${topLevelCount}. ${link}\n`
|
||||||
} else if (depthDiff <= 3) {
|
} else if (depthDiff <= 3 &&(maxDepth === undefined || depthDiff < maxDepth)) {
|
||||||
toc += `${separators[depthDiff]} ${link}\n`
|
toc += `${separators[depthDiff]} ${link}\n`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,23 +110,18 @@ export default class TableOfContents {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static generateStructure(
|
public static generateStructure(
|
||||||
html: Element
|
html: Element | ChildNode
|
||||||
): { depth: number; title: string; el: Element }[] {
|
): { depth: number; title: string; el: Element }[] {
|
||||||
if (html === undefined) {
|
if (html === undefined) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return [].concat(
|
return Array.from(html.childNodes ?? []).flatMap((child) => {
|
||||||
...Array.from(html.childNodes ?? []).map((child) => {
|
|
||||||
const tag: string = child["tagName"]?.toLowerCase()
|
const tag: string = child["tagName"]?.toLowerCase()
|
||||||
if (!tag) {
|
if (tag?.match(/h[0-9]/)) {
|
||||||
return []
|
|
||||||
}
|
|
||||||
if (tag.match(/h[0-9]/)) {
|
|
||||||
const depth = Number(tag.substring(1))
|
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)
|
return TableOfContents.generateStructure(<Element>child)
|
||||||
})
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue