Draws Claude's replies in color: headings, bold, italics, inline code, links, list markers and highlighted code blocks, in a Monokai Pro theme. Display only…

Monokai Pro colors for Claude Code's replies.
Out of the box, Claude Code draws bold text, italics and headings in the same color as everything else, and colors code blocks from a fixed set of 16 terminal colors. Its /theme setting can't change either. This plugin can. It's a mod that redraws each reply with a full palette: colored headings and emphasis, highlighted inline code and links, and Monokai syntax highlighting in code blocks.
It only changes how replies look. Your saved conversations and what Claude reads stay exactly the same, and it adds nothing to your token usage.
Paste either prompt into Claude Code.
Set up Claude Code Themes for me (github.com/danishmughal/claude-code-themes):
1. Check that `claude --version` is 2.1.287 or newer; run `claude update` if not.
2. Run `claude plugin marketplace add danishmughal/claude-code-themes`.
3. Read the repo's README and ask me which theme I want.
4. Run `claude plugin install themes@claude-code-themes --config theme=<my pick>`.
5. Tell me to run /reload-plugins.
Set up Claude Code Themes for me (github.com/danishmughal/claude-code-themes):
1. Check that `claude --version` is 2.1.287 or newer; run `claude update` if not.
2. Run `claude plugin marketplace add danishmughal/claude-code-themes`.
3. Read the repo's README and ask me which theme I want.
4. Run `claude plugin install themes@claude-code-themes --config theme=<my pick>`.
5. Star the repo: `gh api -X PUT user/starred/danishmughal/claude-code-themes`
(skip this if gh isn't signed in).
6. Tell me to run /reload-plugins.
Claude asks which theme you want and installs it. After /reload-plugins, the next reply comes back in color.
You need Claude Code 2.1.287 or later, and a terminal that shows full 24-bit color.
claude plugin marketplace add danishmughal/claude-code-themes
claude plugin install themes@claude-code-themes
This repository is private, so the machine needs GitHub access to it: either an SSH key loaded in ssh-agent, or gh auth login followed by gh auth setup-git.
Then start a new session. To confirm the plugin loaded, run /plugin; it shows 1 mod active · themes.
If the install prints 1 userConfig option not yet set, that's only the theme choice. Until you pick one, you get the default, monokai-pro-classic.
There's one theme for each of the six Monokai Pro palettes. Pick the one that matches your terminal's theme; Warp includes all six.
Switch anytime with /plugin configure themes@claude-code-themes inside Claude Code, or choose one when you install:
claude plugin install themes@claude-code-themes --config theme=monokai-pro
Every theme colors the same parts of a reply:
| Part of a reply | Color | | :- | :- | | Headings and list markers | green | | Bold and italic text | blue | | Inline code, and code blocks with no language | orange | | Link text | purple | | Code blocks | keywords red, declarations blue, strings yellow, numbers purple, functions and types green, comments gray |
Each screenshot is a real Claude Code session showing the same reply, on the theme's matching terminal background.
For comparison, this is a reply without the plugin. Bold is only heavier, headings are plain, and code uses the terminal's 16 basic colors.

The Monokai Pro default, on a warm charcoal background, #2d2a2e.
#ff6188 red · #fc9867 orange · #ffd866 yellow · #a9dc76 green · #78dce8 blue · #ab9df2 purple

The original Monokai colors, on #272822. This is the plugin's default.
#f92672 red · #fd971f orange · #e6db74 yellow · #a6e22e green · #66d9ef blue · #ae81ff purple

Cooler, brighter colors on a blue-gray background, #273136.
#ff6d7e red · #ffb270 orange · #ffed72 yellow · #a2e57b green · #7cd5f1 blue · #baa0f8 purple

Softer, muted colors on a navy background, #282a3a.
#ff657a red · #ff9b5e orange · #ffd76d yellow · #bad761 green · #9cd1bb blue · #c39ac9 purple

Warm colors on a dark brown background, #2c2525.
#fd6883 red · #f38d70 orange · #f9cc6c yellow · #adda78 green · #85dacc blue · #a8a9eb purple

Saturated colors on a neutral gray background, #222222.
#fc618d red · #fd9353 orange · #fce566 yellow · #7bd88f green · #5ad4e6 blue · #948ae3 purple

claude plugin update themes@claude-code-themes
Or turn on auto-update for this marketplace under Marketplaces in /plugin.
/plugin doesn't list the mod. Claude Code sessions older than 2.1.287 save a setting that switches mods off, and newer sessions read it when they start. Restart any old sessions, or run claude -p /cost once to refresh the setting, then open a new session./plugin.The plugin handles one event: Claude Code asking how to draw a reply (ui.render for AssistantMessage).
hooks/draw.ts reads the reply with the same markdown parser Claude Code uses (marked, with Claude Code's settings), so line breaks, lists, numbering and spacing match what Claude Code would draw. It then draws paragraphs, lists, headings and code blocks in color.hooks/highlight.ts highlights code with highlight.js, using the token rules of Claude Code's built-in Monokai Extended colors.hooks/palettes.ts holds the themes. To add one, add an entry there and its name to the options list in .claude-plugin/plugin.json.To work on the plugin:
claude --plugin-dir . # load this checkout; edits reload as you save
claude plugin validate .
claude plugin test
hooks/vendor/marked.js is marked 18.0.14, the lib/marked.esm.js file from its npm package (MIT, see hooks/vendor/marked.LICENSE).hooks/vendor/hljs/ is highlight.js 11.12.0: es/core.js and es/languages/<name>.min.js from @highlightjs/cdn-assets, each language saved as <name>.js (BSD-3-Clause, see hooks/vendor/hljs/LICENSE). To add a language, copy its file in and register it in hooks/highlight.ts.MIT
hooks/register.ts 17 lines1import type { Register } from 'claude-code'
2
3import { draw } from './draw'
4import { themeNamed } from './palettes'
5
6export const register: Register = (on, options) => {
7 // The theme picked with /plugin configure, read each time the mod loads
8 const theme = themeNamed((options as { theme?: unknown } | undefined)?.theme)
9
10 // Redraws each reply block in the theme's colors. Only the drawing changes:
11 // the stored message, and what Claude reads next turn, stay as written.
12 on('ui.render', { component: 'AssistantMessage' }, ($, e, next) => {
13 if (e.surface !== 'terminal') return next(e)
14 return draw($.ui.resolve(e), e.props.text, e.props.isFirstOfReply, theme) ?? next(e)
15 })
16}
17hooks/draw.ts 259 lines1// Draws one assistant reply block the way Claude Code's own renderer does,
2// in the chosen theme's colors. Paragraphs, lists, headings and code blocks
3// are drawn here from marked's tokens; every other block (tables, quotes,
4// rules) goes to Claude Code's own Markdown element unchanged.
5import type { Elements, RenderElement, RenderNode } from 'claude-code'
6
7import { highlight, languageOf } from './highlight'
8import { lex } from './lexer'
9import type { Token } from './lexer'
10import type { Theme } from './palettes'
11
12type Table = Elements['terminal']
13
14// The theme of the draw in progress; draw() runs start to finish without
15// awaiting, so no other draw can change it midway
16let theme: Theme
17
18// Element string and Markdown text limits
19const MAX_CHARS = 10000
20// The reply bullet: BLACK CIRCLE FOR RECORD, U+23FA, which Claude Code draws on
21// macOS. Elsewhere it draws U+25CF; a mod has no way to read the platform.
22const BULLET = String.fromCodePoint(0x23fa)
23// Claude Code caps a nested list's indent at this many columns
24const MAX_INDENT = 32
25
26class Unsupported extends Error {}
27
28// Returns null when Claude Code should draw the block itself
29export function draw(t: Table, text: string, isFirstOfReply: boolean, active: Theme): RenderElement | null {
30 theme = active
31 let body: RenderElement[]
32 try {
33 body = blocks(t, lex(text))
34 } catch (err) {
35 if (err instanceof Unsupported) return null
36 throw err
37 }
38 if (body.length === 0) return null
39 const dot = isFirstOfReply
40 ? [t.Box({ minWidth: 2, flexShrink: 0, children: [t.Text({ color: 'text', children: [BULLET] })] })]
41 : []
42 return t.Box({
43 flexDirection: 'row',
44 alignItems: 'flex-start',
45 width: '100%',
46 marginTop: isFirstOfReply ? 1 : 0,
47 children: [...dot, t.Box({ flexDirection: 'column', flexGrow: 1, flexShrink: 1, children: body })],
48 })
49}
50
51// Top-level blocks, spaced as the engine's string output spaces them: a blank
52// line wherever the source had one, and always after a heading
53function blocks(t: Table, tokens: Token[]): RenderElement[] {
54 const out: RenderElement[] = []
55 let gap = false
56 for (const tok of tokens) {
57 if (tok.type === 'space') {
58 gap = true
59 continue
60 }
61 const el = block(t, tok)
62 out.push(out.length > 0 && gap ? t.Box({ marginTop: 1, children: [el] }) : el)
63 gap = tok.type === 'heading'
64 }
65 return out
66}
67
68function block(t: Table, tok: Token): RenderElement {
69 if (tok.type === 'paragraph') return prose(t, tok.tokens ?? [])
70 if (tok.type === 'list') return list(t, tok, 0)
71 if (tok.type === 'heading') return heading(t, tok)
72 if (tok.type === 'code') return code(t, tok) ?? engine(t, tok.raw)
73 return engine(t, tok.raw)
74}
75
76// A code block: the theme's code colors for a language this mod bundles, the
77// inline code color for a fence with no language, plain for indented code, as
78// the engine draws that. Null for a language only the engine knows.
79function code(t: Table, tok: Token): RenderElement | null {
80 const text = tok.text ?? ''
81 if (tok.codeBlockStyle === 'indented') return t.Text({ children: pieces(text) })
82 const info = (tok.lang ?? '').trim()
83 if (!info) return t.Text({ color: theme.markdown.code, children: pieces(text) })
84 const language = languageOf(info)
85 const spans = language ? highlight(text, language, theme) : null
86 if (!spans) return null
87 return t.Text({
88 children: spans.flatMap((s) =>
89 s.color === theme.foreground ? pieces(s.text) : [t.Text({ color: s.color, children: pieces(s.text) })],
90 ),
91 })
92}
93
94// A string as Text children within the per-string limit
95function pieces(s: string): string[] {
96 const out: string[] = []
97 for (let i = 0; i < s.length; i += MAX_CHARS) out.push(s.slice(i, i + MAX_CHARS))
98 return out
99}
100
101// The engine's heading weights (# bold, italic and underlined; the rest
102// bold), in the heading color
103function heading(t: Table, tok: Token): RenderElement {
104 const top = tok.depth === 1
105 return t.Text({
106 bold: true,
107 color: theme.markdown.heading,
108 ...(top ? { italic: true, underline: true } : {}),
109 children: inline(t, tok.tokens ?? []),
110 })
111}
112
113function engine(t: Table, raw: string): RenderElement {
114 const text = raw.replace(/\n+$/, '')
115 if (text.length > MAX_CHARS) throw new Unsupported()
116 return t.Markdown({ text })
117}
118
119function prose(t: Table, tokens: Token[]): RenderElement {
120 return t.Text({ children: inline(t, tokens) })
121}
122
123// A list, with the engine's markers: "-" for bullets, and for numbers 1. at
124// the top level, a. one level down, i. two levels down
125function list(t: Table, tok: Token, depth: number): RenderElement {
126 const items = tok.items ?? []
127 const first = tok.start === '' || tok.start === undefined ? 1 : tok.start
128 const last = first + items.length - 1
129 const rows = items.map((item, i) => {
130 const marker = tok.ordered ? `${number(first + i, depth, first, last)}.` : '-'
131 const content = itemBody(t, item, depth)
132 const row = t.Box({
133 flexDirection: 'row',
134 children: [
135 t.Box({
136 minWidth: Math.min(marker.length + 1, MAX_INDENT),
137 flexShrink: 0,
138 children: [t.Text({ color: theme.markdown.marker, children: [marker] })],
139 }),
140 t.Box({ flexDirection: 'column', flexGrow: 1, flexShrink: 1, children: content }),
141 ],
142 })
143 return i > 0 && tok.loose ? t.Box({ marginTop: 1, children: [row] }) : row
144 })
145 return t.Box({ flexDirection: 'column', children: rows })
146}
147
148function number(n: number, depth: number, first: number, last: number): string {
149 if (depth === 1 && first >= 1) return letters(n)
150 if (depth === 2 && first >= 1 && last <= 3999) return roman(n)
151 return String(n)
152}
153
154function letters(n: number): string {
155 let s = ''
156 while (n > 0) {
157 n--
158 s = String.fromCharCode(97 + (n % 26)) + s
159 n = Math.floor(n / 26)
160 }
161 return s
162}
163
164const ROMAN: [number, string][] = [
165 [1000, 'm'], [900, 'cm'], [500, 'd'], [400, 'cd'], [100, 'c'], [90, 'xc'],
166 [50, 'l'], [40, 'xl'], [10, 'x'], [9, 'ix'], [5, 'v'], [4, 'iv'], [1, 'i'],
167]
168
169function roman(n: number): string {
170 let s = ''
171 for (const [v, r] of ROMAN) while (n >= v) (s += r), (n -= v)
172 return s
173}
174
175// An item holds text (tight lists), paragraphs (loose lists), nested lists
176// and code, which sits under the item's text. Tables and quotes inside an
177// item get layout this mod doesn't reproduce, so such a reply is left to the
178// engine.
179function itemBody(t: Table, item: Token, depth: number): RenderElement[] {
180 const out: RenderElement[] = []
181 for (const tok of item.tokens ?? []) {
182 if (tok.type === 'space') continue
183 if (tok.type === 'text' || tok.type === 'paragraph') out.push(prose(t, tok.tokens ?? [{ type: 'text', raw: tok.raw, text: tok.text }]))
184 else if (tok.type === 'list') out.push(list(t, tok, depth + 1))
185 else if (tok.type === 'code') out.push(code(t, tok) ?? t.Text({ children: pieces(tok.text ?? '') }))
186 else if (tok.type === 'checkbox') continue
187 else throw new Unsupported()
188 }
189 if (item.task) {
190 const box = t.Text({ children: [item.checked ? '[x] ' : '[ ] '] })
191 if (out.length > 0) out[0] = t.Box({ flexDirection: 'row', children: [box, out[0]] })
192 }
193 return out
194}
195
196// Inline tokens as Text children, styled as the engine styles them, in the
197// theme's colors
198function inline(t: Table, tokens: Token[]): RenderNode[] {
199 const out: RenderNode[] = []
200 for (const tok of tokens) {
201 switch (tok.type) {
202 case 'text':
203 if (tok.tokens) out.push(...inline(t, tok.tokens))
204 else out.push(chars(tok.text ?? tok.raw))
205 break
206 case 'strong':
207 out.push(t.Text({ bold: true, color: theme.markdown.strong, children: inline(t, tok.tokens ?? []) }))
208 break
209 case 'em':
210 out.push(t.Text({ italic: true, color: theme.markdown.em, children: inline(t, tok.tokens ?? []) }))
211 break
212 case 'del':
213 out.push(t.Text({ strikethrough: true, children: inline(t, tok.tokens ?? []) }))
214 break
215 case 'codespan':
216 out.push(t.Text({ color: theme.markdown.code, children: [chars(tok.text ?? '')] }))
217 break
218 case 'link':
219 out.push(link(t, tok))
220 break
221 case 'br':
222 out.push('\n')
223 break
224 case 'checkbox':
225 break
226 case 'image':
227 out.push(chars(tok.text ? `${tok.text} (${tok.href})` : tok.href ?? tok.raw))
228 break
229 default:
230 out.push(chars(tok.text ?? tok.raw))
231 }
232 }
233 return out
234}
235
236function chars(s: string): string {
237 if (s.length > MAX_CHARS) throw new Unsupported()
238 return s
239}
240
241// The Link element refuses the whole tree over a bad href, so anything but a
242// plain https link is drawn as text
243function link(t: Table, tok: Token): RenderNode {
244 const label = t.Text({ color: theme.markdown.link, children: inline(t, tok.tokens ?? []) })
245 const href = safeHref(tok.href ?? '')
246 return href ? t.Link({ href, children: [label] }) : label
247}
248
249function safeHref(href: string): string | null {
250 try {
251 const u = new URL(href)
252 if (u.protocol !== 'https:' || u.username || u.password) return null
253 if (u.href.length > 2048 || !/^[\x21-\x7e]+$/.test(u.href)) return null
254 return u.href
255 } catch {
256 return null
257 }
258}
259hooks/palettes.ts 92 lines1// The themes replies can be drawn in. Each Monokai Pro filter is its
2// published palette; Warp and most editors ship a matching terminal theme of
3// the same name, so pick the one your terminal uses.
4type Palette = {
5 red: string
6 orange: string
7 yellow: string
8 green: string
9 blue: string
10 purple: string
11 comment: string
12 foreground: string
13}
14
15const PALETTES: Record<string, Palette> = {
16 'monokai-pro': {
17 red: '#ff6188', orange: '#fc9867', yellow: '#ffd866', green: '#a9dc76',
18 blue: '#78dce8', purple: '#ab9df2', comment: '#727072', foreground: '#fcfcfa',
19 },
20 'monokai-pro-classic': {
21 red: '#f92672', orange: '#fd971f', yellow: '#e6db74', green: '#a6e22e',
22 blue: '#66d9ef', purple: '#ae81ff', comment: '#6e7066', foreground: '#fdfff1',
23 },
24 'monokai-pro-machine': {
25 red: '#ff6d7e', orange: '#ffb270', yellow: '#ffed72', green: '#a2e57b',
26 blue: '#7cd5f1', purple: '#baa0f8', comment: '#6b7678', foreground: '#f2fffc',
27 },
28 'monokai-pro-octagon': {
29 red: '#ff657a', orange: '#ff9b5e', yellow: '#ffd76d', green: '#bad761',
30 blue: '#9cd1bb', purple: '#c39ac9', comment: '#696d77', foreground: '#eaf2f1',
31 },
32 'monokai-pro-ristretto': {
33 red: '#fd6883', orange: '#f38d70', yellow: '#f9cc6c', green: '#adda78',
34 blue: '#85dacc', purple: '#a8a9eb', comment: '#72696a', foreground: '#fff1f3',
35 },
36 'monokai-pro-spectrum': {
37 red: '#fc618d', orange: '#fd9353', yellow: '#fce566', green: '#7bd88f',
38 blue: '#5ad4e6', purple: '#948ae3', comment: '#69676c', foreground: '#f7f1ff',
39 },
40}
41
42export const DEFAULT_THEME = 'monokai-pro-classic'
43
44export type Theme = {
45 name: string
46 foreground: string
47 // Markdown roles, as Monokai's standard editor theme assigns them
48 markdown: { heading: string; strong: string; em: string; code: string; link: string; marker: string }
49 // highlight.js scopes, as Claude Code's Monokai Extended table assigns them
50 scopes: Map<string, string>
51}
52
53// The named theme, or the default for a name this version doesn't know
54export function themeNamed(name: unknown): Theme {
55 const key = typeof name === 'string' && name in PALETTES ? name : DEFAULT_THEME
56 const p = PALETTES[key]!
57 return {
58 name: key,
59 foreground: p.foreground,
60 markdown: { heading: p.green, strong: p.blue, em: p.blue, code: p.orange, link: p.purple, marker: p.green },
61 scopes: new Map([
62 ['keyword', p.red],
63 // keywords that declare something, as Monokai draws storage
64 ['_storage', p.blue],
65 ['built_in', p.green],
66 ['type', p.green],
67 ['literal', p.purple],
68 ['number', p.purple],
69 ['string', p.yellow],
70 ['title', p.green],
71 ['title.function', p.green],
72 ['title.class', p.green],
73 ['title.class.inherited', p.green],
74 ['params', p.orange],
75 ['comment', p.comment],
76 ['meta', p.comment],
77 ['attr', p.green],
78 ['attribute', p.green],
79 ['variable', p.foreground],
80 ['variable.language', p.foreground],
81 ['property', p.foreground],
82 ['operator', p.red],
83 ['punctuation', p.foreground],
84 ['symbol', p.purple],
85 ['regexp', p.yellow],
86 ['subst', p.foreground],
87 ]),
88 }
89}
90
91export const THEMES = Object.keys(PALETTES)
92hooks/highlight.ts 111 lines1// Syntax highlighting for code blocks. Claude Code highlights reply code with
2// a fixed 16-color table and keeps Monokai Extended for its diff view; this
3// uses that diff view's scope rules, in the theme's colors, over the same
4// highlighter (highlight.js).
5import hljs from './vendor/hljs/core.js'
6import bash from './vendor/hljs/languages/bash.js'
7import c from './vendor/hljs/languages/c.js'
8import cpp from './vendor/hljs/languages/cpp.js'
9import csharp from './vendor/hljs/languages/csharp.js'
10import css from './vendor/hljs/languages/css.js'
11import diff from './vendor/hljs/languages/diff.js'
12import dockerfile from './vendor/hljs/languages/dockerfile.js'
13import go from './vendor/hljs/languages/go.js'
14import graphql from './vendor/hljs/languages/graphql.js'
15import ini from './vendor/hljs/languages/ini.js'
16import java from './vendor/hljs/languages/java.js'
17import javascript from './vendor/hljs/languages/javascript.js'
18import json from './vendor/hljs/languages/json.js'
19import kotlin from './vendor/hljs/languages/kotlin.js'
20import makefile from './vendor/hljs/languages/makefile.js'
21import markdown from './vendor/hljs/languages/markdown.js'
22import php from './vendor/hljs/languages/php.js'
23import plaintext from './vendor/hljs/languages/plaintext.js'
24import python from './vendor/hljs/languages/python.js'
25import ruby from './vendor/hljs/languages/ruby.js'
26import rust from './vendor/hljs/languages/rust.js'
27import scss from './vendor/hljs/languages/scss.js'
28import shell from './vendor/hljs/languages/shell.js'
29import sql from './vendor/hljs/languages/sql.js'
30import swift from './vendor/hljs/languages/swift.js'
31import typescript from './vendor/hljs/languages/typescript.js'
32import xml from './vendor/hljs/languages/xml.js'
33import yaml from './vendor/hljs/languages/yaml.js'
34
35import type { Theme } from './palettes'
36
37const GRAMMARS = {
38 bash, c, cpp, csharp, css, diff, dockerfile, go, graphql, ini, java, javascript, json, kotlin,
39 makefile, markdown, php, plaintext, python, ruby, rust, scss, shell, sql, swift, typescript, xml, yaml,
40}
41for (const [name, grammar] of Object.entries(GRAMMARS)) hljs.registerLanguage(name, grammar)
42
43// Keywords that declare something take the storage color, as in Monokai
44const STORAGE = new Set([
45 'const', 'let', 'var', 'function', 'class', 'type', 'interface', 'enum', 'namespace', 'module',
46 'def', 'fn', 'func', 'struct', 'trait', 'impl',
47])
48
49export type Span = { text: string; color: string }
50
51type Node = { scope?: string; children: (string | Node)[] }
52
53// A code block's language as Claude Code reads it: the whole info string,
54// else its first word
55export function languageOf(info: string): string | null {
56 const word = info.match(/^[\w.+#-]+/)?.[0] ?? ''
57 if (info && hljs.getLanguage(info)) return info
58 if (word && hljs.getLanguage(word)) return word
59 return null
60}
61
62const cache = new Map<string, Span[]>()
63const CACHE_SIZE = 64
64
65// Colored runs for the code, or null when highlight.js can't read it
66export function highlight(code: string, language: string, theme: Theme): Span[] | null {
67 const key = theme.name + '\0' + language + '\0' + code
68 const hit = cache.get(key)
69 if (hit) return hit
70 let root: Node | undefined
71 try {
72 const result = hljs.highlight(code, { language, ignoreIllegals: true })
73 root = result._emitter?.rootNode
74 } catch {
75 return null
76 }
77 if (!root || !Array.isArray(root.children)) return null
78 const spans: Span[] = []
79 walk(root, undefined, theme, spans)
80 if (cache.size >= CACHE_SIZE) cache.delete(cache.keys().next().value!)
81 cache.set(key, spans)
82 return spans
83}
84
85function walk(node: Node, inherited: string | undefined, theme: Theme, out: Span[]) {
86 const scope = node.scope ?? inherited
87 for (const child of node.children) {
88 if (typeof child !== 'string') {
89 walk(child, scope, theme, out)
90 continue
91 }
92 const color = colorOf(scope, child, theme)
93 const last = out[out.length - 1]
94 if (last && last.color === color) last.text += child
95 else out.push({ text: child, color })
96 }
97}
98
99function colorOf(scope: string | undefined, text: string, theme: Theme): string {
100 if (!scope) return theme.foreground
101 if (scope === 'keyword' && STORAGE.has(text.trim())) return theme.scopes.get('_storage')!
102 let s = scope
103 for (;;) {
104 const color = theme.scopes.get(s)
105 if (color) return color
106 const dot = s.lastIndexOf('.')
107 if (dot < 0) return theme.foreground
108 s = s.slice(0, dot)
109 }
110}
111hooks/lexer.ts 42 lines1import { Marked } from './vendor/marked.js'
2
3// Claude Code lexes replies with marked plus two tokenizer overrides. Using
4// the same ones here keeps this mod's blocks identical to the engine's:
5// strikethrough needs a double tilde, and reference definitions stay text.
6const DOUBLE_TILDE = /^~~(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))~~(?=[^~]|$)/
7
8const md = new Marked({ gfm: true })
9md.use({
10 tokenizer: {
11 del(src: string) {
12 const m = DOUBLE_TILDE.exec(src)
13 if (!m || m[1] === undefined) return undefined
14 return { type: 'del', raw: m[0], text: m[1], tokens: this.lexer.inlineTokens(m[1]) }
15 },
16 def() {
17 return undefined
18 },
19 },
20})
21
22export type Token = {
23 type: string
24 raw: string
25 text?: string
26 tokens?: Token[]
27 items?: Token[]
28 ordered?: boolean
29 start?: number | ''
30 loose?: boolean
31 task?: boolean
32 checked?: boolean
33 href?: string
34 depth?: number
35 lang?: string
36 codeBlockStyle?: string
37}
38
39export function lex(text: string): Token[] {
40 return md.lexer(text) as Token[]
41}
42hooks/vendor/hljs/core.js 2607 lines1/*!
2 Highlight.js v11.12.0 (git: f7f7d3803b)
3 (c) 2006-2026 Josh Goebel <hello@joshgoebel.com> and other contributors
4 License: BSD-3-Clause
5 */
6/* eslint-disable no-multi-assign */
7
8function deepFreeze(obj) {
9 if (obj instanceof Map) {
10 obj.clear =
11 obj.delete =
12 obj.set =
13 function () {
14 throw new Error('map is read-only');
15 };
16 } else if (obj instanceof Set) {
17 obj.add =
18 obj.clear =
19 obj.delete =
20 function () {
21 throw new Error('set is read-only');
22 };
23 }
24
25 // Freeze self
26 Object.freeze(obj);
27
28 Object.getOwnPropertyNames(obj).forEach((name) => {
29 const prop = obj[name];
30 const type = typeof prop;
31
32 // Freeze prop if it is an object or function and also not already frozen
33 if ((type === 'object' || type === 'function') && !Object.isFrozen(prop)) {
34 deepFreeze(prop);
35 }
36 });
37
38 return obj;
39}
40
41/** @typedef {import('highlight.js').CallbackResponse} CallbackResponse */
42/** @typedef {import('highlight.js').CompiledMode} CompiledMode */
43/** @implements CallbackResponse */
44
45class Response {
46 /**
47 * @param {CompiledMode} mode
48 */
49 constructor(mode) {
50 // eslint-disable-next-line no-undefined
51 if (mode.data === undefined) mode.data = {};
52
53 this.data = mode.data;
54 this.isMatchIgnored = false;
55 }
56
57 ignoreMatch() {
58 this.isMatchIgnored = true;
59 }
60}
61
62/**
63 * @param {string} value
64 * @returns {string}
65 */
66function escapeHTML(value) {
67 return value
68 .replace(/&/g, '&')
69 .replace(/</g, '<')
70 .replace(/>/g, '>')
71 .replace(/"/g, '"')
72 .replace(/'/g, ''');
73}
74
75/**
76 * performs a shallow merge of multiple objects into one
77 *
78 * @template T
79 * @param {T} original
80 * @param {Record<string,any>[]} objects
81 * @returns {T} a single new object
82 */
83function inherit$1(original, ...objects) {
84 /** @type Record<string,any> */
85 const result = Object.create(null);
86
87 for (const key in original) {
88 result[key] = original[key];
89 }
90 objects.forEach(function(obj) {
91 for (const key in obj) {
92 result[key] = obj[key];
93 }
94 });
95 return /** @type {T} */ (result);
96}
97
98/**
99 * @typedef {object} Renderer
100 * @property {(text: string) => void} addText
101 * @property {(node: Node) => void} openNode
102 * @property {(node: Node) => void} closeNode
103 * @property {() => string} value
104 */
105
106/** @typedef {{scope?: string, language?: string, sublanguage?: boolean}} Node */
107/** @typedef {{walk: (r: Renderer) => void}} Tree */
108/** */
109
110const SPAN_CLOSE = '</span>';
111
112/**
113 * Determines if a node needs to be wrapped in <span>
114 *
115 * @param {Node} node */
116const emitsWrappingTags = (node) => {
117 // rarely we can have a sublanguage where language is undefined
118 // TODO: track down why
119 return !!node.scope;
120};
121
122/**
123 *
124 * @param {string} name
125 * @param {{prefix:string}} options
126 */
127const scopeToCSSClass = (name, { prefix }) => {
128 // sub-language
129 if (name.startsWith("language:")) {
130 return name.replace("language:", "language-");
131 }
132 // tiered scope: comment.line
133 if (name.includes(".")) {
134 const pieces = name.split(".");
135 return [
136 `${prefix}${pieces.shift()}`,
137 ...(pieces.map((x, i) => `${x}${"_".repeat(i + 1)}`))
138 ].join(" ");
139 }
140 // simple scope
141 return `${prefix}${name}`;
142};
143
144/** @type {Renderer} */
145class HTMLRenderer {
146 /**
147 * Creates a new HTMLRenderer
148 *
149 * @param {Tree} parseTree - the parse tree (must support `walk` API)
150 * @param {{classPrefix: string}} options
151 */
152 constructor(parseTree, options) {
153 this.buffer = "";
154 this.classPrefix = options.classPrefix;
155 parseTree.walk(this);
156 }
157
158 /**
159 * Adds texts to the output stream
160 *
161 * @param {string} text */
162 addText(text) {
163 this.buffer += escapeHTML(text);
164 }
165
166 /**
167 * Adds a node open to the output stream (if needed)
168 *
169 * @param {Node} node */
170 openNode(node) {
171 if (!emitsWrappingTags(node)) return;
172
173 const className = scopeToCSSClass(node.scope,
174 { prefix: this.classPrefix });
175 this.span(className);
176 }
177
178 /**
179 * Adds a node close to the output stream (if needed)
180 *
181 * @param {Node} node */
182 closeNode(node) {
183 if (!emitsWrappingTags(node)) return;
184
185 this.buffer += SPAN_CLOSE;
186 }
187
188 /**
189 * returns the accumulated buffer
190 */
191 value() {
192 return this.buffer;
193 }
194
195 // helpers
196
197 /**
198 * Builds a span element
199 *
200 * @param {string} className */
201 span(className) {
202 this.buffer += `<span class="${className}">`;
203 }
204}
205
206/** @typedef {{scope?: string, language?: string, children: Node[]} | string} Node */
207/** @typedef {{scope?: string, language?: string, children: Node[]} } DataNode */
208/** @typedef {import('highlight.js').Emitter} Emitter */
209/** */
210
211/** @returns {DataNode} */
212const newNode = (opts = {}) => {
213 /** @type DataNode */
214 const result = { children: [] };
215 Object.assign(result, opts);
216 return result;
217};
218
219class TokenTree {
220 constructor() {
221 /** @type DataNode */
222 this.rootNode = newNode();
223 this.stack = [this.rootNode];
224 }
225
226 get top() {
227 return this.stack[this.stack.length - 1];
228 }
229
230 get root() { return this.rootNode; }
231
232 /** @param {Node} node */
233 add(node) {
234 this.top.children.push(node);
235 }
236
237 /** @param {string} scope */
238 openNode(scope) {
239 /** @type Node */
240 const node = newNode({ scope });
241 this.add(node);
242 this.stack.push(node);
243 }
244
245 closeNode() {
246 if (this.stack.length > 1) {
247 return this.stack.pop();
248 }
249 // eslint-disable-next-line no-undefined
250 return undefined;
251 }
252
253 closeAllNodes() {
254 while (this.closeNode());
255 }
256
257 toJSON() {
258 return JSON.stringify(this.rootNode, null, 4);
259 }
260
261 /**
262 * @typedef { import("./html_renderer").Renderer } Renderer
263 * @param {Renderer} builder
264 */
265 walk(builder) {
266 // this does not
267 return this.constructor._walk(builder, this.rootNode);
268 // this works
269 // return TokenTree._walk(builder, this.rootNode);
270 }
271
272 /**
273 * @param {Renderer} builder
274 * @param {Node} node
275 */
276 static _walk(builder, node) {
277 if (typeof node === "string") {
278 builder.addText(node);
279 } else if (node.children) {
280 builder.openNode(node);
281 node.children.forEach((child) => this._walk(builder, child));
282 builder.closeNode(node);
283 }
284 return builder;
285 }
286
287 /**
288 * @param {Node} node
289 */
290 static _collapse(node) {
291 if (typeof node === "string") return;
292 if (!node.children) return;
293
294 if (node.children.every(el => typeof el === "string")) {
295 // node.text = node.children.join("");
296 // delete node.children;
297 node.children = [node.children.join("")];
298 } else {
299 node.children.forEach((child) => {
300 TokenTree._collapse(child);
301 });
302 }
303 }
304}
305
306/**
307 Currently this is all private API, but this is the minimal API necessary
308 that an Emitter must implement to fully support the parser.
309
310 Minimal interface:
311
312 - addText(text)
313 - __addSublanguage(emitter, subLanguageName)
314 - startScope(scope)
315 - endScope()
316 - finalize()
317 - toHTML()
318
319*/
320
321/**
322 * @implements {Emitter}
323 */
324class TokenTreeEmitter extends TokenTree {
325 /**
326 * @param {*} options
327 */
328 constructor(options) {
329 super();
330 this.options = options;
331 }
332
333 /**
334 * @param {string} text
335 */
336 addText(text) {
337 if (text === "") { return; }
338
339 this.add(text);
340 }
341
342 /** @param {string} scope */
343 startScope(scope) {
344 this.openNode(scope);
345 }
346
347 endScope() {
348 this.closeNode();
349 }
350
351 /**
352 * @param {Emitter & {root: DataNode}} emitter
353 * @param {string} name
354 */
355 __addSublanguage(emitter, name) {
356 /** @type DataNode */
357 const node = emitter.root;
358 if (name) node.scope = `language:${name}`;
359
360 this.add(node);
361 }
362
363 toHTML() {
364 const renderer = new HTMLRenderer(this, this.options);
365 return renderer.value();
366 }
367
368 finalize() {
369 this.closeAllNodes();
370 return true;
371 }
372}
373
374/**
375 * @param {string} value
376 * @returns {RegExp}
377 * */
378
379/**
380 * @param {RegExp | string } re
381 * @returns {string}
382 */
383function source(re) {
384 if (!re) return null;
385 if (typeof re === "string") return re;
386
387 return re.source;
388}
389
390/**
391 * @param {RegExp | string } re
392 * @returns {string}
393 */
394function lookahead(re) {
395 return concat('(?=', re, ')');
396}
397
398/**
399 * @param {RegExp | string } re
400 * @returns {string}
401 */
402function anyNumberOfTimes(re) {
403 return concat('(?:', re, ')*');
404}
405
406/**
407 * @param {RegExp | string } re
408 * @returns {string}
409 */
410function optional(re) {
411 return concat('(?:', re, ')?');
412}
413
414/**
415 * @param {...(RegExp | string) } args
416 * @returns {string}
417 */
418function concat(...args) {
419 const joined = args.map((x) => source(x)).join("");
420 return joined;
421}
422
423/**
424 * @param { Array<string | RegExp | Object> } args
425 * @returns {object}
426 */
427function stripOptionsFromArgs(args) {
428 const opts = args[args.length - 1];
429
430 if (typeof opts === 'object' && opts.constructor === Object) {
431 args.splice(args.length - 1, 1);
432 return opts;
433 } else {
434 return {};
435 }
436}
437
438/** @typedef { {capture?: boolean} } RegexEitherOptions */
439
440/**
441 * Any of the passed expresssions may match
442 *
443 * Creates a huge this | this | that | that match
444 * @param {(RegExp | string)[] | [...(RegExp | string)[], RegexEitherOptions]} args
445 * @returns {string}
446 */
447function either(...args) {
448 /** @type { object & {capture?: boolean} } */
449 const opts = stripOptionsFromArgs(args);
450 const joined = '('
451 + (opts.capture ? "" : "?:")
452 + args.map((x) => source(x)).join("|") + ")";
453 return joined;
454}
455
456/**
457 * @param {RegExp | string} re
458 * @returns {number}
459 */
460function countMatchGroups(re) {
461 return (new RegExp(re.toString() + '|')).exec('').length - 1;
462}
463
464/**
465 * Does lexeme start with a regular expression match at the beginning
466 * @param {RegExp} re
467 * @param {string} lexeme
468 */
469function startsWith(re, lexeme) {
470 const match = re && re.exec(lexeme);
471 return match && match.index === 0;
472}
473
474// BACKREF_RE matches an open parenthesis or backreference. To avoid an
475// incorrect parse, it also matches the constructs where the meaning of
476// parentheses, escapes, or capture counting changes.
477const BACKREF_RE = new RegExp(either(
478 /\[(?:[^\\\]]|\\.)*\]/, // a character class, inside which ( and \ lose their meaning
479 /\(\?<(?![=!])[^>]+>/, // a named capture group `(?<name>` (not a lookbehind `(?<=` / `(?<!`)
480 /\(\?'[^']+'/, // a named capture group `(?'name'`
481 /\(\??/, // an opening parenthesis, capturing or non-capturing / lookahead
482 /\\([1-9][0-9]*)/, // a backreference like `\1`
483 /\\./ // any other escape sequence
484));
485
486// **INTERNAL** Not intended for outside usage
487// join logically computes regexps.join(separator), but fixes the
488// backreferences so they continue to match.
489// it also places each individual regular expression into it's own
490// match group, keeping track of the sequencing of those match groups
491// is currently an exercise for the caller. :-)
492/**
493 * @param {(string | RegExp)[]} regexps
494 * @param {{joinWith: string}} opts
495 * @returns {string}
496 */
497function _rewriteBackreferences(regexps, { joinWith }) {
498 let numCaptures = 0;
499
500 return regexps.map((regex) => {
501 numCaptures += 1;
502 const offset = numCaptures;
503 let re = source(regex);
504 let out = '';
505
506 while (re.length > 0) {
507 const match = BACKREF_RE.exec(re);
508 if (!match) {
509 out += re;
510 break;
511 }
512 out += re.substring(0, match.index);
513 re = re.substring(match.index + match[0].length);
514 if (match[0][0] === '\\' && match[1]) {
515 // Adjust the backreference.
516 out += '\\' + String(Number(match[1]) + offset);
517 } else {
518 out += match[0];
519 if (match[0] === '(' || /^\(\?[<']/.test(match[0])) {
520 numCaptures++;
521 }
522 }
523 }
524 return out;
525 }).map(re => `(${re})`).join(joinWith);
526}
527
528/** @typedef {import('highlight.js').Mode} Mode */
529/** @typedef {import('highlight.js').ModeCallback} ModeCallback */
530
531// Common regexps
532const MATCH_NOTHING_RE = /\b\B/;
533const IDENT_RE = '[a-zA-Z]\\w*';
534const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*';
535const NUMBER_RE = '\\b\\d+(\\.\\d+)?';
536const C_NUMBER_RE = '(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float
537const BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b...
538const RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~';
539
540/**
541* @param { Partial<Mode> & {binary?: string | RegExp} } opts
542*/
543const SHEBANG = (opts = {}) => {
544 const beginShebang = /^#![ ]*\//;
545 if (opts.binary) {
546 opts.begin = concat(
547 beginShebang,
548 /.*\b/,
549 opts.binary,
550 /\b.*/);
551 }
552 return inherit$1({
553 scope: 'meta',
554 begin: beginShebang,
555 end: /$/,
556 relevance: 0,
557 /** @type {ModeCallback} */
558 "on:begin": (m, resp) => {
559 if (m.index !== 0) resp.ignoreMatch();
560 }
561 }, opts);
562};
563
564// Common modes
565const BACKSLASH_ESCAPE = {
566 begin: '\\\\[\\s\\S]', relevance: 0
567};
568const APOS_STRING_MODE = {
569 scope: 'string',
570 begin: '\'',
571 end: '\'',
572 illegal: '\\n',
573 contains: [BACKSLASH_ESCAPE]
574};
575const QUOTE_STRING_MODE = {
576 scope: 'string',
577 begin: '"',
578 end: '"',
579 illegal: '\\n',
580 contains: [BACKSLASH_ESCAPE]
581};
582const PHRASAL_WORDS_MODE = {
583 begin: /\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/
584};
585/**
586 * Creates a comment mode
587 *
588 * @param {string | RegExp} begin
589 * @param {string | RegExp} end
590 * @param {Mode | {}} [modeOptions]
591 * @returns {Partial<Mode>}
592 */
593const COMMENT = function(begin, end, modeOptions = {}) {
594 const mode = inherit$1(
595 {
596 scope: 'comment',
597 begin,
598 end,
599 contains: []
600 },
601 modeOptions
602 );
603 mode.contains.push({
604 scope: 'doctag',
605 // hack to avoid the space from being included. the space is necessary to
606 // match here to prevent the plain text rule below from gobbling up doctags
607 begin: '[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)',
608 end: /(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,
609 excludeBegin: true,
610 relevance: 0
611 });
612 const ENGLISH_WORD = either(
613 // list of common 1 and 2 letter words in English
614 "I",
615 "a",
616 "is",
617 "so",
618 "us",
619 "to",
620 "at",
621 "if",
622 "in",
623 "it",
624 "on",
625 // note: this is not an exhaustive list of contractions, just popular ones
626 /[A-Za-z]+['](d|ve|re|ll|t|s|n)/, // contractions - can't we'd they're let's, etc
627 /[A-Za-z]+[-][a-z]+/, // `no-way`, etc.
628 /[A-Za-z][a-z]{2,}/ // allow capitalized words at beginning of sentences
629 );
630 // looking like plain text, more likely to be a comment
631 mode.contains.push(
632 {
633 // TODO: how to include ", (, ) without breaking grammars that use these for
634 // comment delimiters?
635 // begin: /[ ]+([()"]?([A-Za-z'-]{3,}|is|a|I|so|us|[tT][oO]|at|if|in|it|on)[.]?[()":]?([.][ ]|[ ]|\))){3}/
636 // ---
637
638 // this tries to find sequences of 3 english words in a row (without any
639 // "programming" type syntax) this gives us a strong signal that we've
640 // TRULY found a comment - vs perhaps scanning with the wrong language.
641 // It's possible to find something that LOOKS like the start of the
642 // comment - but then if there is no readable text - good chance it is a
643 // false match and not a comment.
644 //
645 // for a visual example please see:
646 // https://github.com/highlightjs/highlight.js/issues/2827
647
648 begin: concat(
649 /[ ]+/, // necessary to prevent us gobbling up doctags like /* @author Bob Mcgill */
650 '(',
651 ENGLISH_WORD,
652 /[.]?[:]?([.][ ]|[ ])/,
653 '){3}') // look for 3 words in a row
654 }
655 );
656 return mode;
657};
658const C_LINE_COMMENT_MODE = COMMENT('//', '$');
659const C_BLOCK_COMMENT_MODE = COMMENT('/\\*', '\\*/');
660const HASH_COMMENT_MODE = COMMENT('#', '$');
661const NUMBER_MODE = {
662 scope: 'number',
663 begin: NUMBER_RE,
664 relevance: 0
665};
666const C_NUMBER_MODE = {
667 scope: 'number',
668 begin: C_NUMBER_RE,
669 relevance: 0
670};
671const BINARY_NUMBER_MODE = {
672 scope: 'number',
673 begin: BINARY_NUMBER_RE,
674 relevance: 0
675};
676const REGEXP_MODE = {
677 scope: "regexp",
678 begin: /\/(?=[^/\n]*\/)/,
679 end: /\/[gimuy]*/,
680 contains: [
681 BACKSLASH_ESCAPE,
682 {
683 begin: /\[/,
684 end: /\]/,
685 relevance: 0,
686 contains: [BACKSLASH_ESCAPE]
687 }
688 ]
689};
690const TITLE_MODE = {
691 scope: 'title',
692 begin: IDENT_RE,
693 relevance: 0
694};
695const UNDERSCORE_TITLE_MODE = {
696 scope: 'title',
697 begin: UNDERSCORE_IDENT_RE,
698 relevance: 0
699};
700const METHOD_GUARD = {
701 // excludes method names from keyword processing
702 begin: '\\.\\s*' + UNDERSCORE_IDENT_RE,
703 relevance: 0
704};
705
706/**
707 * Adds end same as begin mechanics to a mode
708 *
709 * Your mode must include at least a single () match group as that first match
710 * group is what is used for comparison
711 * @param {Partial<Mode>} mode
712 */
713const END_SAME_AS_BEGIN = function(mode) {
714 return Object.assign(mode,
715 {
716 /** @type {ModeCallback} */
717 'on:begin': (m, resp) => { resp.data._beginMatch = m[1]; },
718 /** @type {ModeCallback} */
719 'on:end': (m, resp) => { if (resp.data._beginMatch !== m[1]) resp.ignoreMatch(); }
720 });
721};
722
723var MODES = /*#__PURE__*/Object.freeze({
724 __proto__: null,
725 APOS_STRING_MODE: APOS_STRING_MODE,
726 BACKSLASH_ESCAPE: BACKSLASH_ESCAPE,
727 BINARY_NUMBER_MODE: BINARY_NUMBER_MODE,
728 BINARY_NUMBER_RE: BINARY_NUMBER_RE,
729 COMMENT: COMMENT,
730 C_BLOCK_COMMENT_MODE: C_BLOCK_COMMENT_MODE,
731 C_LINE_COMMENT_MODE: C_LINE_COMMENT_MODE,
732 C_NUMBER_MODE: C_NUMBER_MODE,
733 C_NUMBER_RE: C_NUMBER_RE,
734 END_SAME_AS_BEGIN: END_SAME_AS_BEGIN,
735 HASH_COMMENT_MODE: HASH_COMMENT_MODE,
736 IDENT_RE: IDENT_RE,
737 MATCH_NOTHING_RE: MATCH_NOTHING_RE,
738 METHOD_GUARD: METHOD_GUARD,
739 NUMBER_MODE: NUMBER_MODE,
740 NUMBER_RE: NUMBER_RE,
741 PHRASAL_WORDS_MODE: PHRASAL_WORDS_MODE,
742 QUOTE_STRING_MODE: QUOTE_STRING_MODE,
743 REGEXP_MODE: REGEXP_MODE,
744 RE_STARTERS_RE: RE_STARTERS_RE,
745 SHEBANG: SHEBANG,
746 TITLE_MODE: TITLE_MODE,
747 UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE,
748 UNDERSCORE_TITLE_MODE: UNDERSCORE_TITLE_MODE
749});
750
751/**
752@typedef {import('highlight.js').CallbackResponse} CallbackResponse
753@typedef {import('highlight.js').CompilerExt} CompilerExt
754*/
755
756// Grammar extensions / plugins
757// See: https://github.com/highlightjs/highlight.js/issues/2833
758
759// Grammar extensions allow "syntactic sugar" to be added to the grammar modes
760// without requiring any underlying changes to the compiler internals.
761
762// `compileMatch` being the perfect small example of now allowing a grammar
763// author to write `match` when they desire to match a single expression rather
764// than being forced to use `begin`. The extension then just moves `match` into
765// `begin` when it runs. Ie, no features have been added, but we've just made
766// the experience of writing (and reading grammars) a little bit nicer.
767
768// ------
769
770// TODO: We need negative look-behind support to do this properly
771/**
772 * Skip a match if it has a preceding dot
773 *
774 * This is used for `beginKeywords` to prevent matching expressions such as
775 * `bob.keyword.do()`. The mode compiler automatically wires this up as a
776 * special _internal_ 'on:begin' callback for modes with `beginKeywords`
777 * @param {RegExpMatchArray} match
778 * @param {CallbackResponse} response
779 */
780function skipIfHasPrecedingDot(match, response) {
781 const before = match.input[match.index - 1];
782 if (before === ".") {
783 response.ignoreMatch();
784 }
785}
786
787/**
788 *
789 * @type {CompilerExt}
790 */
791function scopeClassName(mode, _parent) {
792 // eslint-disable-next-line no-undefined
793 if (mode.className !== undefined) {
794 mode.scope = mode.className;
795 delete mode.className;
796 }
797}
798
799/**
800 * `beginKeywords` syntactic sugar
801 * @type {CompilerExt}
802 */
803function beginKeywords(mode, parent) {
804 if (!parent) return;
805 if (!mode.beginKeywords) return;
806
807 // for languages with keywords that include non-word characters checking for
808 // a word boundary is not sufficient, so instead we check for a word boundary
809 // or whitespace - this does no harm in any case since our keyword engine
810 // doesn't allow spaces in keywords anyways and we still check for the boundary
811 // first
812 mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')(?!\\.)(?=\\b|\\s)';
813 mode.__beforeBegin = skipIfHasPrecedingDot;
814 mode.keywords = mode.keywords || mode.beginKeywords;
815 delete mode.beginKeywords;
816
817 // prevents double relevance, the keywords themselves provide
818 // relevance, the mode doesn't need to double it
819 // eslint-disable-next-line no-undefined
820 if (mode.relevance === undefined) mode.relevance = 0;
821}
822
823/**
824 * Allow `illegal` to contain an array of illegal values
825 * @type {CompilerExt}
826 */
827function compileIllegal(mode, _parent) {
828 if (!Array.isArray(mode.illegal)) return;
829
830 mode.illegal = either(...mode.illegal);
831}
832
833/**
834 * `match` to match a single expression for readability
835 * @type {CompilerExt}
836 */
837function compileMatch(mode, _parent) {
838 if (!mode.match) return;
839 if (mode.begin || mode.end) throw new Error("begin & end are not supported with match");
840
841 mode.begin = mode.match;
842 delete mode.match;
843}
844
845/**
846 * provides the default 1 relevance to all modes
847 * @type {CompilerExt}
848 */
849function compileRelevance(mode, _parent) {
850 // eslint-disable-next-line no-undefined
851 if (mode.relevance === undefined) mode.relevance = 1;
852}
853
854// allow beforeMatch to act as a "qualifier" for the match
855// the full match begin must be [beforeMatch][begin]
856const beforeMatchExt = (mode, parent) => {
857 if (!mode.beforeMatch) return;
858 // starts conflicts with endsParent which we need to make sure the child
859 // rule is not matched multiple times
860 if (mode.starts) throw new Error("beforeMatch cannot be used with starts");
861
862 const originalMode = Object.assign({}, mode);
863 Object.keys(mode).forEach((key) => { delete mode[key]; });
864
865 mode.keywords = originalMode.keywords;
866 mode.begin = concat(originalMode.beforeMatch, lookahead(originalMode.begin));
867 mode.starts = {
868 relevance: 0,
869 contains: [
870 Object.assign(originalMode, { endsParent: true })
871 ]
872 };
873 mode.relevance = 0;
874
875 delete originalMode.beforeMatch;
876};
877
878// keywords that should have no default relevance value
879const COMMON_KEYWORDS = [
880 'of',
881 'and',
882 'for',
883 'in',
884 'not',
885 'or',
886 'if',
887 'then',
888 'parent', // common variable name
889 'list', // common variable name
890 'value' // common variable name
891];
892
893const DEFAULT_KEYWORD_SCOPE = "keyword";
894
895/**
896 * Given raw keywords from a language definition, compile them.
897 *
898 * @param {string | Record<string,string|string[]> | Array<string>} rawKeywords
899 * @param {boolean} caseInsensitive
900 */
901function compileKeywords(rawKeywords, caseInsensitive, scopeName = DEFAULT_KEYWORD_SCOPE) {
902 /** @type {import("highlight.js/private").KeywordDict} */
903 const compiledKeywords = Object.create(null);
904
905 // input can be a string of keywords, an array of keywords, or a object with
906 // named keys representing scopeName (which can then point to a string or array)
907 if (typeof rawKeywords === 'string') {
908 compileList(scopeName, rawKeywords.split(" "));
909 } else if (Array.isArray(rawKeywords)) {
910 compileList(scopeName, rawKeywords);
911 } else {
912 Object.keys(rawKeywords).forEach(function(scopeName) {
913 // collapse all our objects back into the parent object
914 Object.assign(
915 compiledKeywords,
916 compileKeywords(rawKeywords[scopeName], caseInsensitive, scopeName)
917 );
918 });
919 }
920 return compiledKeywords;
921
922 // ---
923
924 /**
925 * Compiles an individual list of keywords
926 *
927 * Ex: "for if when while|5"
928 *
929 * @param {string} scopeName
930 * @param {Array<string>} keywordList
931 */
932 function compileList(scopeName, keywordList) {
933 if (caseInsensitive) {
934 keywordList = keywordList.map(x => x.toLowerCase());
935 }
936 keywordList.forEach(function(keyword) {
937 const pair = keyword.split('|');
938 compiledKeywords[pair[0]] = [scopeName, scoreForKeyword(pair[0], pair[1])];
939 });
940 }
941}
942
943/**
944 * Returns the proper score for a given keyword
945 *
946 * Also takes into account comment keywords, which will be scored 0 UNLESS
947 * another score has been manually assigned.
948 * @param {string} keyword
949 * @param {string} [providedScore]
950 */
951function scoreForKeyword(keyword, providedScore) {
952 // manual scores always win over common keywords
953 // so you can force a score of 1 if you really insist
954 if (providedScore) {
955 return Number(providedScore);
956 }
957
958 return commonKeyword(keyword) ? 0 : 1;
959}
960
961/**
962 * Determines if a given keyword is common or not
963 *
964 * @param {string} keyword */
965function commonKeyword(keyword) {
966 return COMMON_KEYWORDS.includes(keyword.toLowerCase());
967}
968
969/*
970
971For the reasoning behind this please see:
972https://github.com/highlightjs/highlight.js/issues/2880#issuecomment-747275419
973
974*/
975
976/**
977 * @type {Record<string, boolean>}
978 */
979const seenDeprecations = {};
980
981/**
982 * @param {string} message
983 */
984const error = (message) => {
985 console.error(message);
986};
987
988/**
989 * @param {string} message
990 * @param {any} args
991 */
992const warn = (message, ...args) => {
993 console.log(`WARN: ${message}`, ...args);
994};
995
996/**
997 * @param {string} version
998 * @param {string} message
999 */
1000const deprecated = (version, message) => {
1001 if (seenDeprecations[`${version}/${message}`]) return;
1002
1003 console.log(`Deprecated as of ${version}. ${message}`);
1004 seenDeprecations[`${version}/${message}`] = true;
1005};
1006
1007/* eslint-disable no-throw-literal */
1008
1009/**
1010@typedef {import('highlight.js').CompiledMode} CompiledMode
1011*/
1012
1013const MultiClassError = new Error();
1014
1015/**
1016 * Renumbers labeled scope names to account for additional inner match
1017 * groups that otherwise would break everything.
1018 *
1019 * Lets say we 3 match scopes:
1020 *
1021 * { 1 => ..., 2 => ..., 3 => ... }
1022 *
1023 * So what we need is a clean match like this:
1024 *
1025 * (a)(b)(c) => [ "a", "b", "c" ]
1026 *
1027 * But this falls apart with inner match groups:
1028 *
1029 * (a)(((b)))(c) => ["a", "b", "b", "b", "c" ]
1030 *
1031 * Our scopes are now "out of alignment" and we're repeating `b` 3 times.
1032 * What needs to happen is the numbers are remapped:
1033 *
1034 * { 1 => ..., 2 => ..., 5 => ... }
1035 *
1036 * We also need to know that the ONLY groups that should be output
1037 * are 1, 2, and 5. This function handles this behavior.
1038 *
1039 * @param {CompiledMode} mode
1040 * @param {Array<RegExp | string>} regexes
1041 * @param {{key: "beginScope"|"endScope"}} opts
1042 */
1043function remapScopeNames(mode, regexes, { key }) {
1044 let offset = 0;
1045 const scopeNames = mode[key];
1046 /** @type Record<number,boolean> */
1047 const emit = {};
1048 /** @type Record<number,string> */
1049 const positions = {};
1050
1051 for (let i = 1; i <= regexes.length; i++) {
1052 positions[i + offset] = scopeNames[i];
1053 emit[i + offset] = true;
1054 offset += countMatchGroups(regexes[i - 1]);
1055 }
1056 // we use _emit to keep track of which match groups are "top-level" to avoid double
1057 // output from inside match groups
1058 mode[key] = positions;
1059 mode[key]._emit = emit;
1060 mode[key]._multi = true;
1061}
1062
1063/**
1064 * @param {CompiledMode} mode
1065 */
1066function beginMultiClass(mode) {
1067 if (!Array.isArray(mode.begin)) return;
1068
1069 if (mode.skip || mode.excludeBegin || mode.returnBegin) {
1070 error("skip, excludeBegin, returnBegin not compatible with beginScope: {}");
1071 throw MultiClassError;
1072 }
1073
1074 if (typeof mode.beginScope !== "object" || mode.beginScope === null) {
1075 error("beginScope must be object");
1076 throw MultiClassError;
1077 }
1078
1079 remapScopeNames(mode, mode.begin, { key: "beginScope" });
1080 mode.begin = _rewriteBackreferences(mode.begin, { joinWith: "" });
1081}
1082
1083/**
1084 * @param {CompiledMode} mode
1085 */
1086function endMultiClass(mode) {
1087 if (!Array.isArray(mode.end)) return;
1088
1089 if (mode.skip || mode.excludeEnd || mode.returnEnd) {
1090 error("skip, excludeEnd, returnEnd not compatible with endScope: {}");
1091 throw MultiClassError;
1092 }
1093
1094 if (typeof mode.endScope !== "object" || mode.endScope === null) {
1095 error("endScope must be object");
1096 throw MultiClassError;
1097 }
1098
1099 remapScopeNames(mode, mode.end, { key: "endScope" });
1100 mode.end = _rewriteBackreferences(mode.end, { joinWith: "" });
1101}
1102
1103/**
1104 * this exists only to allow `scope: {}` to be used beside `match:`
1105 * Otherwise `beginScope` would necessary and that would look weird
1106
1107 {
1108 match: [ /def/, /\w+/ ]
1109 scope: { 1: "keyword" , 2: "title" }
1110 }
1111
1112 * @param {CompiledMode} mode
1113 */
1114function scopeSugar(mode) {
1115 if (mode.scope && typeof mode.scope === "object" && mode.scope !== null) {
1116 mode.beginScope = mode.scope;
1117 delete mode.scope;
1118 }
1119}
1120
1121/**
1122 * @param {CompiledMode} mode
1123 */
1124function MultiClass(mode) {
1125 scopeSugar(mode);
1126
1127 if (typeof mode.beginScope === "string") {
1128 mode.beginScope = { _wrap: mode.beginScope };
1129 }
1130 if (typeof mode.endScope === "string") {
1131 mode.endScope = { _wrap: mode.endScope };
1132 }
1133
1134 beginMultiClass(mode);
1135 endMultiClass(mode);
1136}
1137
1138/**
1139@typedef {import('highlight.js').Mode} Mode
1140@typedef {import('highlight.js').CompiledMode} CompiledMode
1141@typedef {import('highlight.js').Language} Language
1142@typedef {import('highlight.js').HLJSPlugin} HLJSPlugin
1143@typedef {import('highlight.js').CompiledLanguage} CompiledLanguage
1144*/
1145
1146// compilation
1147
1148/**
1149 * Compiles a language definition result
1150 *
1151 * Given the raw result of a language definition (Language), compiles this so
1152 * that it is ready for highlighting code.
1153 * @param {Language} language
1154 * @returns {CompiledLanguage}
1155 */
1156function compileLanguage(language) {
1157 /**
1158 * Builds a regex with the case sensitivity of the current language
1159 *
1160 * @param {RegExp | string} value
1161 * @param {boolean} [global]
1162 */
1163 function langRe(value, global) {
1164 return new RegExp(
1165 source(value),
1166 'm'
1167 + (language.case_insensitive ? 'i' : '')
1168 + (language.unicodeRegex ? 'u' : '')
1169 + (global ? 'g' : '')
1170 );
1171 }
1172
1173 /**
1174 Stores multiple regular expressions and allows you to quickly search for
1175 them all in a string simultaneously - returning the first match. It does
1176 this by creating a huge (a|b|c) regex - each individual item wrapped with ()
1177 and joined by `|` - using match groups to track position. When a match is
1178 found checking which position in the array has content allows us to figure
1179 out which of the original regexes / match groups triggered the match.
1180
1181 The match object itself (the result of `Regex.exec`) is returned but also
1182 enhanced by merging in any meta-data that was registered with the regex.
1183 This is how we keep track of which mode matched, and what type of rule
1184 (`illegal`, `begin`, end, etc).
1185 */
1186 class MultiRegex {
1187 constructor() {
1188 this.matchIndexes = {};
1189 // @ts-ignore
1190 this.regexes = [];
1191 this.matchAt = 1;
1192 this.position = 0;
1193 }
1194
1195 // @ts-ignore
1196 addRule(re, opts) {
1197 opts.position = this.position++;
1198 // @ts-ignore
1199 this.matchIndexes[this.matchAt] = opts;
1200 this.regexes.push([opts, re]);hooks/vendor/hljs/languages/bash.js 21 lines1/*! `bash` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict";return e=>{const s=e.regex,t={},a={
3begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]}
4;Object.assign(t,{className:"variable",variants:[{
5begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]});const n={
6className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]
7},c=e.inherit(e.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),i={
8begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,
9end:/(\w+)/,className:"string"})]}},o={className:"string",begin:/"/,end:/"/,
10contains:[e.BACKSLASH_ESCAPE,t,n]};n.contains.push(o);const r={begin:/\$?\(\(/,
11end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t]
12},l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10
13}),m={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,
14contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{
15name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/,
16keyword:["if","then","else","elif","fi","time","for","while","until","in","do","done","case","esac","coproc","function","select"],
17literal:["true","false"],
18built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","sudo","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"]
19},contains:[l,e.SHEBANG(),m,r,c,i,{match:/(\/[a-z._-]+)+/},o,{match:/\\"/},{
20className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}})()
21;export default hljsGrammar;hooks/vendor/hljs/languages/c.js 45 lines1/*! `c` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict";return e=>{
3const t=e.regex,n=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]
4}),a="decltype\\(auto\\)",s="[a-zA-Z_]\\w*::",i="("+a+"|"+t.optional(s)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",r={
5className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{
6match:t.concat(/\batomic_/,t.either("bool","char","schar","uchar","short","ushort","int","uint","long","ulong","llong","ullong","char16_t","char32_t","wchar_t","int_least8_t","uint_least8_t","int_least16_t","uint_least16_t","int_least32_t","uint_least32_t","int_least64_t","uint_least64_t","int_fast8_t","uint_fast8_t","int_fast16_t","uint_fast16_t","int_fast32_t","uint_fast32_t","int_fast64_t","uint_fast64_t","intptr_t","uintptr_t","size_t","ptrdiff_t","intmax_t","uintmax_t"),/\b/)
7}]},l={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",
8contains:[e.BACKSLASH_ESCAPE]},{
9begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",
10end:"'",illegal:"."},e.END_SAME_AS_BEGIN({
11begin:/(?:u8?|U|L)?R"([^()\\\s"]{0,16})\(/,end:/\)([^()\\\s"]{0,16})"/})]},o={
12className:"number",variants:[{match:/\b(0b[01']+)/},{
13match:/(-?)\b([\d']+(\.[\d']*)?|\.[\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)/
14},{
15match:/(-?)\b(0[xX][a-fA-F0-9]+(?:'[a-fA-F0-9]+)*(?:\.[a-fA-F0-9]*(?:'[a-fA-F0-9]*)*)?(?:[pP][-+]?[0-9]+)?(l|L)?(u|U)?)/
16},{match:/(-?)\b\d+(?:'\d+)*(?:\.\d*(?:'\d*)*)?(?:[eE][-+]?\d+)?/}],relevance:0
17},c={scope:"meta",begin:/#\s*include\b/,end:/$/,keywords:{keyword:"include"},
18contains:[{begin:/\\\n/},l,{scope:"string",begin:/<.*?>/
19},n,e.C_BLOCK_COMMENT_MODE]},_={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,
20keywords:{
21keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef elifdef elifndef include"
22},contains:[{begin:/\\\n/,relevance:0},e.inherit(l,{className:"string"
23}),n,e.C_BLOCK_COMMENT_MODE]},d=[c,_],u={className:"title",
24begin:t.optional(s)+e.IDENT_RE,relevance:0
25},m=t.optional(s)+e.IDENT_RE+"\\s*\\(",f={
26keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","typeof","typeof_unqual","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"],
27type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_BitInt","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal96","_Decimal128","_Decimal64x","_Decimal128x","_Float16","_Float32","_Float64","_Float128","_Float32x","_Float64x","_Float128x","const","static","constexpr","complex","bool","imaginary"],
28literal:"true false NULL",
29built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr"
30},p=[...d,r,n,e.C_BLOCK_COMMENT_MODE,o,l],g={variants:[{begin:/=/,end:/;/},{
31begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],
32keywords:f,contains:p.concat([{begin:/\(/,end:/\)/,keywords:f,
33contains:p.concat(["self"]),relevance:0}]),relevance:0},b={
34begin:"("+i+"[\\*&\\s]+){1,12}"+m,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,
35keywords:f,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:a,keywords:f,relevance:0},{
36begin:m,returnBegin:!0,contains:[e.inherit(u,{className:"title.function"})],
37relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,
38keywords:f,relevance:0,contains:[n,e.C_BLOCK_COMMENT_MODE,l,o,r,{begin:/\(/,
39end:/\)/,keywords:f,relevance:0,contains:["self",n,e.C_BLOCK_COMMENT_MODE,l,o,r]
40}]},r,n,e.C_BLOCK_COMMENT_MODE,...d]};return{name:"C",aliases:["h"],keywords:f,
41disableAutodetect:!0,illegal:"</",contains:[].concat(g,b,p,[...d,{
42begin:e.IDENT_RE+"::",keywords:f},{className:"class",
43beginKeywords:"enum class struct union",end:/[{;:<>=]/,contains:[{
44beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:_,
45strings:l,keywords:f}}}})();export default hljsGrammar;hooks/vendor/hljs/languages/cpp.js 49 lines1/*! `cpp` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict";return e=>{
3const t=e.regex,a=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]
4}),n="decltype\\(auto\\)",r="[a-zA-Z_]\\w*::",i="(?!struct)("+n+"|"+t.optional(r)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",s={
5className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{
6begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{
7begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",
8end:"'",illegal:"."},e.END_SAME_AS_BEGIN({
9begin:/(?:u8?|U|L)?R"([^()\\\s"]{0,16})\(/,end:/\)([^()\\\s"]{0,16})"/})]},o={
10className:"number",variants:[{
11begin:"[+-]?(?:(?:\\b[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?|\\.[0-9](?:'?[0-9])*)(?:[Ee][+-]?[0-9](?:'?[0-9])*)?|\\b[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*|\\b0[Xx](?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)[Pp][+-]?[0-9](?:'?[0-9])*)(?:[Ff](?:16|32|64|128)?|(BF|bf)16|[Ll]|)"
12},{
13begin:"[+-]?\\b(?:0[Bb][01](?:'?[01])*|0[Xx][0-9A-Fa-f](?:'?[0-9A-Fa-f])*|0(?:'?[0-7])*|[1-9](?:'?[0-9])*)(?:[Uu](?:LL?|ll?)|[Uu][Zz]?|(?:LL?|ll?)[Uu]?|[Zz][Uu]|)"
14}],relevance:0},l=[{scope:"meta",begin:/#\s*include\b/,end:/$/,keywords:{
15keyword:"include"},contains:[{begin:/\\\n/},c,{scope:"string",begin:/<.*?>/
16},a,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,
17keywords:{
18keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"
19},contains:[{begin:/\\\n/,relevance:0},e.inherit(c,{className:"string"
20}),a,e.C_BLOCK_COMMENT_MODE]}],d={className:"title",
21begin:t.optional(r)+e.IDENT_RE,relevance:0
22},u=t.optional(r)+e.IDENT_RE+"\\s*\\(",_=["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],p={
23type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],
24keyword:_,literal:["NULL","false","nullopt","nullptr","true"],
25built_in:["_Pragma"],
26_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","flat_map","flat_set","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]
27},m={className:"function.dispatch",relevance:0,keywords:{
28_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]
29},
30begin:t.concat(/\b/,`(?!${_.join("|")})`,e.IDENT_RE,t.lookahead(/(<[^<>]+>|)\s*\(/))
31},f=[m,...l,s,a,e.C_BLOCK_COMMENT_MODE,o,c],g={variants:[{begin:/=/,end:/;/},{
32begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],
33keywords:p,contains:f.concat([{begin:/\(/,end:/\)/,keywords:p,
34contains:f.concat(["self"]),relevance:0}]),relevance:0},b={className:"function",
35begin:"("+i+"[\\*&\\s]+){1,12}"+u,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,
36keywords:p,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:n,keywords:p,relevance:0},{
37begin:u,returnBegin:!0,contains:[d],relevance:0},{begin:/::/,relevance:0},{
38begin:/:/,endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{
39className:"params",begin:/\(/,end:/\)/,keywords:p,relevance:0,
40contains:[a,e.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p,
41relevance:0,contains:["self",a,e.C_BLOCK_COMMENT_MODE,c,o,s]}]
42},s,a,e.C_BLOCK_COMMENT_MODE,...l]};return{name:"C++",
43aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"</",
44classNameAliases:{"function.dispatch":"built_in"},
45contains:[].concat(g,b,m,f,[...l,{
46begin:"\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array|tuple|optional|variant|function|flat_map|flat_set)\\s*<(?!<)",
47end:">",keywords:p,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:p},{
48match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],
49className:{1:"keyword",3:"title.class"}}])}}})();export default hljsGrammar;hooks/vendor/hljs/languages/csharp.js 49 lines1/*! `csharp` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict";return e=>{const n={
3keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","scoped","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","args","async","await","by","descending","dynamic","equals","file","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","record","remove","required","scoped","select","set","unmanaged","value|0","var","when","where","with","yield"]),
4built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"],
5literal:["default","false","null","true"]},a=e.inherit(e.TITLE_MODE,{
6begin:"[a-zA-Z](\\.?\\w)*"}),i="\\d(_*\\d)*",s="([uU][lL]?|[lL][uU]?)?",r={
7className:"number",variants:[{begin:"\\b0[bB]_*[01](_*[01])*"+s},{
8begin:"(-?)\\b0[xX]_*[a-fA-F0-9](_*[a-fA-F0-9])*"+s},{
9begin:"(-?)(\\b"+i+"(\\.("+i+")?)?|\\."+i+")([eE][-+]?"+i+")?([fFdDmM]|[uU][lL]?|[lL][uU]?)?"
10}],relevance:0},t={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]
11},l=e.inherit(t,{illegal:/\n/}),c={className:"subst",begin:/\{/,end:/\}/,
12keywords:n},o=e.inherit(c,{illegal:/\n/}),d={className:"string",begin:/\$"/,
13end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/
14},e.BACKSLASH_ESCAPE,o]},g={className:"string",begin:/\$@"/,end:'"',contains:[{
15begin:/\{\{/},{begin:/\}\}/},{begin:'""'},c]},_=e.inherit(g,{illegal:/\n/,
16contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},o]})
17;c.contains=[g,d,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,r,e.C_BLOCK_COMMENT_MODE],
18o.contains=[_,d,l,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,r,e.inherit(e.C_BLOCK_COMMENT_MODE,{
19illegal:/\n/})];const E={variants:[{className:"string",
20begin:/"""("*)(?!")(.|\n)*?"""\1/,relevance:1
21},g,d,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},b={begin:"<",end:">",
22contains:[{beginKeywords:"in out"},a]
23},u=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",M={
24begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],
25keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,
26contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{
27begin:"\x3c!--|--\x3e"},{begin:"</?",end:">"}]}]
28}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",
29end:"$",keywords:{
30keyword:"if else elif endif define undef warning error line region endregion pragma checksum"
31}},E,r,{beginKeywords:"class interface",relevance:0,end:/[{;=]/,
32illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"
33},a,b,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",
34relevance:0,end:/[{;=]/,illegal:/[^\s:]/,
35contains:[a,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
36beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,
37contains:[a,b,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",
38begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{
39className:"string",begin:/"/,end:/"/}]},{
40beginKeywords:"new return throw await else",relevance:0},{className:"function",
41begin:"("+u+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,
42end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{
43beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial",
44relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,
45contains:[e.TITLE_MODE,b],relevance:0},{match:/\(\)/},{className:"params",
46begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,
47contains:[E,r,e.C_BLOCK_COMMENT_MODE]
48},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},M]}}})()
49;export default hljsGrammar;hooks/vendor/hljs/languages/css.js 33 lines1/*! `css` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict"
3;const e=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","optgroup","option","p","picture","q","quote","samp","section","select","source","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video","defs","g","marker","mask","pattern","svg","switch","symbol","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feFlood","feGaussianBlur","feImage","feMerge","feMorphology","feOffset","feSpecularLighting","feTile","feTurbulence","linearGradient","radialGradient","stop","circle","ellipse","image","line","path","polygon","polyline","rect","text","use","textPath","tspan","foreignObject","clipPath"],t=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"].sort().reverse(),i=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"].sort().reverse(),o=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"].sort().reverse(),r=["accent-color","align-content","align-items","align-self","alignment-baseline","all","anchor-name","animation","animation-composition","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-range","animation-range-end","animation-range-start","animation-timeline","animation-timing-function","appearance","aspect-ratio","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-end-end-radius","border-end-start-radius","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-start-end-radius","border-start-start-radius","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-align","box-decoration-break","box-direction","box-flex","box-flex-group","box-lines","box-ordinal-group","box-orient","box-pack","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","color-scheme","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","contain-intrinsic-block-size","contain-intrinsic-height","contain-intrinsic-inline-size","contain-intrinsic-size","contain-intrinsic-width","container","container-name","container-type","content","content-visibility","corner-bottom-left-shape","corner-bottom-right-shape","corner-shape","corner-top-left-shape","corner-top-right-shape","counter-increment","counter-reset","counter-set","cue","cue-after","cue-before","cursor","cx","cy","direction","display","dominant-baseline","empty-cells","enable-background","field-sizing","fill","fill-opacity","fill-rule","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flood-color","flood-opacity","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-palette","font-size","font-size-adjust","font-smooth","font-smoothing","font-stretch","font-style","font-synthesis","font-synthesis-position","font-synthesis-small-caps","font-synthesis-style","font-synthesis-weight","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-emoji","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","forced-color-adjust","gap","glyph-orientation-horizontal","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphenate-character","hyphenate-limit-chars","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","initial-letter","initial-letter-align","inline-size","inset","inset-area","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","kerning","left","letter-spacing","lighting-color","line-break","line-height","line-height-step","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","margin-trim","marker","marker-end","marker-mid","marker-start","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","masonry-auto-flow","math-depth","math-shift","math-style","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-anchor","overflow-block","overflow-clip-margin","overflow-inline","overflow-wrap","overflow-x","overflow-y","overlay","overscroll-behavior","overscroll-behavior-block","overscroll-behavior-inline","overscroll-behavior-x","overscroll-behavior-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","paint-order","pause","pause-after","pause-before","perspective","perspective-origin","place-content","place-items","place-self","pointer-events","position","position-anchor","position-visibility","print-color-adjust","quotes","r","resize","rest","rest-after","rest-before","right","rotate","row-gap","ruby-align","ruby-position","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scroll-timeline","scroll-timeline-axis","scroll-timeline-name","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","shape-rendering","speak","speak-as","src","stop-color","stop-opacity","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","tab-size","table-layout","text-align","text-align-all","text-align-last","text-anchor","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-decoration-thickness","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-size-adjust","text-transform","text-underline-offset","text-underline-position","text-wrap","text-wrap-mode","text-wrap-style","timeline-scope","top","touch-action","transform","transform-box","transform-origin","transform-style","transition","transition-behavior","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","unicode-range","user-modify","user-select","vector-effect","vertical-align","view-timeline","view-timeline-axis","view-timeline-inset","view-timeline-name","view-transition-name","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","white-space-collapse","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","x","y","z-index","zoom"].sort().reverse()
4;return n=>{const a=n.regex,l=(e=>({IMPORTANT:{scope:"meta",begin:"!important"},
5BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",
6begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},UNICODE_RANGE:{
7scope:"number",
8begin:/\b[Uu]\+[0-9A-Fa-f][0-9A-Fa-f?]{0,5}(-[0-9A-Fa-f][0-9A-Fa-f]{0,5})?/},
9FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},
10ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",
11contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{
12scope:"number",
13begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",
14relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z_][A-Za-z0-9_-]*/}
15}))(n),s=[n.APOS_STRING_MODE,n.QUOTE_STRING_MODE];return{name:"CSS",
16case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"},
17classNameAliases:{keyframePosition:"selector-tag"},contains:[l.BLOCK_COMMENT,{
18begin:/-(webkit|moz|ms|o)-(?=[a-z])/},l.CSS_NUMBER_MODE,{
19className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{
20className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0
21},l.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{
22begin:":("+i.join("|")+")"},{begin:":(:)?("+o.join("|")+")"}]},l.CSS_VARIABLE,{
23className:"attribute",begin:"\\b("+r.join("|")+")\\b"},{begin:/:/,end:/[;}{]/,
24contains:[l.BLOCK_COMMENT,l.HEXCOLOR,l.IMPORTANT,l.CSS_NUMBER_MODE,l.UNICODE_RANGE,...s,{
25begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri"
26},contains:[...s,{className:"string",begin:/[^)]/,endsWithParent:!0,
27excludeEnd:!0}]},l.FUNCTION_DISPATCH]},{begin:a.lookahead(/@/),end:"[{;]",
28relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/
29},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{
30$pattern:/[a-z-]+/,keyword:"and or not only",attribute:t.join(" ")},contains:[{
31begin:/[a-z-]+(?=:)/,className:"attribute"},...s,l.CSS_NUMBER_MODE]}]},{
32className:"selector-tag",begin:"\\b("+e.join("|")+")\\b"}]}}})()
33;export default hljsGrammar;hooks/vendor/hljs/languages/diff.js 9 lines1/*! `diff` grammar compiled for Highlight.js 11.12.0 */
2var hljsGrammar=(()=>{"use strict";return e=>{const a=e.regex;return{
3name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,
4match:a.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^@@ +-\d+ +\+\d+,\d+ +@@/,/^@@ +-\d+,\d+ +\+\d+ +@@/,/^@@ +-\d+ +\+\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)
5},{className:"comment",variants:[{
6begin:a.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),
7end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{
8className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,
9end:/$/}]}}})();export default hljsGrammar;