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
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
filters: |
core:
- 'packages/core/**'
- 'vendor/grammar-versions.json'
- 'package.json'
- '.github/**'
react-native:
Expand Down Expand Up @@ -133,6 +134,10 @@ jobs:
if: matrix.build_type == 'RelWithDebInfo'
run: yarn workspace @enriched-markdown/core lint-clang

# The highlight tests need the gitignored tree-sitter runtime and grammars.
- name: Vendor tree-sitter grammars
run: yarn workspace react-native-enriched-markdown vendor-grammars

- name: Build and run C++ core tests (${{ matrix.build_type }}${{ matrix.sanitize && ', sanitized' || '' }})
env:
CORE_CMAKE_ARGS: -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCORE_SANITIZE=${{ matrix.sanitize }}
Expand Down
17 changes: 13 additions & 4 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@ nmHoistingLimits: workspaces
yarnPath: .yarn/releases/yarn-4.11.0.cjs

# The tree-sitter grammars are vendored from source (see vendor/vendor-grammars.mjs);
# we never load their compiled Node bindings. @tree-sitter-grammars/tree-sitter-markdown
# and tree-sitter-swift ship a typo'd peerDependenciesMeta key ("tree_sitter" instead of
# "tree-sitter"), so Yarn treats their optional "tree-sitter" peer as required and warns.
# Re-declare it optional. (Their native builds are disabled via dependenciesMeta in package.json.)
# we never load their compiled Node bindings. @tree-sitter-grammars/tree-sitter-markdown,
# tree-sitter-swift, tree-sitter-kotlin and @derekstride/tree-sitter-sql ship a typo'd
# peerDependenciesMeta key ("tree_sitter" instead of "tree-sitter"), so Yarn treats their
# optional "tree-sitter" peer as required and warns. Re-declare it optional. (Their
# native builds are disabled via dependenciesMeta in package.json.)
packageExtensions:
'@tree-sitter-grammars/tree-sitter-markdown@*':
peerDependenciesMeta:
tree-sitter:
optional: true
'@derekstride/tree-sitter-sql@*':
peerDependenciesMeta:
tree-sitter:
optional: true
'tree-sitter-kotlin@*':
peerDependenciesMeta:
tree-sitter:
optional: true
'tree-sitter-swift@*':
peerDependenciesMeta:
tree-sitter:
Expand Down
2 changes: 1 addition & 1 deletion apps/react-native-example/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ edgeToEdgeEnabled=false
# Set to false to disable LaTeX math rendering and remove the RaTeX dependency.
#enrichedMarkdown.enableMath=false

enrichedMarkdown.codeHighlightLanguages=json,html,css,markdown,yaml,go,java,javascript,python,c,rust,bash,typescript,tsx,cpp,swift,php,ruby,c-sharp
enrichedMarkdown.codeHighlightLanguages=json,html,css,markdown,yaml,go,java,javascript,python,c,rust,bash,typescript,tsx,cpp,swift,kotlin,dart,sql,php,ruby,c-sharp

# Opt out of built-in kotlin and new DSL behavior that ships with AGP 9.
# Starting from AGP 10.x these opt outs will be removed.
Expand Down
2 changes: 1 addition & 1 deletion apps/react-native-example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ENV['RCT_NEW_ARCH_ENABLED'] = '1'
# ENV['ENRICHED_MARKDOWN_ENABLE_MATH'] = '0'

# Keep project default to full list of languages
ENV['ENRICHED_MARKDOWN_CODE_HIGHLIGHT_LANGUAGES'] = 'json,html,css,markdown,yaml,go,java,javascript,python,c,rust,bash,typescript,tsx,cpp,swift,php,ruby,c-sharp'
ENV['ENRICHED_MARKDOWN_CODE_HIGHLIGHT_LANGUAGES'] = 'json,html,css,markdown,yaml,go,java,javascript,python,c,rust,bash,typescript,tsx,cpp,swift,kotlin,dart,sql,php,ruby,c-sharp'
# ENV['ENRICHED_MARKDOWN_ENABLE_CODE_HIGHLIGHT'] = '0'

