theme.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { EditorView } from '@codemirror/view'
  2. import { Compartment, TransactionSpec } from '@codemirror/state'
  3. import { FontFamily, LineHeight, userStyles } from '@/shared/utils/styles'
  4. import { ThemeCache } from '@/features/source-editor/utils/theme-cache'
  5. export type Options = {
  6. fontSize: number
  7. fontFamily: FontFamily
  8. lineHeight: LineHeight
  9. }
  10. const optionsThemeConf = new Compartment()
  11. export const theme = (options: Options) => [
  12. baseTheme,
  13. optionsThemeConf.of(createThemeFromOptions(options)),
  14. ]
  15. const tooltipThemeCache = new ThemeCache()
  16. const createThemeFromOptions = ({
  17. fontSize = 12,
  18. fontFamily = 'monaco',
  19. lineHeight = 'normal',
  20. }: Options) => {
  21. // Theme styles that depend on settings
  22. const styles = userStyles({ fontSize, fontFamily, lineHeight })
  23. return [
  24. EditorView.editorAttributes.of({
  25. style: Object.entries({
  26. '--font-size': styles.fontSize,
  27. '--source-font-family': styles.fontFamily,
  28. '--line-height': styles.lineHeight,
  29. })
  30. .map(([key, value]) => `${key}: ${value}`)
  31. .join(';'),
  32. }),
  33. tooltipThemeCache.get({
  34. '.cm-tooltip': {
  35. '--font-size': styles.fontSize,
  36. '--source-font-family': styles.fontFamily,
  37. },
  38. }),
  39. ]
  40. }
  41. const baseTheme = EditorView.theme({
  42. '&.cm-editor.cm-editor': {
  43. colorScheme: 'light',
  44. },
  45. '.cm-content': {
  46. fontSize: 'var(--font-size)',
  47. fontFamily: 'var(--source-font-family)',
  48. lineHeight: 'var(--line-height)',
  49. color: '#000',
  50. },
  51. '.cm-gutters': {
  52. fontSize: 'var(--font-size)',
  53. lineHeight: 'var(--line-height)',
  54. },
  55. '.cm-lineNumbers': {
  56. fontFamily: 'var(--source-font-family)',
  57. },
  58. '.cm-tooltip': {
  59. // NOTE: fontFamily is not set here, as most tooltips use the UI font
  60. fontSize: 'var(--font-size)',
  61. },
  62. })
  63. export const setOptionsTheme = (options: Options): TransactionSpec => {
  64. return {
  65. effects: optionsThemeConf.reconfigure(createThemeFromOptions(options)),
  66. }
  67. }