Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
76 changes: 76 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,46 @@ 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.

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`, or set an entry to `false` to drop a built-in and treat the name as a plain grammar name:

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

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 +344,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 \| false>` | 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 +357,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 \| false>` | Built-ins | Pseudo-languages merged over `ts-type` and `vue-html` |

### `themes`

Expand Down Expand Up @@ -384,6 +428,36 @@ 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
import shiki, { defaultGrammarContexts } from 'comark/plugins/shiki'

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

Each entry is `{ lang, grammarContextCode? }`, or `false` to drop a built-in. `defaultGrammarContexts` is exported so you can see what you are extending.

**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 +562,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 @@ -95,7 +95,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
123 changes: 123 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,123 @@
---
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"
},
[
"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"
},
[
"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"}.
```
88 changes: 88 additions & 0 deletions packages/comark/SPEC/COMARK/shiki-inline-code-plain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
timeout:
parse: 500ms
html: 5ms
markdown: 5ms
options:
highlight:
themes:
light: 'github-dark'
---

## Input

```md
A `Bonjour`{lang="fr"} and a `const a = 1`{lang="ts"}.
```

## AST

```json
{
"frontmatter": {},
"meta": {},
"nodes": [
[
"p",
{},
"A ",
[
"code",
{
"lang": "fr"
},
"Bonjour"
],
" and a ",
[
"code",
{
"lang": "ts",
"class": "shiki shiki-themes github-dark dark:github-dark"
},
[
"span",
{
"style": "color:#F97583"
},
"const"
],
[
"span",
{
"style": "color:#79B8FF"
},
" a"
],
[
"span",
{
"style": "color:#F97583"
},
" ="
],
[
"span",
{
"style": "color:#79B8FF"
},
" 1"
]
],
"."
]
]
}
```

## HTML

```html
<p>A <code lang="fr">Bonjour</code> and a <code lang="ts" class="shiki shiki-themes github-dark dark:github-dark"><span style="color:#F97583">const</span><span style="color:#79B8FF"> a</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 1</span></code>.</p>
```

## Markdown

```md
A `Bonjour`{lang="fr"} and a `const a = 1`{lang="ts"}.
```
Loading
Loading