Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

NodeCode (WordPress plugin)

Full install & authoring guide: README.md · 简体中文

Server-side code highlighting for WordPress, powered by Shiki. When a post is saved, the plugin sends each code block to the local NodeCode service (../nodecode-service), receives themed static HTML, and caches it in post meta. On the frontend it serves that cached HTML with zero JavaScript required for highlighting — only a tiny script for the copy button, soft-wrap toggle and collapse.

Licensed under the MIT License (see LICENSE).

Why a Node service?

Shiki is a JavaScript library with no PHP port. Running it as a small localhost service lets WordPress reuse the exact, high-fidelity TextMate-grammar highlighting that VS Code uses, while visitors still get plain cached HTML.

Author saves post ──> WP (save_post) ──> POST /highlight/batch (localhost)
                                   └── cache HTML in post meta (_nodecode_cache)
Visitor views post ──> the_content ──> read cached HTML ──> static themed <pre>

Requirements

  • WordPress 5.8+, PHP 7.4+
  • The companion NodeCode service running (see ../nodecode-service/README.md)

Install

  1. Start the NodeCode service and confirm curl http://127.0.0.1:9527/health.
  2. Copy this nodecode-plugin folder into wp-content/plugins/.
  3. Activate NodeCode in the WordPress admin.
  4. Go to Settings → NodeCode and:
    • Set the Service URL (default http://127.0.0.1:9527) and API Key (must match NODECODE_API_KEY in the service .env).
    • Click Test service connection.
    • Choose Light theme / Dark theme (must be preloaded by the service).
    • Confirm the Dark mode CSS selector matches your theme setup (see below).

Dark mode

Shiki renders both themes into CSS variables (--nodecode-light / --nodecode-dark) in the same cached HTML; light is shown by default and the plugin decides when to go dark based on the Dark mode strategy setting:

Strategy When code blocks go dark Use when
Follow site dark toggle (selector) — default When the Dark mode CSS selector matches (a class/attribute on <html>/<body>) Your theme or a WP dark-mode plugin toggles a class
Follow visitor OS When the visitor's OS is dark (prefers-color-scheme) Your site has no dark toggle of its own
Always light Never (blocks stay light) A dark plugin inverts the whole page with a CSS filter, or you use Dark Reader site-wide

Avoiding "double darkening" with multiple dark-mode tools

If you run several dark-mode mechanisms at once (theme dark mode + a WP dark-mode plugin + a browser extension like Dark Reader), they can fight and double-process the code colors. The plugin includes safeguards and a recommended setup:

  • Every code block declares color-scheme and carries a data-nodecode-managed="1" attribute, signalling browsers/extensions that it handles its own theming.
  • Pick ONE source of truth via the strategy setting instead of stacking them.

Recommended config for a site that has its own dark toggle:

  1. Strategy = Follow site dark toggle (selector).
  2. Toggle dark mode on your site, open DevTools, inspect <html>/<body>, and put the class/attribute that appears into Dark mode CSS selector (default tries html[data-theme="dark"], body.dark, html.dark).
  3. If a separate dark plugin or Dark Reader still recolors code blocks, exclude them there using the selector [data-nodecode-managed] (most tools have an "ignore selectors" list), or switch the strategy to Always light so the page-level filter darkens everything uniformly.

Authoring code

Any of these are detected automatically:

  • Gutenberg code block (``` block) — language taken from a language-xxx class if present.
  • Classic editor <pre><code class="language-js"> ... </code></pre> (also supports legacy brush: js).
  • Shortcode: [nodecode lang="js" title="example.js"] ... [/nodecode] or [code lang="php"] ... [/code] (legacy [shiki] is also accepted).
    • Optional attributes: title, linenumbers="true|false", wrap="true|false".

Line annotations (Shiki notation)

Inside the code, comments drive per-line effects:

  • // [!code highlight] — highlight the line
  • // [!code ++] / // [!code --] — diff added / removed
  • // [!code focus] — focus this line (blur the rest)
  • // [!code word:foo] — highlight a word

WP-CLI

After changing themes/features, regenerate caches for existing posts:

wp nodecode rerender --all
wp nodecode rerender --post=123
wp nodecode rerender --all --post_type=post,page
wp nodecode flush          # clear all cached HTML + transients
wp nodecode health         # check the service connection

How caching works

  • Each block is hashed from code + lang + title + flags + config version.
  • config version includes the chosen themes and plugin version, so changing themes invalidates old cache entries automatically (re-run wp nodecode rerender).
  • If the service is down when a post is saved, those blocks are not cached; on the frontend the plugin first tries a live render (cached in a transient), and if that also fails it falls back to an escaped <pre><code> block — the page never breaks.

Uninstall

Removing the plugin deletes its options, all _nodecode_cache post meta and the nodecode_live_* transients.