Skip to content
Merged
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
8 changes: 2 additions & 6 deletions .envrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
source_url \
https://omnix.page/om/develop/omnixrc/v1 \
'sha256-FBAVRYkaexKeFKQGUxaPHqhBnqA7km7++O77dKiyD0I='
watch_file nix/modules/flake-parts/*.nix

watch_file nix/modules/flake-parts/*.nix om.yaml

use omnix .
use flake .
1 change: 0 additions & 1 deletion docs/guide/orgmode.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
page:
headHtml: |
<snippet var="js.highlightjs" />
<snippet var="js.mathjax" />
2 changes: 0 additions & 2 deletions docs/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,3 @@ template:
page:
siteUrl: https://emanote.srid.ca
siteTitle: Emanote
headHtml: |
<snippet var="js.highlightjs" />
6 changes: 0 additions & 6 deletions docs/start/resources/editors/vim.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
---
page:
headHtml: |
<snippet var="js.highlightjs" />
<with var="js">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${value:highlightjs-ver}/languages/vim.min.js"></script>
</with>
slug: vim
---

Expand Down
4 changes: 0 additions & 4 deletions docs/start/resources/zk.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
---
slug: zk
page:
headHtml: |
<snippet var="js.highlightjs" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/languages/ini.min.js"></script>
---

# zk
Expand Down
2 changes: 0 additions & 2 deletions docs/tips/js/math.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
slug: math
page:
headHtml: |
<snippet var="js.highlightjs" />
<snippet var="js.mathjax" />

---

# Math
Expand Down
2 changes: 0 additions & 2 deletions docs/tips/js/mermaid.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
---
slug: mermaid
page:
headHtml: |
<snippet var="js.highlightjs" />
bodyHtml: |
<snippet var="js.mermaid" />
---
Expand Down
65 changes: 0 additions & 65 deletions docs/tips/js/syntax-highlighting.md

This file was deleted.

77 changes: 77 additions & 0 deletions docs/tips/syntax-highlighting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
slug: syntax-highlighting
order: -1
---

# Syntax Highlighting

Emanote includes built-in syntax highlighting powered by [skylighting](https://github.com/jgm/skylighting), the same library used by Pandoc. Code blocks are highlighted at build time—no JavaScript required.

## How it Works

Code blocks are automatically tokenized during rendering. Each token gets a CSS class (like `kw` for keywords, `st` for strings, `co` for comments) and styled via CSS included in emanote's default theme.

### Example

```haskell
-- A simple factorial function
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
```

```python
def fibonacci(n):
"""Generate fibonacci sequence up to n"""
a, b = 0, 1
while a < n:
yield a
a, b = b, a + b
```

```nix
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
vim
git
];
}
```

## Supported Languages

Skylighting supports [over 140 languages](https://github.com/jgm/skylighting/tree/master/skylighting-core/xml) including:

- Haskell, Python, JavaScript, TypeScript, Rust, Go
- Nix, Shell/Bash, YAML, JSON, TOML
- HTML, CSS, SQL, Markdown
- And many more...

## Disabling Syntax Highlighting

To disable built-in syntax highlighting (for example, to use a client-side highlighter like highlight.js instead), set in your [[yaml-config|index.yaml]]:

```yaml
emanote:
syntaxHighlighting: false
```

## Customizing the Theme

The default theme is in `_emanote-static/skylighting.css`. To customize, create your own `_emanote-static/skylighting.css` in your notes directory to override the default.

Alternatively, add custom styles in your [[yaml-config|index.yaml]]:

```yaml
page:
headHtml: |
<style>
/* Override keyword color */
code span.kw { color: #ff79c6; font-weight: bold; }
/* Override string color */
code span.st { color: #f1fa8c; }
</style>
```

See the [skylighting documentation](https://hackage.haskell.org/package/skylighting-core/docs/Skylighting-Types.html#t:TokenType) for a full list of token classes and their meanings.
4 changes: 4 additions & 0 deletions emanote/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Revision history for emanote

## 1.5.4.0 (2025-12-18)

- Built-in static syntax highlighting using skylighting (replaces client-side JS highlighters)

## Unreleased

**Notable features**
Expand Down
90 changes: 90 additions & 0 deletions emanote/default/_emanote-static/skylighting.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* Skylighting syntax highlighting theme */
/* To override, create your own _emanote-static/skylighting.css */

/* Code block container styling */
pre {
background-color: #f8f8f8;
border: 1px solid #e1e4e8;
border-radius: 6px;
padding: 1rem;
overflow-x: auto;
}

pre code {
background: transparent;
border: none;
padding: 0;
}

/* Dark mode code block */
@media (prefers-color-scheme: dark) {
pre {
background-color: #1e1e1e;
border-color: #333;
}
}

/* Token colors */

code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.re { } /* RegionMarker */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */

/* Dark mode overrides */
@media (prefers-color-scheme: dark) {
code span.al { color: #ff6b6b; }
code span.an { color: #8ec8e8; }
code span.at { color: #a9c77d; }
code span.bn { color: #87ceab; }
code span.bu { color: #66cc99; }
code span.cf { color: #66cc99; }
code span.ch { color: #79a6d2; }
code span.cn { color: #e09090; }
code span.co { color: #8ec8e8; }
code span.cv { color: #8ec8e8; }
code span.do { color: #e08080; }
code span.dt { color: #e09090; }
code span.dv { color: #87ceab; }
code span.er { color: #ff6b6b; }
code span.fl { color: #87ceab; }
code span.fu { color: #79a6d2; }
code span.im { color: #66cc99; }
code span.in { color: #8ec8e8; }
code span.kw { color: #cc99cc; }
code span.op { color: #cccccc; }
code span.ot { color: #66cc99; }
code span.pp { color: #d7ba7d; }
code span.sc { color: #79a6d2; }
code span.ss { color: #cc99cc; }
code span.st { color: #79a6d2; }
code span.va { color: #9cdcfe; }
code span.vs { color: #79a6d2; }
code span.wa { color: #8ec8e8; }
}
24 changes: 4 additions & 20 deletions emanote/default/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,6 @@ page:
# Builtin JS behaviour library. Use them in `page.headHtml` of your .yaml or .md
# frontmatter.
js:
# Syntax highlighting using prism.js
prism: |
<!-- Prism.js (doesn't work great in live server) -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/themes/prism-tomorrow.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/plugins/autoloader/prism-autoloader.min.js"></script>
<style>code span.token.table{display:inline;}</style> <!-- Tailwind and Prism both use the .table class. This resets the display:table property set by Tailwind. https://github.com/srid/emanote/issues/320 -->
# Syntax highlighting using highlight.js
highlightjs: |
<!-- highlight.js -->
<with var="js">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${value:highlightjs-ver}/styles/hybrid.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${value:highlightjs-ver}/highlight.min.js"></script>
<!-- Include languages that Emanote itself uses -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${value:highlightjs-ver}/languages/haskell.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${value:highlightjs-ver}/languages/nix.min.js"></script>
<script>hljs.highlightAll();</script>
</with>
highlightjs-ver: 11.6.0 # Ref: https://cdnjs.com/libraries/highlight.js
# Diagrams using mermaid.js
mermaid: |
<!-- mermaid.js -->
Expand Down Expand Up @@ -176,3 +156,7 @@ emanote:
# Whether to automatically treat folder notes as a folgezettel parent of its contents
# By default, all but top-level folders are treated as folgezettel parents.
# folder-folgezettel: true

# Enable server-side syntax highlighting using skylighting (default: true)
# Set to false to use client-side highlighters like highlight.js instead
syntaxHighlighting: true
2 changes: 2 additions & 0 deletions emanote/default/templates/styles.tpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<link rel="stylesheet" href="/_emanote-static/skylighting.css" />

<style data-category="global-font">
/* Refined typography with system font stack */
body {
Expand Down
4 changes: 2 additions & 2 deletions emanote/emanote.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cabal-version: 2.4
name: emanote
version: 1.5.3.1
version: 1.5.4.0
license: AGPL-3.0-only
copyright: 2022 Sridhar Ratnakumar
maintainer: srid@srid.ca
Expand Down Expand Up @@ -114,7 +114,7 @@ common library-common
, fsnotify
, hedgehog
, heist >=1.1.1.0
, heist-extra >=0.4.0.0
, heist-extra >=0.5.0.0
, hspec
, hspec-hedgehog
, ixset-typed >=0.5.1.0
Expand Down
2 changes: 2 additions & 0 deletions emanote/src/Emanote/Pandoc/Renderer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ mkRenderCtxWithPandocRenderers ::
Map Text Text ->
model ->
route ->
-- | Enable syntax highlighting for code blocks
Bool ->
HeistT Identity m Splices.RenderCtx
mkRenderCtxWithPandocRenderers nr@PandocRenderers {..} classRules model x =
Splices.mkRenderCtx
Expand Down
4 changes: 4 additions & 0 deletions emanote/src/Emanote/View/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,13 @@ mkTemplateRenderCtx model r meta =
classRules
model
r
enableSyntaxHighlighting
classRules :: Map Text Text
classRules =
SData.lookupAeson mempty ("pandoc" :| ["rewriteClass"]) meta
enableSyntaxHighlighting :: Bool
enableSyntaxHighlighting =
SData.lookupAeson True ("emanote" :| ["syntaxHighlighting"]) meta

defaultRouteMeta :: Model -> (LMLRoute, Aeson.Value)
defaultRouteMeta model =
Expand Down
Loading