Skip to content

Commit 86e280f

Browse files
committed
chore: add server-side highlighting mode with highlight.php, update docs and build process
Add highlight.php dependency, new highlighting-mode setting (client/server), token class remapping for visual parity across both modes. Update build scripts to install production dependencies and exclude build-prism.min.js. Remove composer.lock from .gitignore. Update AGENTS.md, CLAUDE.md, README.md with server-mode details.
1 parent fa6e7ef commit 86e280f

84 files changed

Lines changed: 4453 additions & 83 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/zipitup.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
uses: actions/checkout@v6
2828

2929
- name: Create artifact
30-
run: composer zip build-prism.js
30+
run: composer zip
3131
- name: Upload to release
3232
uses: softprops/action-gh-release@v2
3333
with:

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# AGENTS.md
22

3-
WordPress plugin extending the native Gutenberg `core/code` block with Prism.js syntax highlighting via JS block filters and a `render_block_core/code` PHP filter. Does not replace the block — existing posts stay valid.
3+
WordPress plugin extending the native Gutenberg `core/code` block with syntax highlighting via JS block filters and a `render_block_core/code` PHP filter. Does not replace the block — existing posts stay valid.
4+
5+
Two highlighting modes:
6+
- **Client-side** (default): Prism.js runs in the browser. Loads the Prism JS bundle + theme CSS.
7+
- **Server-side**: highlight.php pre-renders token spans on the server. No JS loaded. Uses the same Prism theme CSS — token class remapping (`remap_token_classes()` in `class-blocks.php`) converts hljs-* span classes to Prism `token *` classes via `strtr`, giving exact visual parity across all 21 themes.
48

59
## Commands
610

CLAUDE.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
44

55
## Plugin Overview
66

7-
**WebberZone Code Block Highlighting** (plugin slug: `webberzone-code-block-highlighting`) extends the native Gutenberg `core/code` block with Prism.js syntax highlighting via JS block filters and a `render_block_core/code` PHP filter. Does not replace the block — existing posts stay valid. Namespace: `WebberZone\Code_Block_Highlighting`. Requires WordPress 6.6+, PHP 7.4+. No Freemius.
7+
**WebberZone Code Block Highlighting** (plugin slug: `webberzone-code-block-highlighting`) extends the native Gutenberg `core/code` block with syntax highlighting via JS block filters and a `render_block_core/code` PHP filter. Does not replace the block — existing posts stay valid. Namespace: `WebberZone\Code_Block_Highlighting`. Requires WordPress 6.6+, PHP 7.4+. No Freemius.
8+
9+
Two highlighting modes:
10+
- **Client-side** (default): Prism.js runs in the browser. Loads the Prism JS bundle + theme CSS.
11+
- **Server-side**: highlight.php pre-renders token spans on the server. No JS loaded. Uses the same Prism theme CSS — token class remapping (`remap_token_classes()` in `class-blocks.php`) converts hljs-* span classes to Prism `token *` classes via `strtr`, giving exact visual parity across all 21 themes.
812

913
WordPress.org: https://wordpress.org/plugins/webberzone-code-block-highlighting/
1014
webberzone.com: https://webberzone.com/plugins/webberzone-code-block-highlighting/
@@ -40,9 +44,9 @@ Bootstrap: `wzcbh()` singleton on `plugins_loaded` → instantiates `Frontend\Bl
4044

4145
Key files:
4246
- `includes/class-main.php` — bootstrap and object wiring
43-
- `includes/frontend/class-blocks.php` — editor assets, REST route, `render_block_core/code`
44-
- `includes/frontend/class-styles-handler.php` — conditional Prism asset loading
45-
- `includes/admin/class-settings.php` — settings registration, theme resolution
47+
- `includes/frontend/class-blocks.php` — editor assets, REST route, `render_block_core/code` filter; `render_code_block_server()` for server mode; `remap_token_classes()` for hljs→Prism class mapping
48+
- `includes/frontend/class-styles-handler.php` — conditional asset loading for both modes: client (Prism JS + theme CSS) and server (theme CSS + `hljs-server-mode.css`, no JS)
49+
- `includes/admin/class-settings.php` — settings registration; `get_color_scheme_css()` always returns Prism CSS URL (no per-mode branch)
4650
- `includes/blocks/src/js/index.js` — block filter, Inspector Controls
4751
- `includes/blocks/src/js/frontend.js` — Prism grammars + plugins
4852

@@ -64,9 +68,20 @@ Always `require` the generated `.asset.php` manifest before enqueueing block scr
6468

6569
**If you change block attributes in JS**, update `render_code_block()` in `class-blocks.php` and the defaults flow as well.
6670

71+
**Server-mode token remapping**`remap_token_classes()` in `class-blocks.php` uses `strtr()` to convert every `class="hljs-*"` span emitted by highlight.php into the equivalent Prism `class="token *"` span. `strtr()` is safe here because highlight.php emits single-class spans only (no compound classes). Keys are ordered longest-first to prevent prefix collisions (e.g. `hljs-selector-tag` before a hypothetical `hljs-selector`).
72+
73+
**highlight.php autoloader**`\Highlight\Autoloader::register()` does not exist. Use `spl_autoload_register(static function(string $class_name): void { \Highlight\Autoloader::load($class_name); })`.
74+
75+
**`hljs-server-mode.css`** — only handles `.wzcbh-highlighted-line` line highlighting. Font-size, line-numbers gutter, and word-wrap are all in `frontend.css` (webpack build), which loads in both modes.
76+
77+
**Both modes use the same Prism theme CSS**`Settings::get_color_scheme_css()` always returns the Prism CSS URL. There is no per-mode branch or hljs-specific theme mapping table.
78+
6779
## Asset loading
6880

69-
Prism assets load only on pages containing at least one `core/code` block (`Styles_Handler::enqueue_assets()`). Use `wzcbh_force_load_assets` to override.
81+
Assets load only on pages containing at least one `core/code` block (`Styles_Handler::enqueue_assets()`). Use `wzcbh_force_load_assets` to override.
82+
83+
- **Client mode**: `frontend.css` + Prism theme CSS + `wzcbh-prism-js` script bundle (includes all grammars and plugins)
84+
- **Server mode**: `frontend.css` + Prism theme CSS + `hljs-server-mode.css` (no JS; syntax already pre-rendered in HTML)
7085

7186
## Filters and routes
7287

README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,29 @@ __License:__ [GPL-2.0+](http://www.gnu.org/licenses/gpl-2.0.html)
1616

1717
__Plugin page:__ [WebberZone Code Block Highlighting](https://webberzone.com/plugins/webberzone-code-block-highlighting/) | [WordPress.org listing](https://wordpress.org/plugins/webberzone-code-block-highlighting/)
1818

19-
Add beautiful syntax highlighting to the Gutenberg Code block — powered by Prism.js with 21 themes and 40 languages, zero configuration required.
19+
Syntax highlighting for the Gutenberg Code block — Prism.js, 21 themes, 40+ languages, plus an optional no-JavaScript server-side mode.
2020

2121
## Description
2222

2323
__WebberZone Code Block Highlighting__ is the easiest way to add syntax highlighting to your WordPress site. It extends the native Gutenberg `core/code` block with [Prism.js](https://prismjs.com/) highlighting — no shortcodes, no block replacement, no risk of breaking existing posts.
2424

25-
Simply activate the plugin and your code blocks will instantly display beautiful, readable syntax highlighting on the frontend. Choose from 35+ programming languages and 21 colour themes, all controlled from the block editor's Inspector Controls sidebar.
25+
Simply activate the plugin and your code blocks will instantly display beautiful, readable syntax highlighting on the frontend. Choose from 40+ programming languages and 21 colour themes, all controlled from the block editor's Inspector Controls sidebar.
26+
27+
### Two highlighting modes
28+
29+
Pick the rendering mode that best fits your site from the settings page:
30+
31+
* __Client-side (default)__[Prism.js](https://prismjs.com/) highlights your code in the browser. Best for interactive features such as copy-to-clipboard and expand/collapse.
32+
* __Server-side (no JavaScript)__ — Code is pre-highlighted on the server with [highlight.php](https://github.com/scrivo/highlight.php), so no JavaScript is loaded on the frontend. Ideal for performance, Core Web Vitals, AMP-style setups, and strict content-security policies.
33+
34+
Both modes use the same 21 Prism themes and produce visually identical output, so you can switch between client-side and server-side rendering at any time without changing how your code blocks look.
2635

2736
### Why use this plugin?
2837

2938
* __Safe by design__ — Works as a filter on top of `core/code`. Existing posts are never invalidated. Deactivate the plugin and your blocks are still valid standard WordPress code blocks.
3039
* __Zero configuration__ — Activate and start writing. No setup wizard, no shortcodes.
31-
* __Smart asset loading__ — Prism CSS and JS only load on pages that actually contain code blocks. Pages without code stay fast.
40+
* __JavaScript-free option__ — Server-side highlighting renders syntax colours without loading any frontend JavaScript, keeping your pages lean and fast.
41+
* __Smart asset loading__ — Theme CSS (and, in client mode, Prism JS) only load on pages that actually contain code blocks. Pages without code stay fast.
3242
* __Per-block controls__ — Set language, theme, line numbers, word wrap, title, highlighted lines, and max height individually for each block.
3343
* __Developer-friendly__ — Filters to add languages, override themes, and force asset loading.
3444

@@ -51,6 +61,7 @@ A11y Dark, Coldark Cold (Light), Coldark Dark, Dracula, Duotone Dark, Duotone Li
5161

5262
### Global settings
5363

64+
* Highlighting mode — client-side (Prism.js) or server-side (highlight.php, no JavaScript)
5465
* Default colour scheme (theme)
5566
* Default language
5667
* Default line numbers toggle and start value
@@ -99,8 +110,11 @@ No. The plugin uses JavaScript and PHP filters to extend `core/code`. Deactivati
99110
__Which languages are supported?__
100111
40 out of the box. Use the `wzcbh_languages` filter to add or remove entries from the language picker — note the corresponding Prism.js grammar must also be available on the frontend.
101112

113+
__What is the difference between client-side and server-side highlighting?__
114+
Client-side mode runs [Prism.js](https://prismjs.com/) in the browser and enables interactive toolbar features (copy-to-clipboard, expand/collapse). Server-side mode pre-renders the highlighted markup with [highlight.php](https://github.com/scrivo/highlight.php) so no JavaScript is loaded on the frontend — ideal for performance and strict content-security policies. Both modes share the same 21 themes and look identical, so you can switch freely from __Settings > Code Block Highlighting__.
115+
102116
__Does Prism.js load on every page?__
103-
No. Assets are only enqueued on pages containing at least one code block. Use `wzcbh_force_load_assets` to override.
117+
No. Theme CSS and (in client-side mode) Prism JS are only enqueued on pages containing at least one code block. Use `wzcbh_force_load_assets` to override.
104118

105119
__How do I highlight specific lines?__
106120
Enter a comma-separated list of lines or ranges in the __Highlight Lines__ field in the sidebar (e.g. `1,3-5,8`).

build-prism.min.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build-zip.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ package-lock.json
4242
phpstan-bootstrap.php
4343
build-zip.sh
4444
build-prism.js
45+
build-prism.min.js
4546
CODE_OF_CONDUCT.md
4647
CONTRIBUTING.md
4748
ISSUE_TEMPLATE.md
@@ -50,6 +51,13 @@ CLAUDE.md
5051
AGENTS.md
5152
EOF
5253

54+
# Install production-only PHP dependencies into the build copy.
55+
# composer.json/lock are excluded from rsync, so copy them temporarily.
56+
echo "Installing production PHP dependencies..."
57+
cp composer.json composer.lock "$TEMP_DIR/"
58+
composer install --working-dir="$TEMP_DIR" --no-dev --quiet
59+
rm "$TEMP_DIR/composer.json" "$TEMP_DIR/composer.lock"
60+
5361
# Create zip
5462
echo "Creating zip file..."
5563
cd "$BUILD_DIR"

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "webberzone/webberzone-code-block-highlighting",
33
"description": "Extends the Gutenberg Code block with syntax highlighting powered by Prism.js.",
4-
"version": "1.0.0",
4+
"version": "1.2.0",
55
"type": "wordpress-plugin",
66
"keywords": [
77
"code block",
@@ -19,7 +19,8 @@
1919
}
2020
],
2121
"require": {
22-
"php": ">=7.4"
22+
"php": ">=7.4",
23+
"scrivo/highlight.php": "^9.18"
2324
},
2425
"require-dev": {
2526
"szepeviktor/phpstan-wordpress": "^1",

includes/admin/class-settings.php

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,21 @@ public static function get_settings_sections(): array {
178178
public static function get_registered_settings(): array {
179179
return array(
180180
'general' => array(
181+
array(
182+
'id' => 'highlighting-mode',
183+
'name' => __( 'Highlighting Mode', 'webberzone-code-block-highlighting' ),
184+
'desc' => __( 'Client-side: Prism.js runs in the browser (default, supports all block features). Server-side: highlight.php pre-renders syntax on the server — no JavaScript required.', 'webberzone-code-block-highlighting' ),
185+
'type' => 'radio',
186+
'default' => 'client',
187+
'options' => array(
188+
'client' => __( 'Client-side (Prism.js)', 'webberzone-code-block-highlighting' ),
189+
'server' => __( 'Server-side (highlight.php)', 'webberzone-code-block-highlighting' ),
190+
),
191+
),
181192
array(
182193
'id' => 'color-scheme',
183194
'name' => __( 'Color Scheme', 'webberzone-code-block-highlighting' ),
184-
'desc' => __( 'Choose the syntax highlighting theme for all code blocks. This styling is applied only on the frontend and not in the block editor.', 'webberzone-code-block-highlighting' ),
195+
'desc' => __( 'Choose the syntax highlighting theme. The same Prism.js theme is used in both client-side and server-side modes.', 'webberzone-code-block-highlighting' ),
185196
'type' => 'select',
186197
'default' => 'prism-onedark',
187198
'options' => self::$color_schemes,
@@ -310,10 +321,8 @@ public function enqueue_language_data( string $hook ): void {
310321
/**
311322
* Get the URL (or filesystem path) to the active color scheme CSS file.
312323
*
313-
* Returns the plain unminified LTR path. Frontend enqueuing (with SCRIPT_DEBUG
314-
* and RTL awareness) is handled by Styles_Handler.
315-
*
316-
* Falls back to the default One Dark theme if the chosen file does not exist.
324+
* Returns the plain unminified LTR path; enqueuing with SCRIPT_DEBUG and RTL
325+
* awareness is handled by Styles_Handler.
317326
*
318327
* @since 1.0.0
319328
*
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
pre code.hljs {
2+
display: block;
3+
overflow-x: auto;
4+
padding: 1em;
5+
}
6+
code.hljs {
7+
padding: 3px 5px;
8+
}
9+
/*!
10+
Theme: a11y-dark
11+
Author: @ericwbailey
12+
Maintainer: @ericwbailey
13+
14+
Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css
15+
*/
16+
.hljs {
17+
background: #2b2b2b;
18+
color: #f8f8f2;
19+
}
20+
/* Comment */
21+
.hljs-comment,
22+
.hljs-quote {
23+
color: #d4d0ab;
24+
}
25+
/* Red */
26+
.hljs-variable,
27+
.hljs-template-variable,
28+
.hljs-tag,
29+
.hljs-name,
30+
.hljs-selector-id,
31+
.hljs-selector-class,
32+
.hljs-regexp,
33+
.hljs-deletion {
34+
color: #ffa07a;
35+
}
36+
/* Orange */
37+
.hljs-number,
38+
.hljs-built_in,
39+
.hljs-literal,
40+
.hljs-type,
41+
.hljs-params,
42+
.hljs-meta,
43+
.hljs-link {
44+
color: #f5ab35;
45+
}
46+
/* Yellow */
47+
.hljs-attribute {
48+
color: #ffd700;
49+
}
50+
/* Green */
51+
.hljs-string,
52+
.hljs-symbol,
53+
.hljs-bullet,
54+
.hljs-addition {
55+
color: #abe338;
56+
}
57+
/* Blue */
58+
.hljs-title,
59+
.hljs-section {
60+
color: #00e0e0;
61+
}
62+
/* Purple */
63+
.hljs-keyword,
64+
.hljs-selector-tag {
65+
color: #dcc6e0;
66+
}
67+
.hljs-emphasis {
68+
font-style: italic;
69+
}
70+
.hljs-strong {
71+
font-weight: bold;
72+
}
73+
@media screen and (-ms-high-contrast: active) {
74+
.hljs-addition,
75+
.hljs-attribute,
76+
.hljs-built_in,
77+
.hljs-bullet,
78+
.hljs-comment,
79+
.hljs-link,
80+
.hljs-literal,
81+
.hljs-meta,
82+
.hljs-number,
83+
.hljs-params,
84+
.hljs-string,
85+
.hljs-symbol,
86+
.hljs-type,
87+
.hljs-quote {
88+
color: highlight;
89+
}
90+
.hljs-keyword,
91+
.hljs-selector-tag {
92+
font-weight: bold;
93+
}
94+
}

includes/assets/hljs-a11y-dark-rtl.min.css

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)