Skip to content

Powered by Grav

Code Blocks

Server-Side Syntax Highlighting

Codesh for Grav is a plugin that provides server-side syntax highlighting for code blocks in your Grav site.

Codesh provides server-side syntax highlighting using Phiki, a PHP port of Shiki that uses TextMate grammars and VS Code themes. All highlighting happens on the server - no JavaScript required, faster page loads, and perfect SEO.

Basic Syntax Highlighting

Tip

View the markdown source for this page to see the raw syntax.

Use the [codesh] shortcode with the language as a shorcode parameter rusulting in:

JAVASCRIPT
function greet(name) {
    return `Hello, ${name}!`;
}

const message = greet('World');
console.log(message);
PYTHON
def greet(name):
    return f"Hello, {name}!"

message = greet("World")
print(message)
PHP
<?php

function greet($name) {
    return "Hello, {$name}!";
}

$message = greet('World');
echo $message;

Wrapping Markdown Code Blocks

For compatibility with markdown editors, you can wrap standard fenced code blocks:

RUST
fn main() {
    println!("Hello, Rustaceans!");
}

Supported Languages

Codesh supports 200+ languages via TextMate grammars, including:

Language Identifier
JavaScript javascript, js
TypeScript typescript, ts
Python python, py
PHP php
Ruby ruby, rb
Go go
Grav grav
Rust rust, rs
Shell/Bash bash, shell, sh
SQL sql
YAML yaml, yml
JSON json
HTML html
CSS css
Markdown markdown, md
Swift swift
Kotlin kotlin, kt
And 180+ more...

Line Numbers

Enable line numbers with the line-numbers attribute:

JAVASCRIPT
 1// This block has line numbers
 2const a = 1;
 3const b = 2;
 4const c = a + b;
 5console.log(c);

Custom Starting Line

Start from a specific line number:

PYTHON
10# Starting from line 10
11def calculate(x, y):
12    return x + y
13
14result = calculate(5, 3)

Line Highlighting

Highlight specific lines to draw attention using highlight or hl:

JAVASCRIPT
 1function processData(data) {
 2    const filtered = data.filter(item => item.active);
 3
 4    const mapped = filtered.map(item => ({
 5        id: item.id,
 6        name: item.name.toUpperCase()
 7    }));
 8
 9    return mapped;
10}

Syntax: highlight="LINE_NUMBERS" where LINE_NUMBERS can be:

  • Single lines: 1,3,5
  • Ranges: 2-4
  • Combined: 1,3-5,8

Line Focus

Focus on specific lines by dimming non-focused lines:

JAVASCRIPT
 1function example() {
 2    // setup code
 3    const important = true;
 4    doSomething(important);
 5    return important;
 6    // cleanup code
 7}

This is useful for drawing attention to the most important parts of longer code examples.

Title/Filename Display

Show a filename or custom title in the header instead of the language:

src/Controller/UserController.php
<?php

namespace App\Controller;

class UserController extends AbstractController
{
    public function index(): Response
    {
        return $this->render('user/index.html.twig');
    }
}

Hide Language Badge

Hide the language badge entirely with hide-lang="true":

BASH
npm install
npm run build

Minimal Mode (No Header)

Hide the entire header bar for a super minimal look with hide-header="true":

JAVASCRIPT
const minimal = true;
console.log('No header, just code');

Automatic Light/Dark Mode

Codesh automatically detects your theme's light/dark mode setting and uses the appropriate syntax theme. When you toggle the theme, the code blocks switch automatically.

  • In light mode: Uses the theme_light setting (default: helios-light)
  • In dark mode: Uses the theme_dark setting (default: helios-dark)

Custom Themes

Override the default theme per code block:

GitHub Dark (default)

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Dracula

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Nord

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

One Dark Pro

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Tokyo Night

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Catppuccin Mocha

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Rose Pine

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

GitHub Light

TYPESCRIPT
interface User {
    id: number;
    name: string;
    email: string;
}

Available Themes

Codesh includes 70+ VS Code themes:

Dark Themes Light Themes
github-dark, github-dark-dimmed github-light
dracula, dracula-soft one-light
nord solarized-light
one-dark-pro catppuccin-latte
monokai vitesse-light
tokyo-night min-light
catppuccin-mocha, catppuccin-macchiato gruvbox-light-*
rose-pine, rose-pine-moon rose-pine-dawn
material-theme-* variants material-theme-lighter
vitesse-dark, vitesse-black snazzy-light
ayu-dark everforest-light
night-owl
poimandres
houston
synthwave-84
vesper

Terminal Output

Use bash or shell for terminal commands:

BASH
$ npm install codesh-plugin
+ [email protected]
added 10 packages in 2.1s

$ npm run build
> Building assets...
> Done in 1.2s

Diff Highlighting

Show code changes with diff (diff=true) syntax:

TXT
- const greeting = 'Hello';
+ const greeting = 'Hello, World!';

function sayHello() {
-   console.log(greeting);
+   console.log(`${greeting} How are you?`);
}

Code Groups

Display multiple code examples in a tabbed interface. Perfect for showing the same functionality in different languages.

Basic Code Group

function greet(name) {
    return `Hello, ${name}!`;
}

console.log(greet("World"));
def greet(name):
    return f"Hello, {name}!"

print(greet("World"))
<?php

function greet($name) {
    return "Hello, {$name}!";
}

echo greet("World");

Synced Code Groups

Use the sync attribute to synchronize tab selection across multiple code groups on the same page. When you select a tab in one group, all groups with the same sync key switch to match.

Variable Declaration:

const name = "World";
const greeting = `Hello, ${name}!`;
name = "World"
greeting = f"Hello, {name}!"
$name = "World";
$greeting = "Hello, {$name}!";

Output:

console.log(greeting);
// Output: Hello, World!
print(greeting)
# Output: Hello, World!
echo $greeting;
// Output: Hello, World!

Tab selections are automatically persisted, so they survive page reloads.

Why Codesh?

Feature Benefit
Server-side rendering No JavaScript required, instant display
200+ languages Comprehensive language support
70+ VS Code themes Beautiful, familiar syntax themes
Built-in line highlighting Highlight specific lines easily
Built-in line focus Draw attention to key code sections
TextMate grammars Accurate, industry-standard highlighting
SEO-friendly Code is in the HTML, fully indexable

Shortcode Attributes Reference

Attribute Description Example
lang Programming language lang="php"
theme Override syntax theme theme="dracula"
line-numbers Show line numbers line-numbers="true"
start Starting line number start="10"
highlight / hl Lines to highlight highlight="1,3-5"
focus Lines to focus focus="2-4"
title Filename or title to display title="config.yaml"
hide-lang Hide the language badge hide-lang="true"
hide-header Hide the header bar hide-header="true"
class Additional CSS class class="my-class"

Code Group Attributes

Attribute Description Example
sync Sync key for tab synchronization sync="lang"

Configuration

Configure defaults in user/config/plugins/codesh.yaml:

YAML
enabled: true
active: true
theme_dark: github-dark     # Theme for dark mode
theme_light: github-light   # Theme for light mode
show_line_numbers: false    # Show line numbers by default
process_markdown: true      # Auto-highlight markdown code blocks

© 2025 Grav. All rights reserved.