Skip to content

Commit 989afdb

Browse files
committed
feat: move createCssVariablesTheme to core
1 parent 50c8e4a commit 989afdb

File tree

4 files changed

+281
-278
lines changed

4 files changed

+281
-278
lines changed

packages/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export { codeToTokens } from './highlight/code-to-tokens'
1616
export { tokenizeAnsiWithTheme } from './highlight/code-to-tokens-ansi'
1717
export { codeToTokensBase, tokenizeWithTheme } from './highlight/code-to-tokens-base'
1818
export { codeToTokensWithThemes } from './highlight/code-to-tokens-themes'
19-
2019
export { normalizeTheme } from './textmate/normalize-theme'
20+
export * from './theme-css-variables'
2121
export { transformerDecorations } from './transformer-decorations'
2222

2323
// Utils and Misc
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
import type { ThemeRegistration } from '@shikijs/types'
2+
3+
export interface CssVariablesThemeOptions {
4+
/**
5+
* Theme name. Need to unique if multiple css variables themes are created
6+
*
7+
* @default 'css-variables'
8+
*/
9+
name?: string
10+
11+
/**
12+
* Prefix for css variables
13+
*
14+
* @default '--shiki-'
15+
*/
16+
variablePrefix?: string
17+
18+
/**
19+
* Default value for css variables, the key is without the prefix
20+
*
21+
* @example `{ 'token-comment': '#888' }` will generate `var(--shiki-token-comment, #888)` for comments
22+
*/
23+
variableDefaults?: Record<string, string>
24+
25+
/**
26+
* Enable font style
27+
*
28+
* @default true
29+
*/
30+
fontStyle?: boolean
31+
}
32+
33+
/**
34+
* A factory function to create a css-variable-based theme
35+
*
36+
* @see https://shiki.style/guide/theme-colors#css-variables-theme
37+
*/
38+
export function createCssVariablesTheme(options: CssVariablesThemeOptions = {}): ThemeRegistration {
39+
const {
40+
name = 'css-variables',
41+
variablePrefix = '--shiki-',
42+
fontStyle = true,
43+
} = options
44+
45+
const variable = (name: string): string => {
46+
if (options.variableDefaults?.[name])
47+
return `var(${variablePrefix}${name}, ${options.variableDefaults[name]})`
48+
return `var(${variablePrefix}${name})`
49+
}
50+
51+
const theme: ThemeRegistration = {
52+
name,
53+
type: 'dark',
54+
colors: {
55+
'editor.foreground': variable('foreground'),
56+
'editor.background': variable('background'),
57+
'terminal.ansiBlack': variable('ansi-black'),
58+
'terminal.ansiRed': variable('ansi-red'),
59+
'terminal.ansiGreen': variable('ansi-green'),
60+
'terminal.ansiYellow': variable('ansi-yellow'),
61+
'terminal.ansiBlue': variable('ansi-blue'),
62+
'terminal.ansiMagenta': variable('ansi-magenta'),
63+
'terminal.ansiCyan': variable('ansi-cyan'),
64+
'terminal.ansiWhite': variable('ansi-white'),
65+
'terminal.ansiBrightBlack': variable('ansi-bright-black'),
66+
'terminal.ansiBrightRed': variable('ansi-bright-red'),
67+
'terminal.ansiBrightGreen': variable('ansi-bright-green'),
68+
'terminal.ansiBrightYellow': variable('ansi-bright-yellow'),
69+
'terminal.ansiBrightBlue': variable('ansi-bright-blue'),
70+
'terminal.ansiBrightMagenta': variable('ansi-bright-magenta'),
71+
'terminal.ansiBrightCyan': variable('ansi-bright-cyan'),
72+
'terminal.ansiBrightWhite': variable('ansi-bright-white'),
73+
},
74+
tokenColors: [
75+
{
76+
scope: [
77+
'keyword.operator.accessor',
78+
'meta.group.braces.round.function.arguments',
79+
'meta.template.expression',
80+
'markup.fenced_code meta.embedded.block',
81+
],
82+
settings: {
83+
foreground: variable('foreground'),
84+
},
85+
},
86+
{
87+
scope: 'emphasis',
88+
settings: {
89+
fontStyle: 'italic',
90+
},
91+
},
92+
{
93+
scope: ['strong', 'markup.heading.markdown', 'markup.bold.markdown'],
94+
settings: {
95+
fontStyle: 'bold',
96+
},
97+
},
98+
{
99+
scope: ['markup.italic.markdown'],
100+
settings: {
101+
fontStyle: 'italic',
102+
},
103+
},
104+
{
105+
scope: 'meta.link.inline.markdown',
106+
settings: {
107+
fontStyle: 'underline',
108+
foreground: variable('token-link'),
109+
},
110+
},
111+
{
112+
scope: ['string', 'markup.fenced_code', 'markup.inline'],
113+
settings: {
114+
foreground: variable('token-string'),
115+
},
116+
},
117+
{
118+
scope: ['comment', 'string.quoted.docstring.multi'],
119+
settings: {
120+
foreground: variable('token-comment'),
121+
},
122+
},
123+
{
124+
scope: [
125+
'constant.numeric',
126+
'constant.language',
127+
'constant.other.placeholder',
128+
'constant.character.format.placeholder',
129+
'variable.language.this',
130+
'variable.other.object',
131+
'variable.other.class',
132+
'variable.other.constant',
133+
'meta.property-name',
134+
'meta.property-value',
135+
'support',
136+
],
137+
settings: {
138+
foreground: variable('token-constant'),
139+
},
140+
},
141+
{
142+
scope: [
143+
'keyword',
144+
'storage.modifier',
145+
'storage.type',
146+
'storage.control.clojure',
147+
'entity.name.function.clojure',
148+
'entity.name.tag.yaml',
149+
'support.function.node',
150+
'support.type.property-name.json',
151+
'punctuation.separator.key-value',
152+
'punctuation.definition.template-expression',
153+
],
154+
settings: {
155+
foreground: variable('token-keyword'),
156+
},
157+
},
158+
{
159+
scope: 'variable.parameter.function',
160+
settings: {
161+
foreground: variable('token-parameter'),
162+
},
163+
},
164+
{
165+
scope: [
166+
'support.function',
167+
'entity.name.type',
168+
'entity.other.inherited-class',
169+
'meta.function-call',
170+
'meta.instance.constructor',
171+
'entity.other.attribute-name',
172+
'entity.name.function',
173+
'constant.keyword.clojure',
174+
],
175+
settings: {
176+
foreground: variable('token-function'),
177+
},
178+
},
179+
{
180+
scope: [
181+
'entity.name.tag',
182+
'string.quoted',
183+
'string.regexp',
184+
'string.interpolated',
185+
'string.template',
186+
'string.unquoted.plain.out.yaml',
187+
'keyword.other.template',
188+
],
189+
settings: {
190+
foreground: variable('token-string-expression'),
191+
},
192+
},
193+
{
194+
scope: [
195+
'punctuation.definition.arguments',
196+
'punctuation.definition.dict',
197+
'punctuation.separator',
198+
'meta.function-call.arguments',
199+
],
200+
settings: {
201+
foreground: variable('token-punctuation'),
202+
},
203+
},
204+
{
205+
// [Custom] Markdown links
206+
scope: [
207+
'markup.underline.link',
208+
'punctuation.definition.metadata.markdown',
209+
],
210+
settings: {
211+
foreground: variable('token-link'),
212+
},
213+
},
214+
{
215+
// [Custom] Markdown list
216+
scope: ['beginning.punctuation.definition.list.markdown'],
217+
settings: {
218+
foreground: variable('token-string'),
219+
},
220+
},
221+
{
222+
// [Custom] Markdown punctuation definition brackets
223+
scope: [
224+
'punctuation.definition.string.begin.markdown',
225+
'punctuation.definition.string.end.markdown',
226+
'string.other.link.title.markdown',
227+
'string.other.link.description.markdown',
228+
],
229+
settings: {
230+
foreground: variable('token-keyword'),
231+
},
232+
},
233+
{
234+
// [Custom] Diff
235+
scope: [
236+
'markup.inserted',
237+
'meta.diff.header.to-file',
238+
'punctuation.definition.inserted',
239+
],
240+
settings: {
241+
foreground: variable('token-inserted'),
242+
},
243+
},
244+
{
245+
scope: [
246+
'markup.deleted',
247+
'meta.diff.header.from-file',
248+
'punctuation.definition.deleted',
249+
],
250+
settings: {
251+
foreground: variable('token-deleted'),
252+
},
253+
},
254+
{
255+
scope: [
256+
'markup.changed',
257+
'punctuation.definition.changed',
258+
],
259+
settings: {
260+
foreground: variable('token-changed'),
261+
},
262+
},
263+
],
264+
}
265+
266+
if (!fontStyle) {
267+
theme.tokenColors = theme.tokenColors?.map((tokenColor) => {
268+
if (tokenColor.settings?.fontStyle)
269+
// @ts-expect-error force delete readonly property
270+
delete tokenColor.settings.fontStyle
271+
return tokenColor
272+
})
273+
}
274+
275+
return theme
276+
}

packages/shiki/src/core.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1 @@
1-
export type { CssVariablesThemeOptions } from './theme-css-variables'
2-
3-
export { createCssVariablesTheme } from './theme-css-variables'
41
export * from '@shikijs/core'

0 commit comments

Comments
 (0)