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,167 @@
|
|||
import { expect, type Page, test } from '@playwright/test'
|
||||
import { openCommandPalette, executeCommand } from './helpers'
|
||||
|
||||
const LIST_ITEM_MARKER = /^[-*+]\s/
|
||||
const HEADING_MARKER = /^#{1,6}\s/
|
||||
|
||||
type MarkdownContent = string
|
||||
type MarkdownLine = string
|
||||
type LineWindow = {
|
||||
line: MarkdownLine
|
||||
nextLine: MarkdownLine
|
||||
lineAfter: MarkdownLine
|
||||
}
|
||||
|
||||
async function openFirstNoteInBlockEditor(page: Page) {
|
||||
const noteListContainer = page.locator('[data-testid="note-list-container"]')
|
||||
await noteListContainer.waitFor({ timeout: 5000 })
|
||||
await noteListContainer.locator('.cursor-pointer').first().click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
const editorContainer = page.locator('.bn-editor')
|
||||
await expect(editorContainer).toBeVisible({ timeout: 5000 })
|
||||
return editorContainer
|
||||
}
|
||||
|
||||
async function triggerSerialization(page: Page) {
|
||||
const editorContainer = await openFirstNoteInBlockEditor(page)
|
||||
await editorContainer.click()
|
||||
await page.keyboard.press('End')
|
||||
await page.keyboard.type(' ')
|
||||
await page.waitForTimeout(300)
|
||||
}
|
||||
|
||||
async function toggleRawEditor(page: Page) {
|
||||
await openCommandPalette(page)
|
||||
await executeCommand(page, 'Toggle Raw')
|
||||
await page.waitForTimeout(500)
|
||||
}
|
||||
|
||||
async function readRawEditorContent(page: Page) {
|
||||
const rawEditor = page.locator('[data-testid="raw-editor-codemirror"]')
|
||||
await expect(rawEditor).toBeVisible({ timeout: 5000 })
|
||||
|
||||
return page.evaluate(() => {
|
||||
const el = document.querySelector('[data-testid="raw-editor-codemirror"]')
|
||||
const cm = el?.querySelector('.cm-content')
|
||||
return cm?.textContent ?? ''
|
||||
})
|
||||
}
|
||||
|
||||
function isBlankLine(line?: MarkdownLine) {
|
||||
return line?.trim() === ''
|
||||
}
|
||||
|
||||
function isListItem(line?: MarkdownLine) {
|
||||
return LIST_ITEM_MARKER.test(line?.trim() ?? '')
|
||||
}
|
||||
|
||||
function isHeading(line?: MarkdownLine) {
|
||||
return HEADING_MARKER.test(line?.trim() ?? '')
|
||||
}
|
||||
|
||||
function hasBlankLineBetweenListItems(window: LineWindow) {
|
||||
if (!isListItem(window.line)) {
|
||||
return false
|
||||
}
|
||||
if (!isBlankLine(window.nextLine)) {
|
||||
return false
|
||||
}
|
||||
return isListItem(window.lineAfter)
|
||||
}
|
||||
|
||||
function hasExtraBlankLinesAfterHeading(window: LineWindow) {
|
||||
if (!isHeading(window.line)) {
|
||||
return false
|
||||
}
|
||||
if (!isBlankLine(window.nextLine)) {
|
||||
return false
|
||||
}
|
||||
return isBlankLine(window.lineAfter)
|
||||
}
|
||||
|
||||
function findThreeLineViolation(
|
||||
rawContent: MarkdownContent,
|
||||
hasViolation: (window: LineWindow) => boolean,
|
||||
) {
|
||||
const lines = rawContent.split('\n')
|
||||
for (let i = 0; i < lines.length - 2; i++) {
|
||||
if (hasViolation({ line: lines[i], nextLine: lines[i + 1], lineAfter: lines[i + 2] })) {
|
||||
return { index: i, lines }
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function expectNoBlankLinesBetweenListItems(rawContent: MarkdownContent) {
|
||||
const violation = findThreeLineViolation(rawContent, hasBlankLineBetweenListItems)
|
||||
if (!violation) {
|
||||
return
|
||||
}
|
||||
|
||||
const line = violation.lines[violation.index]
|
||||
const lineAfter = violation.lines[violation.index + 2]
|
||||
throw new Error(
|
||||
`Found blank line between list items at line ${violation.index + 1}:\n` +
|
||||
` "${line}"\n (blank)\n "${lineAfter}"\n` +
|
||||
'This indicates the serializer is adding extra blank lines between list items.',
|
||||
)
|
||||
}
|
||||
|
||||
function expectNoExtraBlankLinesAfterHeadings(rawContent: MarkdownContent) {
|
||||
const violation = findThreeLineViolation(rawContent, hasExtraBlankLinesAfterHeading)
|
||||
if (!violation) {
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Found multiple blank lines after heading at line ${violation.index + 1}:\n` +
|
||||
` "${violation.lines[violation.index]}"\n (blank)\n (blank)\n` +
|
||||
'Headings should have at most one blank line after them.',
|
||||
)
|
||||
}
|
||||
|
||||
test.describe('BlockNote serializer blank lines fix', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.setViewportSize({ width: 1600, height: 900 })
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
})
|
||||
|
||||
test('tight lists are serialized without blank lines between items', async ({ page }) => {
|
||||
await triggerSerialization(page)
|
||||
await toggleRawEditor(page)
|
||||
const rawContent = await readRawEditorContent(page)
|
||||
|
||||
// The mock content has bullet list items like "- First level item"
|
||||
// After BlockNote serialization, they should still be tight (no blank lines)
|
||||
expect(rawContent).toBeTruthy()
|
||||
expectNoBlankLinesBetweenListItems(rawContent)
|
||||
})
|
||||
|
||||
test('saving without editing does not add whitespace changes', async ({ page }) => {
|
||||
await openFirstNoteInBlockEditor(page)
|
||||
|
||||
await toggleRawEditor(page)
|
||||
const contentBefore = await readRawEditorContent(page)
|
||||
|
||||
await toggleRawEditor(page)
|
||||
|
||||
// Just click the editor without typing
|
||||
await page.locator('.bn-editor').click()
|
||||
await page.waitForTimeout(300)
|
||||
|
||||
await toggleRawEditor(page)
|
||||
const contentAfter = await readRawEditorContent(page)
|
||||
|
||||
expect(contentAfter).toBe(contentBefore)
|
||||
})
|
||||
|
||||
test('headings do not have extra blank lines added after them', async ({ page }) => {
|
||||
await triggerSerialization(page)
|
||||
await toggleRawEditor(page)
|
||||
const rawContent = await readRawEditorContent(page)
|
||||
|
||||
expectNoExtraBlankLinesAfterHeadings(rawContent)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue