Merge remote-tracking branch 'origin/master' into codex/pr-555-ci-fix

This commit is contained in:
creatixchu
2026-08-10 11:28:25 +08:00
86 changed files with 1026 additions and 370 deletions

View File

@@ -167,7 +167,11 @@ describe('QueueDock', () => {
expect(view.getByText('remove me')).toBeTruthy()
expect(view.getByText('second')).toBeTruthy()
act(() => { finishUpdate?.() })
expect(updateQueue).toHaveBeenCalledOnce()
await act(async () => {
finishUpdate?.()
await Promise.resolve()
})
await waitFor(() => {
expect(header).toHaveProperty('disabled', false)
expect(header.getAttribute('aria-expanded')).toBe('false')

View File

@@ -19,7 +19,7 @@
*/
import { createHighlighterCoreSync, createCssVariablesTheme } from 'shiki/core'
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
import { createJavaScriptRegexEngine, defaultJavaScriptRegexConstructor } from 'shiki/engine/javascript'
import langTs from '@shikijs/langs/typescript'
import langBash from '@shikijs/langs/shellscript'
import langJson from '@shikijs/langs/json'
@@ -139,15 +139,49 @@ const cssVariablesTheme = createCssVariablesTheme({
fontStyle: true,
})
/**
* The client regex engine compiles each TextMate pattern when its scanner is
* created. Shiki otherwise defers patterns longer than 3,000 characters until
* their first match; that compilation counts against Shiki's 500 ms per-line
* budget and can return a partial token stream under host contention. Eager
* compilation leaves the same budget in place for scanning user content.
*/
const regexEngine = createJavaScriptRegexEngine({
forgiving: true,
regexConstructor: pattern => defaultJavaScriptRegexConstructor(pattern, {
lazyCompileLength: Number.POSITIVE_INFINITY,
}),
})
let singleton: HighlighterCore | undefined
/** Representative paths through every boot grammar, compiled before user content is timed. */
const BOOT_GRAMMAR_WARMUPS = [
{ lang: 'typescript', code: 'const answer: number = 42' },
{ lang: 'shellscript', code: 'printf \'%s\\n\' "$HOME"' },
{ lang: 'json', code: '{"ready":true}' },
] as const
/** Construct and pre-tokenize the boot grammars outside the user-content scan budget. */
function createHighlighter(): HighlighterCore {
const instance = createHighlighterCoreSync({
themes: [cssVariablesTheme],
langs: LANGS,
engine: regexEngine,
})
for (const sample of BOOT_GRAMMAR_WARMUPS) {
instance.codeToTokens(sample.code, {
lang: sample.lang,
theme: 'css-variables',
tokenizeTimeLimit: 0,
})
}
return instance
}
/** The synchronous highlighter (one instance per document); pre-warmed below, lazy as the fallback. */
function highlighter(): HighlighterCore {
singleton ??= createHighlighterCoreSync({
themes: [cssVariablesTheme],
langs: LANGS,
engine: createJavaScriptRegexEngine({ forgiving: true }),
})
singleton ??= createHighlighter()
return singleton
}

View File

@@ -47,7 +47,7 @@ describe('highlightToHtml', () => {
// Once every grammar has registered, the same call highlights.
await vi.waitFor(() => {
for (const alias of LAZY_ALIASES) expect(highlightToHtml('x', alias)).toContain('shiki')
})
}, { timeout: 5_000 })
})
})

View File

@@ -58,7 +58,7 @@ const STREAM_DOC = [
describe('incremental streaming rendering', () => {
for (const chunkSize of [1, 3, 7, 16]) {
it(`matches a fresh render at every prefix (chunk=${chunkSize})`, () => {
it(`matches a fresh render at every prefix (chunk=${chunkSize})`, { timeout: 20_000 }, () => {
const live = render(<MarkdownText text="" streaming />)
for (let end = chunkSize; end < STREAM_DOC.length + chunkSize; end += chunkSize) {
const prefix = STREAM_DOC.slice(0, Math.min(end, STREAM_DOC.length))

View File

@@ -445,7 +445,7 @@ describe('MarkdownText', () => {
const startedAt = performance.now()
const { container } = render(<MarkdownText text={'\\(x '.repeat(6_400)} />)
expect(performance.now() - startedAt).toBeLessThan(1_000)
expect(performance.now() - startedAt).toBeLessThan(3_000)
expect(container.querySelector('.katex')).toBeNull()
})