# Resolve react_native_pods.rb with node to allow for hoisting
Expand Down
12 changes: 8 additions & 4 deletions docs-md/CODE_HIGHLIGHT.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ def greet(name: str) -> str:
comment: '#7F848E',
function: '#61AFEF',
type: '#E5C07B',
// ...any of the 14 token types
// ...any of the 16 token types
},
},
}}
/>
````

Token colors are set through `codeBlock.syntaxColors`. The 14 token types are: `keyword`,
Token colors are set through `codeBlock.syntaxColors`. The 16 token types are: `keyword`,
`operator`, `punctuation`, `string`, `number`, `constant`, `comment`, `function`, `type`,
`variable`, `property`, `tag`, `attribute`, `embedded`. Any type left unset uses the built-in
`variable`, `property`, `tag`, `attribute`, `embedded`, `inserted`, `deleted`. Any type left unset uses the built-in
(GitHub-dark) palette; `operator`, `punctuation`, `variable` and `embedded` default to the code
block's `color`.

Expand All @@ -63,12 +63,16 @@ derive from), so the table below tracks that manifest:

| Default (on) | Opt-in (heavier) |
|---|---|
| json, html, css, markdown, yaml, go, java, javascript, python, c, rust, bash, typescript, tsx | cpp, swift, php, ruby, c-sharp |
| json, html, css, markdown, yaml, go, java, javascript, python, c, rust, bash, typescript, tsx | cpp, swift, kotlin, dart, sql, php, ruby, c-sharp |

Grammar sources are large (generated parsers run to several MB each); the opt-in grammars include
the largest ones and are only compiled when you list them explicitly.
A block whose language is not compiled in simply renders as plain (uncolored) code.

`diff` and `patch` blocks are highlighted without a grammar whenever highlighting is compiled in:
added and removed lines take the `inserted` and `deleted` colors, hunk ranges the `function` color
and file headers the `constant` color.

## Choosing languages / reducing binary size

Only the grammars you compile end up in your binary, so trimming the list is the main size lever.
Expand Down
2 changes: 2 additions & 0 deletions docs-md/STYLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ Per-token foreground colors for syntax highlighting, keyed on the highlight toke
| `tag` | `string` | Markup tags |
| `attribute` | `string` | Markup attributes |
| `embedded` | `string` | Embedded/injected language regions |
| `inserted` | `string` | Added lines in a `diff` block |
| `deleted` | `string` | Removed lines in a `diff` block |

> [!NOTE]
> Inside list items, code blocks (background included) indent to the item's content column.
Expand Down
6 changes: 4 additions & 2 deletions docs/docs/android/guides/code-highlighting.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Tokens are cached in memory, keyed by the language and the code, in one process-

## Colors {#styling}

Each of the 14 token types takes its color from the first of:
Each of the 16 token types takes its color from the first of:

1. a color you set;
2. GitHub's dark palette, made for the default dark code block (`#1F2937`);
Expand All @@ -150,6 +150,8 @@ Each of the 14 token types takes its color from the first of:
| `function` | `#D2A8FF` |
| `type` | `#FFA657` |
| `tag` | `#7EE787` |
| `inserted` | `#3FB950` |
| `deleted` | `#F85149` |
| `operator`, `punctuation`, `variable`, `embedded` | `codeBlock` color |

