Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/content/4.plugins/1.built-in/rangi.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ npm install rangi
Use [`comark/plugins/shiki`](/plugins/built-in/shiki) when you need transformers, Twoslash, or the full VS Code grammar set. Use `rangi` for a faster, smaller highlighter with built-in light/dark themes.
::

Inline code highlighting with `{lang="…"}` is currently shiki only. Rangi highlights fenced blocks.

## Usage

```typescript
Expand Down
77 changes: 77 additions & 0 deletions docs/content/4.plugins/1.built-in/shiki.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,49 @@ const x: number = 42
```
````

### Inline code

Inline code is highlighted when it declares a language with the attributes syntax. `lang` wins over `language`:

```markdown
The type is `Ref<HTMLInputElement | null>`{lang="ts-type"} and the component is `<UButton />`{lang="vue-html"}.
```

Inline code uses the fast token path only, so `transformers` and `preStyles` are block-only and are not applied. The node gets the same `shiki` class a `<pre>` gets, so the dual-theme CSS in [Styling](#styling) covers it without extra rules.

Inline code naming a grammar that is not registered is left exactly as it was written, with no class and no spans. That is deliberate: `lang` is a real HTML attribute for natural language, so `` `Bonjour`{lang="fr"} `` must not be treated as code. A fenced block behaves differently and still falls back to an unhighlighted `.shiki` block, because a `<pre>` is unambiguously code.

Plain-text language names follow the same rule: `` `x`{lang="text"} ``, `txt` and `plain` are not registered grammars, so inline code naming one is left alone. The same name on a fence still produces a `.shiki` block.

Set `inlineCode: false` to turn this off.

### Grammar contexts

Some inline snippets are fragments rather than whole statements, so the grammar needs seeding before it tokenizes them correctly. A grammar context maps a name you write in `{lang="…"}` onto a real grammar plus source that is tokenized and then discarded.

Two ship by default, mirroring the `@nuxtjs/mdc` conventions:

| Name | Grammar | Seed |
|---|---|---|
| `ts-type` | `typescript` | `let a:` |
| `vue-html` | `vue` | `<template>` |

Without the `ts-type` seed, `Ref<HTMLInputElement | null>` tokenizes as an expression and the type names fall through to plain text.

Add your own with `grammarContexts`:

```ts
shiki({
grammarContexts: {
'sql-expr': { lang: 'sql', grammarContextCode: 'select ' },
},
})
```

A registered grammar always wins. Shiki ships a real `vue-html` grammar, so registering it through `languages` gets you that grammar rather than the built-in context that seeds `vue`.

Contexts apply to fence info strings too. The written name stays on the `<pre>`, so ```` ```ts-type ```` still round-trips. On the `core` entry the target grammar has to be registered through `languages` like any other.

### Line highlighting

Highlight specific lines using `{line-numbers}` syntax:
Expand Down Expand Up @@ -304,6 +347,8 @@ Two option types, one per entry:
| [`languages`](#options-languages) | `Array<LanguageRegistration \| LanguageRegistration[]>` | `undefined` | Extra languages (merged onto the default set) |
| [`transformers`](#options-transformers) | `ShikiTransformer[]` | `undefined` | Shiki transformers applied to every block |
| [`preStyles`](#options-prestyles) | `boolean` | `false` | Add inline background/foreground styles to `<pre>` |
| [`inlineCode`](#options-inlinecode) | `boolean` | `true` | Highlight inline code that declares a language |
| [`grammarContexts`](#options-grammarcontexts) | `Record<string, ShikiGrammarContext>` | Built-ins | Pseudo-languages merged over `ts-type` and `vue-html` |
| [`registerDefaultLanguages`](#options-registerdefaultlanguages) | `boolean` | `true` | Register the built-in default language set |
| [`registerDefaultThemes`](#options-registerdefaultthemes) | `boolean` | `true` | Register the built-in Material themes |

Expand All @@ -315,6 +360,8 @@ Two option types, one per entry:
| `languages` | `Array<LanguageRegistration \| LanguageRegistration[]>` | **required** | Languages to register |
| `transformers` | `ShikiTransformer[]` | `undefined` | Shiki transformers applied to every block |
| `preStyles` | `boolean` | `false` | Add inline background/foreground styles to `<pre>` |
| `inlineCode` | `boolean` | `true` | Highlight inline code that declares a language |
| `grammarContexts` | `Record<string, ShikiGrammarContext>` | Built-ins | Pseudo-languages merged over `ts-type` and `vue-html` |

### `themes`

Expand Down Expand Up @@ -384,6 +431,34 @@ shiki({ preStyles: true })

**Default:** `false`

Block-only. Inline code never receives inline styles, so a user-authored `` `x`{style="…"} `` survives the round-trip.

### `inlineCode`

Whether to highlight inline code that declares a language, e.g. `` `Ref<T>`{lang="ts-type"} ``. See [Inline code](#inline-code).

```typescript
shiki({ inlineCode: false })
```

**Default:** `true`

### `grammarContexts`

Pseudo-languages usable in `{lang="…"}` and in fence info strings, merged on top of the built-in `ts-type` and `vue-html`. See [Grammar contexts](#grammar-contexts).

```typescript
shiki({
grammarContexts: {
'sql-expr': { lang: 'sql', grammarContextCode: 'select ' },
},
})
```

Each entry is `{ lang, grammarContextCode? }`. A name that is already a registered grammar is never routed through a context.

**Default:** the built-in contexts

### `registerDefaultLanguages`

Standard entry only. When `true`, these languages are pre-registered: `vue`, `tsx`, `svelte`, `astro`, `typescript`, `javascript`, `bash`, `json`, `yaml` (plus the built-in Comark/`mdc` grammar). Set to `false` to control the language set entirely via `languages`.
Expand Down Expand Up @@ -488,6 +563,8 @@ Browser-side twoslash with CDN-fetched TypeScript types and interactive type pop

Shiki outputs tokens as `<span class="line">` elements inside a `<pre class="shiki">` block.

Highlighted inline code gets the same `shiki` class on the `<code>` element, with the token spans directly inside it and no `.line` wrapper. Rules written against `.shiki span` therefore cover both. Use `pre.shiki` when a rule should apply to blocks only.

### Line highlight

Lines set with `{1,3-5}` syntax receive the `.highlight` class:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ const variable = "value"
{
"language": "ts",
"attr": "value",
"class": "shiki shiki-themes min-light nord dark:nord . class",
"class": "shiki shiki-themes min-light nord dark:nord class",
"$": {
"class": "class"
},
"style": "background-color:#ffffff;color:#212121;--shiki-dark-bg:#2e3440;--shiki-dark:#d8dee9"
},
[
Expand Down Expand Up @@ -95,7 +98,7 @@ const variable = "value"
## HTML

```html
<pre language="ts" attr="value" class="shiki shiki-themes min-light nord dark:nord . class" style="background-color:#ffffff;color:#212121;--shiki-dark-bg:#2e3440;--shiki-dark:#d8dee9"><code class="language-ts"><span class="line" style="display: inline"><span style="color:#D32F2F;--shiki-dark:#81A1C1">const</span><span style="color:#1976D2;--shiki-dark:#D8DEE9"> variable</span><span style="color:#D32F2F;--shiki-dark:#81A1C1"> =</span><span style="color:#22863A;--shiki-dark:#ECEFF4"> "</span><span style="color:#22863A;--shiki-dark:#A3BE8C">value</span><span style="color:#22863A;--shiki-dark:#ECEFF4">"</span></span></code></pre>
<pre language="ts" attr="value" class="shiki shiki-themes min-light nord dark:nord class" style="background-color:#ffffff;color:#212121;--shiki-dark-bg:#2e3440;--shiki-dark:#d8dee9"><code class="language-ts"><span class="line" style="display: inline"><span style="color:#D32F2F;--shiki-dark:#81A1C1">const</span><span style="color:#1976D2;--shiki-dark:#D8DEE9"> variable</span><span style="color:#D32F2F;--shiki-dark:#81A1C1"> =</span><span style="color:#22863A;--shiki-dark:#ECEFF4"> "</span><span style="color:#22863A;--shiki-dark:#A3BE8C">value</span><span style="color:#22863A;--shiki-dark:#ECEFF4">"</span></span></code></pre>
```

## Markdown
Expand Down
3 changes: 3 additions & 0 deletions packages/comark/SPEC/COMARK/shiki-codeblock-dual-theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ console.log(greeting)
{
"language": "typescript",
"class": "shiki shiki-themes min-light nord dark:nord",
"$": {
"class": ""
},
"style": "background-color:#ffffff;color:#212121;--shiki-dark-bg:#2e3440;--shiki-dark:#d8dee9"
},
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ func main() {
10
],
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ console.log(greeting)
],
"meta": "some meta",
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ console.log(greeting)
"pre",
{
"language": "typescript",
"class": "shiki shiki-themes github-dark dark:github-dark"
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
}
},
[
"code",
Expand Down
3 changes: 3 additions & 0 deletions packages/comark/SPEC/COMARK/shiki-codeblock-no-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ No language specified
"pre",
{
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
3 changes: 3 additions & 0 deletions packages/comark/SPEC/COMARK/shiki-codeblock-rust-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ fn main() {
4
],
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ options:
"language": "html",
"filename": "template.html",
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
5 changes: 4 additions & 1 deletion packages/comark/SPEC/COMARK/shiki-codeblock-twoslash.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const message = "Hello from twoslash"
{
"language": "ts",
"meta": "twoslash",
"class": "shiki shiki-themes min-light twoslash lsp dark:min-light"
"class": "shiki shiki-themes min-light twoslash lsp dark:min-light",
"$": {
"class": ""
}
},
[
"code",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ More content here.
"language": "markdown",
"filename": "content.md",
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
},
"style": "background-color:#24292e;color:#e1e4e8"
},
[
Expand Down
129 changes: 129 additions & 0 deletions packages/comark/SPEC/COMARK/shiki-inline-code-lang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
timeout:
parse: 500ms
html: 5ms
markdown: 5ms
options:
highlight:
themes:
light: 'github-dark'
---

## Input

```md
Use `Ref<HTMLInputElement | null>`{lang="ts-type"} with `<UButton />`{lang="vue-html"}.
```

## AST

```json
{
"frontmatter": {},
"meta": {},
"nodes": [
[
"p",
{},
"Use ",
[
"code",
{
"lang": "ts-type",
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
}
},
[
"span",
{
"style": "color:#B392F0"
},
"Ref"
],
[
"span",
{
"style": "color:#E1E4E8"
},
"<"
],
[
"span",
{
"style": "color:#B392F0"
},
"HTMLInputElement"
],
[
"span",
{
"style": "color:#F97583"
},
" |"
],
[
"span",
{
"style": "color:#79B8FF"
},
" null"
],
[
"span",
{
"style": "color:#E1E4E8"
},
">"
]
],
" with ",
[
"code",
{
"lang": "vue-html",
"class": "shiki shiki-themes github-dark dark:github-dark",
"$": {
"class": ""
}
},
[
"span",
{
"style": "color:#E1E4E8"
},
"<"
],
[
"span",
{
"style": "color:#85E89D"
},
"UButton"
],
[
"span",
{
"style": "color:#E1E4E8"
},
" />"
]
],
"."
]
]
}
```

## HTML

```html
<p>Use <code lang="ts-type" class="shiki shiki-themes github-dark dark:github-dark"><span style="color:#B392F0">Ref</span><span style="color:#E1E4E8">&lt;</span><span style="color:#B392F0">HTMLInputElement</span><span style="color:#F97583"> |</span><span style="color:#79B8FF"> null</span><span style="color:#E1E4E8">&gt;</span></code> with <code lang="vue-html" class="shiki shiki-themes github-dark dark:github-dark"><span style="color:#E1E4E8">&lt;</span><span style="color:#85E89D">UButton</span><span style="color:#E1E4E8"> /&gt;</span></code>.</p>
```

## Markdown

```md
Use `Ref<HTMLInputElement | null>`{lang="ts-type"} with `<UButton />`{lang="vue-html"}.
```
Loading
Loading