mirror of
https://github.com/supabase/supabase.git
synced 2026-09-22 13:37:53 +08:00
7fb2e8cd42
## What kind of change does this PR introduce? bug fix alternative to #50492 ## What is the current behavior? [#50239](https://github.com/supabase/supabase/pull/50239) introduced repeated shiki grammar registration. duplicate injection rules accumulate between code blocks, slowing later tutorials enough to hit the 60-second build timeout ## What is the new behavior? - reuses one highlighter with all languages loaded once - restores previous highlighting approach + startup cost while keeping the page-size savings replay | before #50239 | after #50239 | this pr -- | -- | -- | -- cold, including initialization | 2.99 s | 6.96 s | 2.94 s warm | 0.37 s | 5.90 s | 0.36 s <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Enhancements * Code blocks now preload syntax highlighting for all supported bundled languages, including SQL, Markdown, and TypeScript. * Highlighting uses a shared configuration and theme for consistent rendering across code blocks. * Concurrent code block renders share a single highlighter initialization. * Language handling and syntax-highlighted output are more consistent across supported, unsupported, aliased, and plain-text code blocks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Ali Waseem <waseema393@gmail.com>
88 lines
3.2 KiB
TypeScript
88 lines
3.2 KiB
TypeScript
import { bundledLanguages, createHighlighter, type Highlighter } from 'shiki'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import theme from './supabase-2.json' with { type: 'json' }
|
|
|
|
vi.mock('shiki', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('shiki')>()
|
|
return { ...actual, createHighlighter: vi.fn() }
|
|
})
|
|
|
|
const result = {
|
|
tokens: [[{ content: 'select', offset: 0, color: 'var(--code-token-keyword)', fontStyle: 1 }]],
|
|
}
|
|
const highlighter = {
|
|
codeToTokens: vi.fn<Highlighter['codeToTokens']>(),
|
|
loadLanguage: vi.fn(),
|
|
loadTheme: vi.fn(),
|
|
}
|
|
const create = vi.mocked(createHighlighter, { partial: true })
|
|
|
|
describe('shared code block highlighting', () => {
|
|
beforeEach(() => {
|
|
vi.resetModules()
|
|
vi.resetAllMocks()
|
|
create.mockResolvedValue(highlighter)
|
|
highlighter.codeToTokens.mockReturnValue(result)
|
|
})
|
|
|
|
it('initializes all languages once and never reloads languages or themes between blocks', async () => {
|
|
const { highlightCode } = await import('./CodeBlock.highlight')
|
|
expect(create).not.toHaveBeenCalled()
|
|
|
|
await highlightCode('echo hello', 'bash')
|
|
await highlightCode('select 42', 'sql')
|
|
await highlightCode('echo again', 'shell')
|
|
|
|
expect(create).toHaveBeenCalledExactlyOnceWith({
|
|
themes: [theme],
|
|
langs: Object.keys(bundledLanguages),
|
|
})
|
|
expect(create.mock.calls[0][0].themes?.[0]).not.toBe(theme)
|
|
expect(highlighter.loadLanguage).not.toHaveBeenCalled()
|
|
expect(highlighter.loadTheme).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it.each(['javascript', 'js', null] as const)(
|
|
'forwards the source and options for %s and returns the tokens unchanged',
|
|
async (lang) => {
|
|
const { highlightCode } = await import('./CodeBlock.highlight')
|
|
expect(await highlightCode('const value = 42', lang)).toBe(result)
|
|
expect(highlighter.codeToTokens).toHaveBeenCalledExactlyOnceWith('const value = 42', {
|
|
lang: lang ?? undefined,
|
|
theme: 'Supabase Theme',
|
|
tokenizeTimeLimit: 0,
|
|
tokenizeMaxLineLength: 100_000,
|
|
})
|
|
}
|
|
)
|
|
|
|
it('shares pending initialization across concurrent languages and aliases', async () => {
|
|
const { promise, resolve } = Promise.withResolvers<typeof highlighter>()
|
|
create.mockReturnValue(promise)
|
|
const { highlightCode } = await import('./CodeBlock.highlight')
|
|
const pending = [
|
|
highlightCode('echo hello', 'bash'),
|
|
highlightCode('echo again', 'shell'),
|
|
highlightCode('select 42', 'sql'),
|
|
]
|
|
expect(create).toHaveBeenCalledTimes(1)
|
|
expect(highlighter.codeToTokens).not.toHaveBeenCalled()
|
|
|
|
resolve(highlighter)
|
|
expect(await Promise.all(pending)).toEqual([result, result, result])
|
|
expect(highlighter.codeToTokens).toHaveBeenCalledTimes(3)
|
|
})
|
|
|
|
it('retains initialization failures without adding retries', async () => {
|
|
const failure = new Error('Highlighter could not be initialized')
|
|
create.mockRejectedValue(failure)
|
|
const { highlightCode } = await import('./CodeBlock.highlight')
|
|
|
|
await expect(highlightCode('echo hello', 'bash')).rejects.toBe(failure)
|
|
await expect(highlightCode('select 42', 'sql')).rejects.toBe(failure)
|
|
expect(create).toHaveBeenCalledTimes(1)
|
|
expect(highlighter.codeToTokens).not.toHaveBeenCalled()
|
|
})
|
|
})
|