:::caution
Expand All @@ -176,7 +178,7 @@ val oneDarkStyle = markdownStyle {
}
```

The properties are `keyword`, `operator`, `punctuation`, `string`, `number`, `constant`, `comment`, `function`, `type`, `variable`, `property`, `tag`, `attribute`, and `embedded`, each a `Color?`. A token you leave unset keeps its palette color. To pick the token at runtime, index the scope with a `SyntaxTokenType` (from `com.swmansion.enriched.markdown.codehighlight`): `this[SyntaxTokenType.KEYWORD] = color`.
The properties are `keyword`, `operator`, `punctuation`, `string`, `number`, `constant`, `comment`, `function`, `type`, `variable`, `property`, `tag`, `attribute`, `embedded`, `inserted`, and `deleted`, each a `Color?`. A token you leave unset keeps its palette color. To pick the token at runtime, index the scope with a `SyntaxTokenType` (from `com.swmansion.enriched.markdown.codehighlight`): `this[SyntaxTokenType.KEYWORD] = color`.

Repeating the block merges into the earlier one, exactly like the built-in blocks, so `MarkdownStyle.merge { codeHighlight { … } }` layers over a base style and changes only what it names.

Expand Down
4 changes: 3 additions & 1 deletion docs/docs/ios/api-reference/style-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ struct CodeSampleView: View {
}
```

`SyntaxTokenType` has fourteen cases: `.keyword`, `.operator`, `.punctuation`, `.string`, `.number`, `.constant`, `.comment`, `.function`, `.type`, `.variable`, `.property`, `.tag`, `.attribute`, and `.embedded`.
`SyntaxTokenType` has sixteen cases: `.keyword`, `.operator`, `.punctuation`, `.string`, `.number`, `.constant`, `.comment`, `.function`, `.type`, `.variable`, `.property`, `.tag`, `.attribute`, `.embedded`, `.inserted`, and `.deleted`.

Turning highlighting on layers `MarkdownTheme.syntaxHighlightingDefault` - GitHub's palette - above `MarkdownTheme.default` and below your own themes, so a `SyntaxToken` you set overrides one type and leaves the rest. The palette switches between light and dark with the color scheme:

Expand All @@ -685,6 +685,8 @@ Turning highlighting on layers `MarkdownTheme.syntaxHighlightingDefault` - GitHu
| `.function` | `#8250DF` | `#D2A8FF` |
| `.type` | `#953800` | `#FFA657` |
| `.tag` | `#116329` | `#7EE787` |
| `.inserted` | `#1A7F37` | `#3FB950` |
| `.deleted` | `#D1242F` | `#F85149` |

`.operator`, `.punctuation`, `.variable`, and `.embedded` have no default color, so they keep the code block's color until you give them one.

Expand Down
1 change: 1 addition & 0 deletions docs/docs/ios/guides/syntax-highlighting.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ Each run is classified as one of the `SyntaxTokenType` cases:
public enum SyntaxTokenType: UInt8, CaseIterable, Sendable {
case keyword, `operator`, punctuation, string, number, constant, comment
case function, type, variable, property, tag, attribute, embedded
case inserted, deleted
}
```

Expand Down
2 changes: 2 additions & 0 deletions docs/docs/react-native/api-reference/style-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ To learn more about how code highlighting works, see the [Code highlighting](/ri
| `tag` | `#7EE787` | Markup tags (e.g. HTML or JSX element names) |
| `attribute` | `#79C0FF` | Markup attributes |
| `embedded` | Base `color` | Embedded content such as interpolations. Inherits the base `color` when omitted |
| `inserted` | `#3FB950` | Added lines in a `diff` block |
| `deleted` | `#F85149` | Removed lines in a `diff` block |

:::note
Syntax colors only take visible effect when the optional syntax-highlighting module is compiled in; otherwise code blocks render uncolored. The module is native-only, so `syntaxColors` has no effect on the web build.
Expand Down
11 changes: 7 additions & 4 deletions docs/docs/rich-text-formatting/code-highlighting.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ In the React Native package, set token colors through the `syntaxColors` map on

<LivePreview src={SyntaxColorsSrc} unavailable unavailableReason={<>iOS and Android only - the web build renders code blocks uncolored, so <code>syntaxColors</code> has no visible effect here.</>} />

