Skip to content

Commit

Permalink
fix: colorReplacements also for bg and fg, close #641
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Apr 1, 2024
1 parent f254653 commit bb47a84
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 9 deletions.
1 change: 1 addition & 0 deletions packages/core/src/code-to-tokens-ansi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function tokenizeAnsiWithTheme(
}

color = applyColorReplacements(color, colorReplacements)
bgColor = applyColorReplacements(bgColor, colorReplacements)

if (token.decorations.has('dim'))
color = dimColor(color)
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/code-to-tokens-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@ export function tokenizeWithTheme(
continue

const metadata = result.tokens[2 * j + 1]
const foreground = StackElementMetadata.getForeground(metadata)
const foregroundColor = applyColorReplacements(colorMap[foreground], colorReplacements)
const color = applyColorReplacements(
colorMap[StackElementMetadata.getForeground(metadata)],
colorReplacements,
)
const fontStyle: FontStyle = StackElementMetadata.getFontStyle(metadata)

const token: ThemedToken = {
content: line.substring(startIndex, nextStartIndex),
offset: lineOffset + startIndex,
color: foregroundColor,
color,
fontStyle,
}

Expand Down
19 changes: 14 additions & 5 deletions packages/core/src/code-to-tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { codeToTokensBase } from './code-to-tokens-base'
import { codeToTokensWithThemes } from './code-to-tokens-themes'
import { ShikiError } from './error'
import type { CodeToTokensOptions, ShikiInternal, ThemedToken, ThemedTokenWithVariants, TokensResult } from './types'
import { getTokenStyleObject, stringifyTokenStyle } from './utils'
import { applyColorReplacements, getTokenStyleObject, stringifyTokenStyle } from './utils'

/**
* High-level code-to-tokens API.
Expand All @@ -24,6 +24,7 @@ export function codeToTokens(
const {
defaultColor = 'light',
cssVariablePrefix = '--shiki-',
colorReplacements,
} = options

const themes = Object.entries(options.themes)
Expand All @@ -48,21 +49,29 @@ export function codeToTokens(
tokens = themeTokens
.map(line => line.map(token => mergeToken(token, themesOrder, cssVariablePrefix, defaultColor)))

fg = themes.map((t, idx) => (idx === 0 && defaultColor ? '' : `${cssVariablePrefix + t.color}:`) + (themeRegs[idx].fg || 'inherit')).join(';')
bg = themes.map((t, idx) => (idx === 0 && defaultColor ? '' : `${cssVariablePrefix + t.color}-bg:`) + (themeRegs[idx].bg || 'inherit')).join(';')
fg = themes.map((t, idx) => (idx === 0 && defaultColor
? ''
: `${cssVariablePrefix + t.color}:`) + (applyColorReplacements(themeRegs[idx].fg, colorReplacements) || 'inherit')).join(';')
bg = themes.map((t, idx) => (idx === 0 && defaultColor
? ''
: `${cssVariablePrefix + t.color}-bg:`) + (applyColorReplacements(themeRegs[idx].bg, colorReplacements) || 'inherit')).join(';')
themeName = `shiki-themes ${themeRegs.map(t => t.name).join(' ')}`
rootStyle = defaultColor ? undefined : [fg, bg].join(';')
}
else if ('theme' in options) {
const {
colorReplacements,
} = options

tokens = codeToTokensBase(
internal,
code,
options,
)

const _theme = internal.getTheme(options.theme)
bg = _theme.bg
fg = _theme.fg
bg = applyColorReplacements(_theme.bg, colorReplacements)
fg = applyColorReplacements(_theme.fg, colorReplacements)
themeName = _theme.name
}
else {
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,11 @@ export function splitTokens<
})
}

export function applyColorReplacements(color: string, replacements?: Record<string, string>): string {
export function applyColorReplacements(color: string, replacements?: Record<string, string>): string
export function applyColorReplacements(color?: string | undefined, replacements?: Record<string, string>): string | undefined
export function applyColorReplacements(color?: string, replacements?: Record<string, string>): string | undefined {
if (!color)
return color
return replacements?.[color?.toLowerCase()] || color
}

Expand Down
46 changes: 46 additions & 0 deletions packages/shiki/test/color-replacement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect, it } from 'vitest'
import { codeToHtml } from '../src'

it('colorReplacements', async () => {
const result = await codeToHtml('console.log("hi")', {
lang: 'js',
themes: {
light: 'vitesse-light',
dark: 'material-theme-palenight',
},
colorReplacements: {
'#393a34': 'var(---replaced-1)',
'#b07d48': 'var(---replaced-2)',
},
})

expect(result).toContain('var(---replaced-1)')
expect(result).toContain('var(---replaced-2)')

expect(result.replace(/>/g, '>\n'))
.toMatchInlineSnapshot(`
"<pre class="shiki shiki-themes vitesse-light material-theme-palenight" style="background-color:#ffffff;--shiki-dark-bg:#292D3E;color:var(---replaced-1);--shiki-dark:#babed8" tabindex="0">
<code>
<span class="line">
<span style="color:var(---replaced-2);--shiki-dark:#BABED8">
console</span>
<span style="color:#999999;--shiki-dark:#89DDFF">
.</span>
<span style="color:#59873A;--shiki-dark:#82AAFF">
log</span>
<span style="color:#999999;--shiki-dark:#BABED8">
(</span>
<span style="color:#B5695999;--shiki-dark:#89DDFF">
"</span>
<span style="color:#B56959;--shiki-dark:#C3E88D">
hi</span>
<span style="color:#B5695999;--shiki-dark:#89DDFF">
"</span>
<span style="color:#999999;--shiki-dark:#BABED8">
)</span>
</span>
</code>
</pre>
"
`)
})

0 comments on commit bb47a84

Please sign in to comment.