@tanstack/highlight
Version:
Tiny class-based syntax highlighting for documentation.
88 lines (86 loc) • 2.37 kB
JavaScript
export const themeTokenClasses = [
'token',
'attr',
'code-inline',
'command',
'comment',
'deleted',
'function',
'heading',
'inserted',
'keyword',
'link',
'literal',
'meta',
'number',
'operator',
'property',
'selector',
'string',
'tag',
'type',
'variable',
];
export function createThemeCss(options) {
const themeEntries = options.themes || [
...(options.light
? [
{
selector: options.lightSelector || ':root',
theme: options.light,
},
]
: []),
...(options.dark
? [
{
selector: options.darkSelector || '.dark',
theme: options.dark,
},
]
: []),
];
const themeCss = themeEntries
.map(({ selector, theme }) => createThemeRule(selector, theme))
.join('\n\n');
if (options.includeBaseStyles === false) {
return themeCss;
}
return `${themeCss}\n\n${createThemeBaseCss(options)}`;
}
export function createThemeRule(selector, theme) {
const variables = [
` --th-background: ${theme.background};`,
` --th-token: ${theme.tokens.token || theme.foreground};`,
...themeTokenClasses
.filter((className) => className !== 'token')
.map((className) => ` --th-${className}: ${theme.tokens[className]};`),
];
return `${selector} {
${variables.join('\n')}
}`;
}
export function createThemeBaseCss(options = {}) {
const codeBlockSelector = options.codeBlockSelector || 'pre.th-code';
const lineNumbersSelector = options.lineNumbersSelector || '.th-code--line-numbers';
return `${codeBlockSelector} {
overflow-x: auto;
padding: 1rem;
background: var(--th-background);
color: var(--th-token);
}
${themeTokenClasses
.map((token) => `.th-${token} { color: var(--th-${token}); }`)
.join('\n')}
.th-line { display: inline-block; min-width: 100%; width: max-content; }
${lineNumbersSelector} code { counter-reset: th-line; }
${lineNumbersSelector} .th-line::before {
display: inline-block;
width: 2.5em;
padding-right: 1em;
color: var(--th-comment);
content: attr(data-line);
text-align: right;
user-select: none;
}`;
}