There are 14 token types, any of which you can color. Most of them ship with a color of their own, from a GitHub-dark palette tuned for the default `#1F2937` code background:
There are 16 token types, any of which you can color. Most of them ship with a color of their own, from a GitHub-dark palette tuned for the default `#1F2937` code background:

| Token | Default |
| --- | --- |
Expand All @@ -43,21 +43,24 @@ There are 14 token types, any of which you can color. Most of them ship with a c
| `function` | `#D2A8FF` |
| `type` | `#FFA657` |
| `tag` | `#7EE787` |
| `inserted`, `deleted` | `#3FB950`, `#F85149` |
| `operator`, `punctuation`, `variable`, `embedded` | inherit `codeBlock.color` |

Only those last four fall back to the normal code color when left unset; the other ten keep their palette default until you override them.
Only those last four fall back to the normal code color when left unset; the other twelve keep their palette default until you override them.

## Supported languages

A fence's info string maps to a grammar (for example `js` and `jsx` both select JavaScript). In the React Native package a curated default set is compiled in unless you override it; a block whose language is not compiled simply renders as plain, uncolored code.

| Default (compiled in) | Opt-in (add explicitly) |
|---|---|
| json, html, css, markdown, yaml, go, java, javascript, python, c, rust, bash, typescript, tsx | cpp, swift, php, ruby, c-sharp |
| json, html, css, markdown, yaml, go, java, javascript, python, c, rust, bash, typescript, tsx | cpp, swift, kotlin, dart, sql, php, ruby, c-sharp |

The default set is the smaller-footprint tier; the opt-in grammars are heavier and only compiled when you list them explicitly.

Several fence tags are aliases of the same grammar - `sh`, `shell` and `zsh` all select `bash`; `cc`, `cpp` and `cxx` select `cpp`; `cs` and `csharp` select `c-sharp`; and likewise `golang`, `js`/`jsx`, `md`, `py`, `rb`, `rs`, `ts`, `yml`. A handful of tags are recognized as **labels only** and never highlighted: `dockerfile`, `graphql`, `objc`, `objectivec`, `scss`, `sql`, `toml`, `xml`.
Several fence tags are aliases of the same grammar - `sh`, `shell` and `zsh` all select `bash`; `cc`, `cpp` and `cxx` select `cpp`; `cs` and `csharp` select `c-sharp`; `kt` and `kts` select `kotlin`; `mysql`, `postgres`, `postgresql`, `pgsql` and `sqlite` select `sql`; and likewise `golang`, `js`/`jsx`, `md`, `py`, `rb`, `rs`, `ts`, `yml`. A handful of tags are recognized as **labels only** and never highlighted: `dockerfile`, `graphql`, `objc`, `objectivec`, `scss`, `toml`, `xml`.

`diff` and `patch` blocks need no grammar: whenever highlighting is compiled in, added and removed lines take the `inserted` and `deleted` colors, hunk ranges (`@@ -1,2 +1,3 @@`) the `function` color, and file headers the `constant` color. Context lines keep the code color.

:::caution
The alias table and the `codeHighlightLanguages` ids are **not** the same list. `c-sharp` is the grammar id you must write in `codeHighlightLanguages`, but it is not a valid fence tag - in Markdown, write `cs` or `csharp`.
Expand Down
9 changes: 9 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
},
"packageManager": "yarn@4.11.0",
"dependenciesMeta": {
"@derekstride/tree-sitter-sql": {
"built": false
},
"@tree-sitter-grammars/tree-sitter-markdown": {
"built": false
},
Expand All @@ -105,6 +108,9 @@
"tree-sitter-css": {
"built": false
},
"tree-sitter-dart": {
"built": false
},
"tree-sitter-go": {
"built": false
},
Expand All @@ -120,6 +126,9 @@
"tree-sitter-json": {
"built": false
},
"tree-sitter-kotlin": {
"built": false
},
"tree-sitter-php": {
"built": false
},
Expand Down
Loading