vowel 0.7.7 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vowel",
3
3
  "type": "module",
4
- "version": "0.7.7",
4
+ "version": "0.8.0",
5
5
  "engines": {
6
6
  "node": ">=26"
7
7
  },
@@ -88,4 +88,4 @@
88
88
  "!plugins/html/bundle.js",
89
89
  "!plugins/html/editorClient.js"
90
90
  ]
91
- }
91
+ }
@@ -0,0 +1,66 @@
1
+ import { refractor } from "refractor"
2
+ import graphql from "refractor/graphql"
3
+ import jsx from "refractor/jsx"
4
+ import shellSession from "refractor/shell-session"
5
+ import toml from "refractor/toml"
6
+ import tsx from "refractor/tsx"
7
+ import wasm from "refractor/wasm"
8
+ import { extendMarkdown } from "./markdownGrammar.js"
9
+
10
+ /**
11
+ * Syntax highlighting for fenced code: Prism's grammars, through
12
+ * refractor, which returns a hast tree. Prism replaced highlight.js
13
+ * (vowel 0.8) because highlight.js's markdown grammar knew neither
14
+ * frontmatter, comments nor GFM, and Vowel's code blocks are mostly
15
+ * Vowel's own markup; Prism is as fast (markdownGrammar.js).
16
+ *
17
+ * refractor's common set is 62 languages. These are added so that every
18
+ * name highlight.js answered to still highlights: the languages it had
19
+ * and refractor's common set doesn't, and the other spellings of the
20
+ * ones it does.
21
+ */
22
+ refractor.register(graphql)
23
+ refractor.register(jsx)
24
+ refractor.register(shellSession)
25
+ refractor.register(toml)
26
+ refractor.register(tsx)
27
+ refractor.register(wasm)
28
+
29
+ refractor.alias({
30
+ bash: ["zsh"],
31
+ c: ["h"],
32
+ cpp: ["cc", "c++", "h++", "hpp", "hh", "hxx", "cxx"],
33
+ csharp: ["c#"],
34
+ diff: ["patch"],
35
+ go: ["golang"],
36
+ graphql: ["gql"],
37
+ javascript: ["mjs", "cjs"],
38
+ json: ["jsonc", "json5"],
39
+ makefile: ["mk", "mak", "make"],
40
+ markdown: ["mkdown", "mkd"],
41
+ markup: ["xhtml", "xsd", "xsl", "plist"],
42
+ "objectivec": ["mm", "obj-c"],
43
+ perl: ["pl", "pm"],
44
+ python: ["ipython"],
45
+ ruby: ["gemspec", "podspec", "irb"],
46
+ rust: ["rs"],
47
+ "shell-session": ["console"],
48
+ typescript: ["mts", "cts"],
49
+ vbnet: ["vb"]
50
+ })
51
+
52
+ extendMarkdown(refractor)
53
+
54
+ /**
55
+ * `code` highlighted as `language`, as hast, or undefined for a
56
+ * language Prism doesn't know. Matched case-insensitively, as a fence's
57
+ * language was by highlight.js.
58
+ * @param {string} code
59
+ * @param {string} language
60
+ * @returns {import("hast").Root | undefined}
61
+ */
62
+ export function highlightCode(code, language) {
63
+ const name = language.toLowerCase()
64
+ if (!refractor.registered(name)) return undefined
65
+ return refractor.highlight(code, name)
66
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Prism's markdown grammar, made to read what Vowel reads: GitHub
3
+ * Flavored Markdown, then Vowel's own syntax on top (per Sam, Nov 6:
4
+ * Vowel is a GFM superset, so its code blocks highlight as GFM).
5
+ *
6
+ * Prism's grammar is close. These change what it gets wrong, measured
7
+ * against micromark, which Vowel parses pages with:
8
+ *
9
+ * - frontmatter only on the first line (Prism allowed blank lines
10
+ * before it);
11
+ * - fences of `~~~` as well as ```, and longer fences (a `~~~` fence was
12
+ * strikethrough, and a ```` fence ended at the first ``` inside it);
13
+ * - table delimiter cells of one dash (Prism wanted three);
14
+ * - task list items, footnotes and autolinks, which it didn't know.
15
+ *
16
+ * And these add Vowel's syntax, with the patterns `readRules.js` reads
17
+ * it with: alerts, wikilinks, hashtags, `:shortcodes:`, `==highlights==`
18
+ * and listing lines (`/blog/*`).
19
+ *
20
+ * Prism grammars are objects that are changed in place: `insertBefore`
21
+ * is how a rule is added, and the order of rules is the order they are
22
+ * tried in. A token that is cut out of a line hides it from the rules
23
+ * after it: that is why a task item takes its list marker with it.
24
+ */
25
+
26
+ /**
27
+ * Prism's table patterns with one dash or more per delimiter cell.
28
+ * @param {RegExp} pattern
29
+ */
30
+ const oneDash = (pattern) => new RegExp(pattern.source.replaceAll("-{3,}", "-+"), pattern.flags)
31
+
32
+ /**
33
+ * Extends the markdown grammar of this refractor, once.
34
+ * @param {import("refractor/core").Refractor} refractor - with markdown registered
35
+ */
36
+ export function extendMarkdown(refractor) {
37
+ const languages = refractor.languages
38
+ const markdown = languages.markdown
39
+
40
+ markdown["front-matter-block"].pattern = /^---(?!.)[\s\S]*?[\r\n]---(?!.)/
41
+ markdown["front-matter-block"].lookbehind = false
42
+
43
+ // Three or more backticks or tildes, closed by the same character at
44
+ // least as many times. The parts stay in the order Prism's
45
+ // after-tokenize hook expects (fence, language, newline, block,
46
+ // newline, fence): it reads the language from them, and highlights
47
+ // the block in it.
48
+ markdown.code[1] = {
49
+ pattern: /^(([`~])\2{2,})[^\r\n]*(?:\r\n?|\n)(?:[\s\S]*?(?:\r\n?|\n))??\1\2*[ \t]*$/m,
50
+ greedy: true,
51
+ inside: {
52
+ "code-block": {
53
+ pattern: /^((?:`{3,}|~{3,})[^\r\n]*(?:\r\n?|\n))[\s\S]+(?=(?:\r\n?|\n)(?:`{3,}|~{3,})[ \t]*$)/,
54
+ lookbehind: true
55
+ },
56
+ "code-language": {
57
+ pattern: /^(`{3,}|~{3,})[^\s`~][^\r\n]*/,
58
+ lookbehind: true
59
+ },
60
+ punctuation: /`{3,}|~{3,}/
61
+ }
62
+ }
63
+
64
+ const table = markdown.table
65
+ const rows = table.inside["table-data-rows"]
66
+ const line = table.inside["table-line"]
67
+ table.pattern = oneDash(table.pattern)
68
+ rows.pattern = oneDash(rows.pattern)
69
+ line.pattern = oneDash(line.pattern)
70
+ line.inside.punctuation = oneDash(line.inside.punctuation)
71
+
72
+ languages.insertBefore("markdown", "blockquote", {
73
+ // `> [!NOTE]`, any word, at the start of a quote.
74
+ alert: {
75
+ pattern: /(^>[ \t]*)\[![A-Za-z]+\]/m,
76
+ lookbehind: true,
77
+ alias: "important"
78
+ }
79
+ })
80
+
81
+ languages.insertBefore("markdown", "list", {
82
+ // `- [x]` and `1. [ ]`.
83
+ task: {
84
+ pattern: /^[ \t]*(?:[*+-]|\d+[.)])[ \t]+\[[ xX]\](?=[ \t])/m,
85
+ inside: {
86
+ list: { pattern: /^[ \t]*(?:[*+-]|\d+[.)])/, alias: "punctuation" },
87
+ checkbox: { pattern: /\[[ xX]\]/, alias: "keyword" }
88
+ }
89
+ },
90
+ // A paragraph that is only a path: a listing (`/blog/*`, `./drafts/**`)
91
+ // or a reference to a page (`/blog/post`).
92
+ directive: {
93
+ pattern: /(^|\n[ \t]*\n)(?:\/|\.\.?\/)\S*(?=[ \t]*(?:\n[ \t]*\n|\n?$))/,
94
+ lookbehind: true,
95
+ alias: "function"
96
+ }
97
+ })
98
+
99
+ languages.insertBefore("markdown", "url-reference", {
100
+ // `[^1]: The source.`, which Prism read as a link definition with
101
+ // the first word as its url.
102
+ "footnote-definition": {
103
+ pattern: /^[ \t]*\[\^[^\]\s]+\]:/m,
104
+ alias: "url"
105
+ }
106
+ })
107
+
108
+ languages.insertBefore("markdown", "url", {
109
+ // `[[Name]]`, `[[Name#Section]]`, `[[Name|words]]` and `![[Name]]`.
110
+ wikilink: {
111
+ pattern: /!?\[\[[^\]|#\r\n]+(?:#[^\]|\r\n]+)?(?:\|[^\]\r\n]+)?\]\]/,
112
+ greedy: true,
113
+ alias: "url",
114
+ inside: { punctuation: /^!?\[\[|\]\]$|[|#]/ }
115
+ },
116
+ // `[^1]`
117
+ footnote: {
118
+ pattern: /\[\^[^\]\s]+\]/,
119
+ alias: "url"
120
+ },
121
+ // `<https://vowel.cc>`, and a bare `https://vowel.cc` without the
122
+ // punctuation that ends a sentence.
123
+ autolink: {
124
+ pattern: /<(?:https?|mailto):[^\s>]+>|\bhttps?:\/\/[^\s<]*[^\s<.,:;"')\]]/,
125
+ alias: "url"
126
+ },
127
+ // `#tag` after the start of a line or a space: never a heading's
128
+ // `# `, a salt's `##` or the `#` in `a#b`.
129
+ hashtag: {
130
+ pattern: /(^|[ \t])#[\w\-/]+\b/m,
131
+ lookbehind: true,
132
+ alias: "tag"
133
+ },
134
+ // `:name:` and `:folder/name:`, an emoji or an icon.
135
+ shortcode: {
136
+ pattern: /:[a-z0-9_+-]+(?:\/[a-z0-9_+-]+)?:/,
137
+ alias: "symbol"
138
+ },
139
+ // `==highlighted==`
140
+ mark: {
141
+ pattern: /==(?=\S)[^=\r\n]*\S==/,
142
+ alias: "important"
143
+ }
144
+ })
145
+ }
@@ -1,12 +1,12 @@
1
1
  import path from "node:path"
2
2
  import { h } from "hastscript"
3
- import { common, createLowlight } from "lowlight"
4
3
  import { toText } from "hast-util-to-text"
5
4
  import GithubSlugger from "github-slugger"
6
5
  import { createVisitor, SKIP } from "../markdown/visitor.js"
7
6
  import { showPages, isPageWithoutFile, imageSizes, sourceLocation } from "../../utils.js"
8
7
  import { globClasses, alertLabel } from "./editor/directives.js"
9
8
  import createDynamicImage, { derivativeURL } from "./image.js"
9
+ import { highlightCode } from "./highlighting.js"
10
10
  import { displayPath } from "../../secretPaths.js"
11
11
 
12
12
  /**
@@ -31,7 +31,6 @@ const at = (node, target) => sourceLocation(target.source ?? target.path, node?.
31
31
  * write can link the highlight stylesheet only on pages that need it.
32
32
  */
33
33
 
34
- const lowlight = createLowlight(common)
35
34
 
36
35
  /** @param {any} node */
37
36
  const isElement = (node) => node?.type === "element"
@@ -276,9 +275,10 @@ const icon = {
276
275
  }
277
276
 
278
277
  /**
279
- * A fenced block with a language: what rehype-highlight did, without
280
- * its walk. hljs plus per-token spans on the <code>; the language class
281
- * is left for the stylesheet. An unregistered language is left alone.
278
+ * A fenced block with a language, highlighted by Prism
279
+ * (highlighting.js): per-token spans in the <code>, and the language
280
+ * class on the <pre> as well as the <code>, where Prism's themes look
281
+ * for it. A language Prism doesn't know is left alone.
282
282
  * @type {import("../markdown/visitor.js").BlockRule}
283
283
  */
284
284
  const highlight = {
@@ -288,14 +288,10 @@ const highlight = {
288
288
  const code = node.children[0]
289
289
  const language = (code.properties?.className ?? []).map(String).find(name => name.startsWith("language-"))?.slice("language-".length)
290
290
  if (!language) return SKIP
291
- let result
292
- try {
293
- result = lowlight.highlight(language, toText(code, { whitespace: "pre" }))
294
- } catch (error) {
295
- if (/Unknown language/.test(error.message)) return SKIP
296
- throw error
297
- }
298
- code.properties.className = ["hljs", ...code.properties.className.filter(name => name !== "hljs")]
291
+ const result = highlightCode(toText(code, { whitespace: "pre" }), language)
292
+ if (!result) return SKIP
293
+ const preClasses = (node.properties?.className ?? []).map(String).filter(name => !name.startsWith("language-"))
294
+ node.properties = { ...node.properties, className: [...preClasses, `language-${language}`] }
299
295
  if (result.children.length) code.children = result.children
300
296
  context.highlighted = true
301
297
  return SKIP
@@ -17,7 +17,7 @@
17
17
  --_name is internal to a sheet: computed here, not for setting.
18
18
  */
19
19
 
20
- @layer reset, typography, default, dynamic-typography;
20
+ @layer reset, typography, syntax-highlighting, default, dynamic-typography;
21
21
 
22
22
  @layer default {
23
23
  :root {
@@ -1,269 +1,214 @@
1
1
  /*
2
- * Syntax highlighting theme for code blocks (rehype-highlight), based on
3
- * highlight.js's GitHub theme. Light by default, dark under
4
- * prefers-color-scheme - see highlight.js/styles/github.css and
5
- * github-dark.css for the source themes this was combined from.
2
+ * Syntax highlighting for code blocks, highlighted by Prism (refractor):
3
+ * GitHub's light and dark colours, as highlight.js's GitHub themes had
4
+ * them, on Prism's token classes. Light by default, dark under
5
+ * prefers-color-scheme.
6
+ *
7
+ * In its own layer, before the default theme's (per Sam), so a theme
8
+ * overrides it: DefaultStyles.css's `pre, code` background replaces the
9
+ * dark background here. A project's own stylesheet is unlayered, so it
10
+ * overrides everything, a Prism theme included. The order is declared
11
+ * in every theme sheet, because a layer named for the first time later
12
+ * would go to the end.
13
+ *
14
+ * Rules of the same specificity are in an order that matters: a token
15
+ * can have several classes (a heading is `title important`, a YAML key
16
+ * `key atrule`), and the later rule wins.
6
17
  */
7
- pre code.hljs {
8
- display: block;
9
- overflow-x: auto;
10
- padding: 1em
11
- }
12
-
13
- code.hljs {
14
- padding: 3px 5px
15
- }
16
-
17
- /*!
18
- Theme: GitHub
19
- Description: Light theme as seen on github.com
20
- Author: github.com
21
- Maintainer: @Hirse
22
- Updated: 2021-05-15
23
-
24
- Outdated base version: https://github.com/primer/github-syntax-light
25
- Current colors taken from GitHub's CSS
26
- */
27
- .hljs {
28
- color: #24292e;
29
- }
30
-
31
- .hljs-doctag,
32
- .hljs-keyword,
33
- .hljs-meta .hljs-keyword,
34
- .hljs-template-tag,
35
- .hljs-template-variable,
36
- .hljs-type,
37
- .hljs-variable.language_ {
38
- /* prettylights-syntax-keyword */
39
- color: #d73a49
40
- }
41
-
42
- .hljs-title,
43
- .hljs-title.class_,
44
- .hljs-title.class_.inherited__,
45
- .hljs-title.function_ {
46
- /* prettylights-syntax-entity */
47
- color: #6f42c1
48
- }
49
-
50
- .hljs-attr,
51
- .hljs-attribute,
52
- .hljs-literal,
53
- .hljs-meta,
54
- .hljs-number,
55
- .hljs-operator,
56
- .hljs-variable,
57
- .hljs-selector-attr,
58
- .hljs-selector-class,
59
- .hljs-selector-id {
60
- /* prettylights-syntax-constant */
61
- color: #005cc5
62
- }
63
-
64
- .hljs-regexp,
65
- .hljs-string,
66
- .hljs-meta .hljs-string {
67
- /* prettylights-syntax-string */
68
- color: #032f62
69
- }
70
-
71
- .hljs-built_in,
72
- .hljs-symbol {
73
- /* prettylights-syntax-variable */
74
- color: #e36209
75
- }
76
-
77
- .hljs-comment,
78
- .hljs-code,
79
- .hljs-formula {
80
- /* prettylights-syntax-comment */
81
- color: #6a737d
82
- }
83
-
84
- .hljs-name,
85
- .hljs-quote,
86
- .hljs-selector-tag,
87
- .hljs-selector-pseudo {
88
- /* prettylights-syntax-entity-tag */
89
- color: #22863a
90
- }
91
-
92
- .hljs-subst {
93
- /* prettylights-syntax-storage-modifier-import */
94
- color: #24292e
95
- }
96
-
97
- .hljs-section {
98
- /* prettylights-syntax-markup-heading */
99
- color: #005cc5;
100
- font-weight: bold
101
- }
102
-
103
- .hljs-bullet {
104
- /* prettylights-syntax-markup-list */
105
- color: #735c0f
106
- }
107
-
108
- .hljs-emphasis {
109
- /* prettylights-syntax-markup-italic */
110
- color: #24292e;
111
- font-style: italic
112
- }
113
-
114
- .hljs-strong {
115
- /* prettylights-syntax-markup-bold */
116
- color: #24292e;
117
- font-weight: bold
118
- }
119
-
120
- .hljs-addition {
121
- /* prettylights-syntax-markup-inserted */
122
- color: #22863a;
123
- background-color: #f0fff4
124
- }
125
-
126
- .hljs-deletion {
127
- /* prettylights-syntax-markup-deleted */
128
- color: #b31d28;
129
- background-color: #ffeef0
130
- }
131
-
132
- .hljs-char.escape_,
133
- .hljs-link,
134
- .hljs-params,
135
- .hljs-property,
136
- .hljs-punctuation,
137
- .hljs-tag {
138
- /* purposely ignored */
139
18
 
140
- }
141
-
142
- @media (prefers-color-scheme: dark) {
19
+ @layer reset, typography, syntax-highlighting, default, dynamic-typography;
143
20
 
144
- /*!
145
- Theme: GitHub Dark
146
- Description: Dark theme as seen on github.com
147
- Author: github.com
148
- Maintainer: @Hirse
149
- Updated: 2021-05-15
150
-
151
- Outdated base version: https://github.com/primer/github-syntax-dark
152
- Current colors taken from GitHub's CSS
153
- */
154
- .hljs {
155
- color: #c9d1d9;
156
- background: #0d1117
21
+ @layer syntax-highlighting {
22
+ pre[class*="language-"] {
23
+ color: #24292e;
157
24
  }
158
25
 
159
- .hljs-doctag,
160
- .hljs-keyword,
161
- .hljs-meta .hljs-keyword,
162
- .hljs-template-tag,
163
- .hljs-template-variable,
164
- .hljs-type,
165
- .hljs-variable.language_ {
166
- /* prettylights-syntax-keyword */
167
- color: #ff7b72
26
+ pre[class*="language-"]>code {
27
+ display: block;
28
+ overflow-x: auto;
29
+ padding: 1em;
168
30
  }
169
31
 
170
- .hljs-title,
171
- .hljs-title.class_,
172
- .hljs-title.class_.inherited__,
173
- .hljs-title.function_ {
174
- /* prettylights-syntax-entity */
175
- color: #d2a8ff
32
+ /* prettylights-syntax-keyword */
33
+ .token.keyword,
34
+ .token.atrule,
35
+ .token.rule,
36
+ .token.important {
37
+ color: #d73a49;
176
38
  }
177
39
 
178
- .hljs-attr,
179
- .hljs-attribute,
180
- .hljs-literal,
181
- .hljs-meta,
182
- .hljs-number,
183
- .hljs-operator,
184
- .hljs-variable,
185
- .hljs-selector-attr,
186
- .hljs-selector-class,
187
- .hljs-selector-id {
188
- /* prettylights-syntax-constant */
189
- color: #79c0ff
40
+ /* prettylights-syntax-entity */
41
+ .token.function,
42
+ .token.class-name {
43
+ color: #6f42c1;
190
44
  }
191
45
 
192
- .hljs-regexp,
193
- .hljs-string,
194
- .hljs-meta .hljs-string {
195
- /* prettylights-syntax-string */
196
- color: #a5d6ff
46
+ /* prettylights-syntax-constant */
47
+ .token.number,
48
+ .token.boolean,
49
+ .token.constant,
50
+ .token.operator,
51
+ .token.variable,
52
+ .token.property,
53
+ .token.attr-name,
54
+ .token.entity,
55
+ .token.doctype,
56
+ .token.prolog,
57
+ .token.key {
58
+ color: #005cc5;
197
59
  }
198
60
 
199
- .hljs-built_in,
200
- .hljs-symbol {
201
- /* prettylights-syntax-variable */
202
- color: #ffa657
61
+ /* prettylights-syntax-string */
62
+ .token.string,
63
+ .token.char,
64
+ .token.attr-value,
65
+ .token.regex,
66
+ .token.url {
67
+ color: #032f62;
203
68
  }
204
69
 
205
- .hljs-comment,
206
- .hljs-code,
207
- .hljs-formula {
208
- /* prettylights-syntax-comment */
209
- color: #8b949e
70
+ /* prettylights-syntax-variable */
71
+ .token.builtin,
72
+ .token.symbol {
73
+ color: #e36209;
210
74
  }
211
75
 
212
- .hljs-name,
213
- .hljs-quote,
214
- .hljs-selector-tag,
215
- .hljs-selector-pseudo {
216
- /* prettylights-syntax-entity-tag */
217
- color: #7ee787
76
+ /* prettylights-syntax-comment: also markdown's code, whose language
77
+ is highlighted inside it */
78
+ .token.comment,
79
+ .token.cdata,
80
+ .token.code-snippet,
81
+ .token.code.keyword {
82
+ color: #6a737d;
218
83
  }
219
84
 
220
- .hljs-subst {
221
- /* prettylights-syntax-storage-modifier-import */
222
- color: #c9d1d9
85
+ /* prettylights-syntax-entity-tag */
86
+ .token.tag,
87
+ .token.selector,
88
+ .token.blockquote {
89
+ color: #22863a;
223
90
  }
224
91
 
225
- .hljs-section {
226
- /* prettylights-syntax-markup-heading */
227
- color: #1f6feb;
228
- font-weight: bold
92
+ /* prettylights-syntax-markup-heading */
93
+ .token.title {
94
+ color: #005cc5;
95
+ font-weight: bold;
229
96
  }
230
97
 
231
- .hljs-bullet {
232
- /* prettylights-syntax-markup-list */
233
- color: #f2cc60
98
+ /* prettylights-syntax-markup-list */
99
+ .token.list,
100
+ .token.checkbox {
101
+ color: #735c0f;
234
102
  }
235
103
 
236
- .hljs-emphasis {
237
- /* prettylights-syntax-markup-italic */
238
- color: #c9d1d9;
239
- font-style: italic
104
+ .token.table-header {
105
+ color: inherit;
106
+ font-weight: bold;
240
107
  }
241
108
 
242
- .hljs-strong {
243
- /* prettylights-syntax-markup-bold */
244
- color: #c9d1d9;
245
- font-weight: bold
109
+ .token.bold {
110
+ font-weight: bold;
246
111
  }
247
112
 
248
- .hljs-addition {
249
- /* prettylights-syntax-markup-inserted */
250
- color: #aff5b4;
251
- background-color: #033a16
113
+ .token.italic {
114
+ font-style: italic;
252
115
  }
253
116
 
254
- .hljs-deletion {
255
- /* prettylights-syntax-markup-deleted */
256
- color: #ffdcd7;
257
- background-color: #67060c
117
+ .token.strike {
118
+ text-decoration: line-through;
258
119
  }
259
120
 
260
- .hljs-char.escape_,
261
- .hljs-link,
262
- .hljs-params,
263
- .hljs-property,
264
- .hljs-punctuation,
265
- .hljs-tag {
266
- /* purposely ignored */
121
+ /* prettylights-syntax-markup-inserted */
122
+ .token.inserted {
123
+ color: #22863a;
124
+ background-color: #f0fff4;
125
+ }
267
126
 
127
+ /* prettylights-syntax-markup-deleted */
128
+ .token.deleted {
129
+ color: #b31d28;
130
+ background-color: #ffeef0;
131
+ }
132
+
133
+ @media (prefers-color-scheme: dark) {
134
+ pre[class*="language-"] {
135
+ color: #c9d1d9;
136
+ background: #0d1117;
137
+ }
138
+
139
+ .token.keyword,
140
+ .token.atrule,
141
+ .token.rule,
142
+ .token.important {
143
+ color: #ff7b72;
144
+ }
145
+
146
+ .token.function,
147
+ .token.class-name {
148
+ color: #d2a8ff;
149
+ }
150
+
151
+ .token.number,
152
+ .token.boolean,
153
+ .token.constant,
154
+ .token.operator,
155
+ .token.variable,
156
+ .token.property,
157
+ .token.attr-name,
158
+ .token.entity,
159
+ .token.doctype,
160
+ .token.prolog,
161
+ .token.key {
162
+ color: #79c0ff;
163
+ }
164
+
165
+ .token.string,
166
+ .token.char,
167
+ .token.attr-value,
168
+ .token.regex,
169
+ .token.url {
170
+ color: #a5d6ff;
171
+ }
172
+
173
+ .token.builtin,
174
+ .token.symbol {
175
+ color: #ffa657;
176
+ }
177
+
178
+ .token.comment,
179
+ .token.cdata,
180
+ .token.code-snippet,
181
+ .token.code.keyword {
182
+ color: #8b949e;
183
+ }
184
+
185
+ .token.tag,
186
+ .token.selector,
187
+ .token.blockquote {
188
+ color: #7ee787;
189
+ }
190
+
191
+ .token.title {
192
+ color: #1f6feb;
193
+ }
194
+
195
+ .token.list,
196
+ .token.checkbox {
197
+ color: #f2cc60;
198
+ }
199
+
200
+ .token.table-header {
201
+ color: inherit;
202
+ }
203
+
204
+ .token.inserted {
205
+ color: #aff5b4;
206
+ background-color: #033a16;
207
+ }
208
+
209
+ .token.deleted {
210
+ color: #ffdcd7;
211
+ background-color: #67060c;
212
+ }
268
213
  }
269
- }
214
+ }
@@ -1,4 +1,4 @@
1
- @layer reset, typography;
1
+ @layer reset, typography, syntax-highlighting;
2
2
 
3
3
  @layer typography {
4
4