All files / packages/core/src/themes/css syntax-generator.ts

100% Statements 7/7
100% Branches 0/0
100% Functions 3/3
100% Lines 6/6

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62                      60x 60x     60x                     60x 1260x   60x                                                                
// SPDX-License-Identifier: MIT
// Syntax highlighting CSS generation
 
import type { ThemeFlavor } from '../types.js';
import { escapeCssId, sanitizeCssColor } from './helpers.js';
import { SYNTAX_CLASS_GROUPS } from './mappings.js';
 
/**
 * Generates syntax highlighting CSS for a theme flavor.
 */
export function generateSyntaxHighlightingCSS(flavor: ThemeFlavor): string {
  const { tokens } = flavor;
  const escapedId = escapeCssId(flavor.id);
 
  // Sanitize all color values to prevent CSS injection
  const syntaxColors = {
    fg: sanitizeCssColor(tokens.content.codeInline.fg),
    bg: sanitizeCssColor(tokens.content.codeInline.bg),
    comment: sanitizeCssColor(tokens.text.secondary),
    keyword: sanitizeCssColor(tokens.brand.primary),
    string: sanitizeCssColor(tokens.state.success),
    number: sanitizeCssColor(tokens.state.warning),
    title: sanitizeCssColor(tokens.state.info),
    attr: sanitizeCssColor(tokens.accent.link),
  };
 
  const selector = (classes: readonly string[]): string =>
    classes.map((c) => `html[data-flavor='${escapedId}'] .highlight ${c}`).join(',\n');
 
  return `html[data-flavor='${escapedId}'] .highlight {
  background: ${syntaxColors.bg};
  color: ${syntaxColors.fg};
}
html[data-flavor='${escapedId}'] .highlight pre,
html[data-flavor='${escapedId}'] pre.highlight {
  background: transparent;
  color: ${syntaxColors.fg};
}
html[data-flavor='${escapedId}'] .highlight code {
  background: transparent;
  color: ${syntaxColors.fg};
}
${selector(SYNTAX_CLASS_GROUPS.comment)} {
  color: ${syntaxColors.comment};
}
${selector(SYNTAX_CLASS_GROUPS.keyword)} {
  color: ${syntaxColors.keyword};
}
${selector(SYNTAX_CLASS_GROUPS.string)} {
  color: ${syntaxColors.string};
}
${selector(SYNTAX_CLASS_GROUPS.number)} {
  color: ${syntaxColors.number};
}
${selector(SYNTAX_CLASS_GROUPS.attr)} {
  color: ${syntaxColors.attr};
}
${selector(SYNTAX_CLASS_GROUPS.title)} {
  color: ${syntaxColors.title};
}`;
}