| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Combine from "./Combine" | 
					
						
							|  |  |  | import BaseUIElement from "../BaseUIElement" | 
					
						
							|  |  |  | import { Translation } from "../i18n/Translation" | 
					
						
							|  |  |  | import { FixedUiElement } from "./FixedUiElement" | 
					
						
							|  |  |  | import Title from "./Title" | 
					
						
							|  |  |  | import List from "./List" | 
					
						
							|  |  |  | import Hash from "../../Logic/Web/Hash" | 
					
						
							|  |  |  | import Link from "./Link" | 
					
						
							|  |  |  | import { Utils } from "../../Utils" | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class TableOfContents extends Combine { | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |     private readonly titles: Title[] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     constructor( | 
					
						
							|  |  |  |         elements: Combine | Title[], | 
					
						
							|  |  |  |         options?: { | 
					
						
							|  |  |  |             noTopLevel: false | boolean | 
					
						
							|  |  |  |             maxDepth?: number | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         let titles: Title[] | 
					
						
							|  |  |  |         if (elements instanceof Combine) { | 
					
						
							| 
									
										
										
										
											2022-01-25 21:55:51 +01:00
										 |  |  |             titles = TableOfContents.getTitles(elements.getElements()) ?? [] | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-01-25 21:55:51 +01:00
										 |  |  |             titles = elements ?? [] | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         let els: { level: number; content: BaseUIElement }[] = [] | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         for (const title of titles) { | 
					
						
							|  |  |  |             let content: BaseUIElement | 
					
						
							|  |  |  |             if (title.title instanceof Translation) { | 
					
						
							|  |  |  |                 content = title.title.Clone() | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             } else if (title.title instanceof FixedUiElement) { | 
					
						
							| 
									
										
										
										
											2022-01-25 21:55:51 +01:00
										 |  |  |                 content = new FixedUiElement(title.title.content) | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             } else if (Utils.runningFromConsole) { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |                 content = new FixedUiElement(title.AsMarkdown()) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             } else if (title["title"] !== undefined) { | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |                 content = new FixedUiElement(title.title.ConstructElement().textContent) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2022-01-25 21:55:51 +01:00
										 |  |  |                 console.log("Not generating a title for ", title) | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const vis = new Link(content, "#" + title.id) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             Hash.hash.addCallbackAndRun((h) => { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |                 if (h === title.id) { | 
					
						
							|  |  |  |                     vis.SetClass("font-bold") | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     vis.RemoveClass("font-bold") | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             els.push({ level: title.level, content: vis }) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const minLevel = Math.min(...els.map((e) => e.level)) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         if (options?.noTopLevel) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             els = els.filter((e) => e.level !== minLevel) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (options?.maxDepth) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             els = els.filter((e) => e.level <= options.maxDepth + minLevel) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super(TableOfContents.mergeLevel(els).map((el) => el.SetClass("mt-2"))) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         this.SetClass("flex flex-col") | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.titles = titles | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |     private static getTitles(elements: BaseUIElement[]): Title[] { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         const titles = [] | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |         for (const uiElement of elements) { | 
					
						
							|  |  |  |             if (uiElement instanceof Combine) { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |                 titles.push(...TableOfContents.getTitles(uiElement.getElements())) | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             } else if (uiElement instanceof Title) { | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |                 titles.push(uiElement) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return titles | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private static mergeLevel( | 
					
						
							|  |  |  |         elements: { level: number; content: BaseUIElement }[] | 
					
						
							|  |  |  |     ): BaseUIElement[] { | 
					
						
							|  |  |  |         const maxLevel = Math.max(...elements.map((e) => e.level)) | 
					
						
							|  |  |  |         const minLevel = Math.min(...elements.map((e) => e.level)) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         if (maxLevel === minLevel) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             return elements.map((e) => e.content) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const result: { level: number; content: BaseUIElement }[] = [] | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         let running: BaseUIElement[] = [] | 
					
						
							|  |  |  |         for (const element of elements) { | 
					
						
							|  |  |  |             if (element.level === maxLevel) { | 
					
						
							|  |  |  |                 running.push(element.content) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (running.length !== undefined) { | 
					
						
							|  |  |  |                 result.push({ | 
					
						
							|  |  |  |                     content: new List(running), | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     level: maxLevel - 1, | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |                 }) | 
					
						
							|  |  |  |                 running = [] | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             result.push(element) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (running.length !== undefined) { | 
					
						
							|  |  |  |             result.push({ | 
					
						
							|  |  |  |                 content: new List(running), | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 level: maxLevel - 1, | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return TableOfContents.mergeLevel(result) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     AsMarkdown(): string { | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |         const depthIcons = ["1.", "  -", "    +", "      *"] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const lines = ["## Table of contents\n"] | 
					
						
							|  |  |  |         const minLevel = Math.min(...this.titles.map((t) => t.level)) | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         for (const title of this.titles) { | 
					
						
							|  |  |  |             const prefix = depthIcons[title.level - minLevel] ?? "        ~" | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             const text = title.title.AsMarkdown().replace("\n", "") | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |             const link = title.id | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  |             lines.push(prefix + " [" + text + "](#" + link + ")") | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-01-18 18:52:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return lines.join("\n") + "\n\n" | 
					
						
							| 
									
										
										
										
											2021-11-30 22:50:48 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |