Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions packages/monaco/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,17 @@ export interface ShikiToMonacoOptions {
* @default 500
*/
tokenizeTimeLimit?: number
/**
* A map of theme names to their Monaco theme options.
*
* This is useful for specifying the base theme for high contrast themes.
*/
themes?: Record<string, {
type?: 'light' | 'dark' | 'hc' | 'hc-light'
}>
}

export function textmateThemeToMonacoTheme(theme: ThemeRegistrationResolved): MonacoTheme {
export function textmateThemeToMonacoTheme(theme: ThemeRegistrationResolved, options?: ShikiToMonacoOptions['themes']): MonacoTheme {
let rules = 'rules' in theme
? theme.rules as MonacoTheme['rules']
: undefined
Expand Down Expand Up @@ -54,8 +62,19 @@ export function textmateThemeToMonacoTheme(theme: ThemeRegistrationResolved): Mo
.map(([key, value]) => [key, `#${normalizeColor(value)}`]),
)

let base = theme.type === 'light' ? 'vs' : 'vs-dark'
if (options?.[theme.name]?.type) {
const type = options[theme.name].type
if (type === 'hc' || type === 'hc-light')
base = type === 'hc' ? 'hc-black' : 'hc-light'
else if (type === 'light')
base = 'vs'
else if (type === 'dark')
base = 'vs-dark'
}

return {
base: theme.type === 'light' ? 'vs' : 'vs-dark',
base: base as any,
inherit: false,
colors,
rules,
Expand All @@ -72,7 +91,7 @@ export function shikiToMonaco(
const themeIds = highlighter.getLoadedThemes()
for (const themeId of themeIds) {
const tmTheme = highlighter.getTheme(themeId)
const monacoTheme = textmateThemeToMonacoTheme(tmTheme)
const monacoTheme = textmateThemeToMonacoTheme(tmTheme, options.themes)
themeMap.set(themeId, monacoTheme)
monaco.editor.defineTheme(themeId, monacoTheme)
}
Expand Down
48 changes: 48 additions & 0 deletions packages/monaco/test/high-contrast.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { describe, expect, it, vi } from 'vitest'
import { shikiToMonaco } from '../src/index'

describe('shikiToMonaco high contrast', () => {
it('registers high contrast theme with correct base', () => {
const highlighter = {
getLoadedThemes: () => ['hc-theme'],
getTheme: (_id: string) => ({
name: 'hc-theme',
type: 'dark',
colors: { 'editor.foreground': '#ffffff' },
rules: [],
}),
setTheme: () => ({ colorMap: [] }),
getLoadedLanguages: () => [],
} as any

const monaco = {
editor: {
defineTheme: vi.fn(),
setTheme: vi.fn(),
create: vi.fn(),
},
languages: {
register: vi.fn(),
getLanguages: () => [],
setTokensProvider: vi.fn(),
},
} as any

shikiToMonaco(highlighter, monaco, {
themes: {
'hc-theme': {
type: 'hc',
},
},
})

const defineThemeCall = monaco.editor.defineTheme.mock.calls[0]
const themeData = defineThemeCall[1]

// This is what we want to fail currently.
// It should be 'vs-dark' currently, but we want it to be 'hc-black' eventually.
// For reproduction, we assert what happens NOW, or we assert what SHOULD happen and expect failure.
// I'll assert what SHOULD happen so it fails.
expect(themeData.base).toBe('hc-black')
})
})