feat: publish HoloLake model-native living system source
This commit is contained in:
parent
6ad10edde1
commit
c395dd3a99
2467 changed files with 615073 additions and 0 deletions
|
|
@ -0,0 +1,311 @@
|
|||
type TocLevel = 1 | 2 | 3
|
||||
|
||||
interface TocInlineText {
|
||||
type?: string
|
||||
text?: string
|
||||
}
|
||||
|
||||
interface TocBlock {
|
||||
id?: string
|
||||
type?: string
|
||||
props?: { level?: number }
|
||||
content?: TocInlineText[]
|
||||
}
|
||||
|
||||
interface MarkdownHeading {
|
||||
blockId?: string
|
||||
level: TocLevel
|
||||
title: string
|
||||
}
|
||||
|
||||
interface HeadingTitlePair {
|
||||
entryTitle: string
|
||||
title: string
|
||||
}
|
||||
|
||||
interface DuplicateHeadingCheck extends HeadingTitlePair {
|
||||
headingIndex: number
|
||||
level: TocLevel
|
||||
}
|
||||
|
||||
interface VisibleHeadings {
|
||||
headings: MarkdownHeading[]
|
||||
titleBlockId?: string
|
||||
}
|
||||
|
||||
interface HeadingBlockMatch {
|
||||
blocks: unknown[]
|
||||
entryTitle: string
|
||||
headings: MarkdownHeading[]
|
||||
}
|
||||
|
||||
interface MarkdownCodeFence {
|
||||
marker: string
|
||||
size: number
|
||||
}
|
||||
|
||||
export interface TocItem {
|
||||
blockId?: string
|
||||
children: TocItem[]
|
||||
id: string
|
||||
level: TocLevel
|
||||
matchIndex?: number
|
||||
title: string
|
||||
}
|
||||
|
||||
function isTocLevel(value: number | undefined): value is TocLevel {
|
||||
return value === 1 || value === 2 || value === 3
|
||||
}
|
||||
|
||||
function headingText(block: TocBlock): string {
|
||||
if (!Array.isArray(block.content)) return ''
|
||||
return block.content
|
||||
.filter((item) => item.type === 'text')
|
||||
.map((item) => item.text ?? '')
|
||||
.join('')
|
||||
.trim()
|
||||
}
|
||||
|
||||
function normalizeHeadingTitle({ title }: { title: string }): string {
|
||||
return title.trim().replace(/\s+/g, ' ')
|
||||
}
|
||||
|
||||
function sameHeadingTitle({ entryTitle, title }: HeadingTitlePair): boolean {
|
||||
return normalizeHeadingTitle({ title }) === normalizeHeadingTitle({ title: entryTitle })
|
||||
}
|
||||
|
||||
function isHeadingBlock(block: unknown): block is TocBlock {
|
||||
return typeof block === 'object'
|
||||
&& block !== null
|
||||
&& !Array.isArray(block)
|
||||
&& (block as TocBlock).type === 'heading'
|
||||
&& isTocLevel((block as TocBlock).props?.level)
|
||||
}
|
||||
|
||||
function tocLevelForBlock(block: TocBlock): TocLevel | null {
|
||||
const level = block.props?.level
|
||||
return isTocLevel(level) ? level : null
|
||||
}
|
||||
|
||||
function nearestParent(stack: TocItem[], level: TocLevel): TocItem {
|
||||
for (let index = stack.length - 1; index >= 0; index -= 1) {
|
||||
const item = stack.at(index)
|
||||
if (item && item.level < level) return item
|
||||
}
|
||||
return stack.at(0)!
|
||||
}
|
||||
|
||||
function appendTocHeading(stack: TocItem[], item: TocItem) {
|
||||
const parent = nearestParent(stack, item.level)
|
||||
parent.children.push(item)
|
||||
Reflect.set(stack, item.level, item)
|
||||
stack.length = item.level + 1
|
||||
}
|
||||
|
||||
function shouldSkipDuplicateTitleHeading({ entryTitle, title, level, headingIndex }: DuplicateHeadingCheck): boolean {
|
||||
return headingIndex === 0
|
||||
&& level === 1
|
||||
&& sameHeadingTitle({ entryTitle, title })
|
||||
}
|
||||
|
||||
function visibleHeadingsForEntry(entryTitle: string, headings: MarkdownHeading[]): VisibleHeadings {
|
||||
return headings.reduce<VisibleHeadings>((result, heading, index) => {
|
||||
if (shouldSkipDuplicateTitleHeading({
|
||||
entryTitle,
|
||||
title: heading.title,
|
||||
level: heading.level,
|
||||
headingIndex: index,
|
||||
})) {
|
||||
return { ...result, titleBlockId: heading.blockId }
|
||||
}
|
||||
result.headings.push(heading)
|
||||
return result
|
||||
}, { headings: [] })
|
||||
}
|
||||
|
||||
export function buildTableOfContents(entryTitle: string, blocks: unknown[]): TocItem {
|
||||
const root: TocItem = { id: 'toc-title', level: 1, title: entryTitle, children: [] }
|
||||
const stack: TocItem[] = [root]
|
||||
let headingCount = 0
|
||||
|
||||
blocks.forEach((block, index) => {
|
||||
if (!isHeadingBlock(block)) return
|
||||
const title = headingText(block)
|
||||
if (!title) return
|
||||
|
||||
const level = tocLevelForBlock(block)
|
||||
if (level === null) return
|
||||
|
||||
if (shouldSkipDuplicateTitleHeading({ entryTitle, title, level, headingIndex: headingCount })) {
|
||||
root.blockId = block.id
|
||||
headingCount += 1
|
||||
return
|
||||
}
|
||||
|
||||
const item: TocItem = {
|
||||
blockId: block.id,
|
||||
children: [],
|
||||
id: block.id ?? `toc-heading-${index}`,
|
||||
level,
|
||||
matchIndex: headingCount - (root.blockId ? 1 : 0),
|
||||
title,
|
||||
}
|
||||
appendTocHeading(stack, item)
|
||||
headingCount += 1
|
||||
})
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
function stripFrontmatter({ markdown }: { markdown: string }): string {
|
||||
if (!markdown.startsWith('---')) return markdown
|
||||
const delimiter = markdown.indexOf('\n---', 3)
|
||||
if (delimiter === -1) return markdown
|
||||
const afterDelimiter = markdown.indexOf('\n', delimiter + 4)
|
||||
return afterDelimiter === -1 ? '' : markdown.slice(afterDelimiter + 1)
|
||||
}
|
||||
|
||||
function stripInlineMarkdown({ text }: { text: string }): string {
|
||||
return text
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
.replace(/\[\[[^|\]]+\|([^\]]+)\]\]/g, '$1')
|
||||
.replace(/\[\[([^\]]+)\]\]/g, '$1')
|
||||
.replace(/[*_`~]/g, '')
|
||||
.trim()
|
||||
}
|
||||
|
||||
function codeFenceForLine(line: string): MarkdownCodeFence | null {
|
||||
const match = line.match(/^ {0,3}(`{3,}|~{3,})/)
|
||||
const fence = match?.at(1)
|
||||
if (!fence) return null
|
||||
return { marker: fence.charAt(0), size: fence.length }
|
||||
}
|
||||
|
||||
function closesCodeFence(line: string, codeFence: MarkdownCodeFence): boolean {
|
||||
const match = line.match(/^ {0,3}(`{3,}|~{3,})\s*$/)
|
||||
const fence = match?.at(1)
|
||||
return fence !== undefined
|
||||
&& fence.charAt(0) === codeFence.marker
|
||||
&& fence.length >= codeFence.size
|
||||
}
|
||||
|
||||
function parseMarkdownHeading(line: string): MarkdownHeading | null {
|
||||
const match = line.match(/^(#{1,3})\s+(.+?)\s*#*\s*$/)
|
||||
if (!match) return null
|
||||
const title = stripInlineMarkdown({ text: match.at(2)! })
|
||||
return title.length > 0
|
||||
? { level: match.at(1)!.length as TocLevel, title }
|
||||
: null
|
||||
}
|
||||
|
||||
function parseMarkdownHeadings({ markdown }: { markdown: string }): MarkdownHeading[] {
|
||||
const headings: MarkdownHeading[] = []
|
||||
let codeFence: MarkdownCodeFence | null = null
|
||||
|
||||
stripFrontmatter({ markdown }).split('\n').forEach((line) => {
|
||||
if (codeFence) {
|
||||
if (closesCodeFence(line, codeFence)) codeFence = null
|
||||
return
|
||||
}
|
||||
|
||||
codeFence = codeFenceForLine(line)
|
||||
if (codeFence) return
|
||||
|
||||
const heading = parseMarkdownHeading(line)
|
||||
if (heading) headings.push(heading)
|
||||
})
|
||||
|
||||
return headings
|
||||
}
|
||||
|
||||
function parsedBlockHeadings(blocks: unknown[]): MarkdownHeading[] {
|
||||
return blocks
|
||||
.filter(isHeadingBlock)
|
||||
.flatMap((block) => {
|
||||
const level = tocLevelForBlock(block)
|
||||
if (level === null) return []
|
||||
return [{
|
||||
blockId: block.id,
|
||||
level,
|
||||
title: headingText(block),
|
||||
}]
|
||||
})
|
||||
.filter((heading) => heading.title.length > 0)
|
||||
}
|
||||
|
||||
function blockIdsForMatchingHeadings({ blocks, entryTitle, headings }: HeadingBlockMatch): VisibleHeadings {
|
||||
const visibleBlocks = visibleHeadingsForEntry(entryTitle, parsedBlockHeadings(blocks))
|
||||
const visibleMarkdown = visibleHeadingsForEntry(entryTitle, headings)
|
||||
if (visibleBlocks.headings.length !== visibleMarkdown.headings.length) return visibleMarkdown
|
||||
|
||||
const blockIds = visibleBlocks.headings.map((blockHeading, index) => {
|
||||
const heading = visibleMarkdown.headings.at(index)
|
||||
if (!heading) return undefined
|
||||
if (blockHeading.level !== heading.level) return undefined
|
||||
if (!sameHeadingTitle({ entryTitle: blockHeading.title, title: heading.title })) return undefined
|
||||
return blockHeading.blockId
|
||||
})
|
||||
if (blockIds.includes(undefined)) return visibleMarkdown
|
||||
|
||||
return {
|
||||
headings: visibleMarkdown.headings.map((heading, index) => ({
|
||||
...heading,
|
||||
blockId: blockIds.at(index),
|
||||
})),
|
||||
titleBlockId: visibleBlocks.titleBlockId,
|
||||
}
|
||||
}
|
||||
|
||||
function tocItemMatchesHeading(item: TocItem, heading: MarkdownHeading | undefined): heading is MarkdownHeading {
|
||||
return heading !== undefined
|
||||
&& heading.level === item.level
|
||||
&& sameHeadingTitle({ entryTitle: heading.title, title: item.title })
|
||||
}
|
||||
|
||||
function indexedHeadingForTocItem(item: TocItem, headings: MarkdownHeading[]): MarkdownHeading | undefined {
|
||||
return item.matchIndex === undefined ? undefined : headings.at(item.matchIndex)
|
||||
}
|
||||
|
||||
function matchingHeadingForTocItem(item: TocItem, headings: MarkdownHeading[]): MarkdownHeading | undefined {
|
||||
const indexedHeading = indexedHeadingForTocItem(item, headings)
|
||||
return tocItemMatchesHeading(item, indexedHeading)
|
||||
? indexedHeading
|
||||
: headings.find((heading) => tocItemMatchesHeading(item, heading))
|
||||
}
|
||||
|
||||
export function resolveTocItemBlockId(entryTitle: string, item: TocItem, blocks: unknown[]): string | undefined {
|
||||
if (item.blockId) return item.blockId
|
||||
const visibleBlocks = visibleHeadingsForEntry(entryTitle, parsedBlockHeadings(blocks))
|
||||
if (item.id === 'toc-title') return visibleBlocks.titleBlockId
|
||||
return matchingHeadingForTocItem(item, visibleBlocks.headings)?.blockId
|
||||
}
|
||||
|
||||
export function buildTableOfContentsFromMarkdown(entryTitle: string, markdown: string, blocks: unknown[] = []): TocItem {
|
||||
const headings = parseMarkdownHeadings({ markdown })
|
||||
const visibleHeadings = blockIdsForMatchingHeadings({ blocks, entryTitle, headings })
|
||||
const root: TocItem = {
|
||||
blockId: visibleHeadings.titleBlockId,
|
||||
id: 'toc-title',
|
||||
level: 1,
|
||||
title: entryTitle,
|
||||
children: [],
|
||||
}
|
||||
const stack: TocItem[] = [root]
|
||||
|
||||
visibleHeadings.headings.forEach((heading, index) => {
|
||||
appendTocHeading(stack, {
|
||||
blockId: heading.blockId,
|
||||
children: [],
|
||||
id: heading.blockId ?? `toc-heading-${index}`,
|
||||
level: heading.level,
|
||||
matchIndex: index,
|
||||
title: heading.title,
|
||||
})
|
||||
})
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
export function buildTableOfContentsFromMarkdownOnly(entryTitle: string, markdown: string): TocItem {
|
||||
return buildTableOfContentsFromMarkdown(entryTitle, markdown)
|
||||
}
|
||||
Loading…
Reference in a new issue