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,212 @@
|
|||
import { describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
MERMAID_BLOCK_TYPE,
|
||||
injectMermaidInBlocks,
|
||||
preProcessMermaidMarkdown,
|
||||
} from './mermaidMarkdown'
|
||||
import { serializeDurableEditorBlocks } from './editorDurableMarkdown'
|
||||
import { TLDRAW_BLOCK_TYPE } from './tldrawMarkdown'
|
||||
|
||||
describe('mermaid markdown round-trip', () => {
|
||||
it('injects fenced Mermaid source into dedicated diagram blocks', () => {
|
||||
const markdown = [
|
||||
'```mermaid',
|
||||
'flowchart LR',
|
||||
' A --> B',
|
||||
'```',
|
||||
].join('\n')
|
||||
const preprocessed = preProcessMermaidMarkdown({ markdown })
|
||||
const blocks = [{
|
||||
type: 'paragraph',
|
||||
content: [{ type: 'text', text: preprocessed, styles: {} }],
|
||||
children: [],
|
||||
}]
|
||||
|
||||
const [block] = injectMermaidInBlocks(blocks) as Array<{
|
||||
type: string
|
||||
props: { source: string; diagram: string }
|
||||
}>
|
||||
|
||||
expect(block.type).toBe(MERMAID_BLOCK_TYPE)
|
||||
expect(block.props.source).toBe(markdown)
|
||||
expect(block.props.diagram).toBe('flowchart LR\n A --> B\n')
|
||||
})
|
||||
|
||||
it('restores token paragraphs split across inline text spans', () => {
|
||||
const markdown = [
|
||||
'```mermaid',
|
||||
'flowchart TD',
|
||||
' A["alpha_beta"] --> B["ok"]',
|
||||
'```',
|
||||
].join('\n')
|
||||
const token = preProcessMermaidMarkdown({ markdown })
|
||||
const splitPoint = Math.floor(token.length / 2)
|
||||
const [block] = injectMermaidInBlocks([{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{ type: 'text', text: token.slice(0, splitPoint), styles: {} },
|
||||
{ type: 'text', text: token.slice(splitPoint), styles: { italic: true } },
|
||||
],
|
||||
children: [],
|
||||
}]) as Array<{
|
||||
type: string
|
||||
props?: { source: string; diagram: string }
|
||||
content?: Array<{ text?: string }>
|
||||
}>
|
||||
|
||||
expect(block.type).toBe(MERMAID_BLOCK_TYPE)
|
||||
expect(block.props).toMatchObject({
|
||||
source: markdown,
|
||||
diagram: 'flowchart TD\n A["alpha_beta"] --> B["ok"]\n',
|
||||
})
|
||||
})
|
||||
|
||||
it('does not erase non-text inline content while reading durable tokens', () => {
|
||||
const markdown = [
|
||||
'```mermaid',
|
||||
'flowchart TD',
|
||||
' A --> B',
|
||||
'```',
|
||||
].join('\n')
|
||||
const token = preProcessMermaidMarkdown({ markdown })
|
||||
const splitPoint = Math.floor(token.length / 2)
|
||||
const [block] = injectMermaidInBlocks([{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{ type: 'text', text: token.slice(0, splitPoint), styles: {} },
|
||||
{ type: 'link', content: [{ type: 'text', text: 'external', styles: {} }] },
|
||||
{ type: 'text', text: token.slice(splitPoint), styles: {} },
|
||||
],
|
||||
children: [],
|
||||
}]) as Array<{
|
||||
type: string
|
||||
content?: Array<{ type?: string; text?: string }>
|
||||
}>
|
||||
|
||||
expect(block.type).toBe('paragraph')
|
||||
expect(block.content).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('preserves multiple Mermaid blocks independently when serializing', () => {
|
||||
const editor = {
|
||||
blocksToMarkdownLossy: vi.fn((blocks: unknown[]) => {
|
||||
return (blocks as Array<{ content?: Array<{ text?: string }> }>)
|
||||
.map((block) => block.content?.map((item) => item.text ?? '').join('') ?? '')
|
||||
.join('\n\n')
|
||||
}),
|
||||
}
|
||||
const firstSource = '```mermaid\nflowchart TD\nA --> B\n```'
|
||||
const secondSource = '~~~mermaid\nsequenceDiagram\nAlice->>Bob: Hi\n~~~'
|
||||
const blocks = [
|
||||
{ type: 'paragraph', content: [{ type: 'text', text: 'Intro' }], children: [] },
|
||||
{ type: MERMAID_BLOCK_TYPE, props: { source: firstSource, diagram: 'flowchart TD\nA --> B\n' }, children: [] },
|
||||
{ type: 'paragraph', content: [{ type: 'text', text: 'Between' }], children: [] },
|
||||
{ type: MERMAID_BLOCK_TYPE, props: { source: secondSource, diagram: 'sequenceDiagram\nAlice->>Bob: Hi\n' }, children: [] },
|
||||
]
|
||||
|
||||
expect(serializeDurableEditorBlocks(editor, blocks)).toBe([
|
||||
'Intro',
|
||||
firstSource,
|
||||
'Between',
|
||||
secondSource,
|
||||
].join('\n\n'))
|
||||
})
|
||||
|
||||
it('injects parsed Mermaid code blocks into dedicated diagram blocks', () => {
|
||||
const [block] = injectMermaidInBlocks([{
|
||||
type: 'codeBlock',
|
||||
props: { language: 'mermaid' },
|
||||
content: [{ type: 'text', text: 'flowchart LR\n A --> B', styles: {} }],
|
||||
children: [],
|
||||
}]) as Array<{
|
||||
type: string
|
||||
props: { source: string; diagram: string }
|
||||
}>
|
||||
|
||||
expect(block.type).toBe(MERMAID_BLOCK_TYPE)
|
||||
expect(block.props.source).toBe('```mermaid\nflowchart LR\n A --> B\n```')
|
||||
expect(block.props.diagram).toBe('flowchart LR\n A --> B\n')
|
||||
})
|
||||
|
||||
it('injects Mermaid-looking text code blocks when the parser drops the language', () => {
|
||||
const [block] = injectMermaidInBlocks([{
|
||||
type: 'codeBlock',
|
||||
props: { language: 'text' },
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: [
|
||||
"%%{init: {'theme':'base'}}%%",
|
||||
'flowchart TD',
|
||||
' A --> B',
|
||||
].join('\n'),
|
||||
styles: {},
|
||||
}],
|
||||
children: [],
|
||||
}]) as Array<{
|
||||
type: string
|
||||
props: { source: string; diagram: string }
|
||||
}>
|
||||
|
||||
expect(block.type).toBe(MERMAID_BLOCK_TYPE)
|
||||
expect(block.props.source).toContain('```mermaid\n')
|
||||
expect(block.props.diagram).toContain('flowchart TD\n A --> B\n')
|
||||
})
|
||||
|
||||
it('keeps ordinary text code blocks unchanged', () => {
|
||||
const [block] = injectMermaidInBlocks([{
|
||||
type: 'codeBlock',
|
||||
props: { language: 'text' },
|
||||
content: [{ type: 'text', text: 'const chart = "flowchart TD"', styles: {} }],
|
||||
children: [],
|
||||
}]) as Array<{ type: string }>
|
||||
|
||||
expect(block.type).toBe('codeBlock')
|
||||
})
|
||||
|
||||
it('leaves non-Mermaid and unclosed fences as normal Markdown', () => {
|
||||
const markdown = [
|
||||
'```ts',
|
||||
'const graph = "mermaid"',
|
||||
'```',
|
||||
'',
|
||||
'```mermaid',
|
||||
'flowchart LR',
|
||||
].join('\n')
|
||||
|
||||
expect(preProcessMermaidMarkdown({ markdown })).toBe(markdown)
|
||||
})
|
||||
|
||||
it('serializes fallback source for Mermaid blocks created without original fence text', () => {
|
||||
const editor = { blocksToMarkdownLossy: vi.fn(() => '') }
|
||||
const blocks = [{
|
||||
type: MERMAID_BLOCK_TYPE,
|
||||
props: { source: '', diagram: 'flowchart LR\nA --> B' },
|
||||
children: [],
|
||||
}]
|
||||
|
||||
expect(serializeDurableEditorBlocks(editor, blocks)).toBe(
|
||||
'```mermaid\nflowchart LR\nA --> B\n```',
|
||||
)
|
||||
})
|
||||
|
||||
it('serializes tldraw blocks beside Mermaid and ordinary Markdown', () => {
|
||||
const editor = {
|
||||
blocksToMarkdownLossy: vi.fn((blocks: unknown[]) => {
|
||||
return (blocks as Array<{ content?: Array<{ text?: string }> }>)
|
||||
.map((block) => block.content?.map((item) => item.text ?? '').join('') ?? '')
|
||||
.join('\n\n')
|
||||
}),
|
||||
}
|
||||
const blocks = [
|
||||
{ type: 'paragraph', content: [{ type: 'text', text: 'Intro' }], children: [] },
|
||||
{ type: TLDRAW_BLOCK_TYPE, props: { boardId: 'map', height: '640', snapshot: '{ "store": {} }', width: '900' }, children: [] },
|
||||
{ type: MERMAID_BLOCK_TYPE, props: { source: '', diagram: 'flowchart LR\nA --> B' }, children: [] },
|
||||
]
|
||||
|
||||
expect(serializeDurableEditorBlocks(editor, blocks)).toBe([
|
||||
'Intro',
|
||||
'```tldraw id="map" height="640" width="900"\n{ "store": {} }\n```',
|
||||
'```mermaid\nflowchart LR\nA --> B\n```',
|
||||
].join('\n\n'))
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue