---
title: Renderer pipeline tour
date: 2025-11-17 12:05:00
categories:
  - demo
tags:
  - walkthrough
---
// Copyright 2015 Shuai Zhang
// SPDX-License-Identifier: LGPL-3.0-or-later WITH LGPL-3.0-linking-exception

= Renderer pipeline tour
:sectnums:

Want to see what happens between your `.adoc` file and the HTML that lands in
`public/`? This post follows the exact steps performed by this renderer.

== Step 1 – Asciidoctor conversion

Each render awaits the named `convert()` API from `@asciidoctor/core` 4.0.5.
Every call uses:

* `doctype=article`
* `safe=server`
* `to_file=false`

The renderer does not pass `base_dir`, so relative includes resolve from the
conversion-time current working directory. `data.path` and the Hexo site root
do not change that behavior.

This renderer is *not safe for untrusted AsciiDoc*. `safe=server` still permits
local includes, and symlink targets can escape an assumed directory boundary.
The current working directory is not a jail. Render only trusted input in an
isolated or sandboxed working directory containing no secrets.

== Step 2 – Static highlighting

After Asciidoctor returns HTML, the package rewrites only the recognized direct
listing-block chain `div.listingblock > div.content > pre > code`. That keeps
code fences visually consistent with the rest of the Hexo ecosystem without
rewriting arbitrary passthrough `<pre><code>` HTML.

The highlighter path uses fixed options:

* `autoDetect=false`
* `gutter=false`
* `wrap=false`

The package does not set `source-highlighter=html-pipeline`. The public
renderer's controlled `safe=server` options ignore a document-level setting and
use Asciidoctor's default output. Its internal highlighter recognizes the
supported default and html-pipeline marker shapes for compatibility, but this
API exposes no arbitrary highlighter configuration.

[source,typescript]
----
import renderer from 'hexo-renderer-asciidoc';

const html = await renderer({ text: '== Sample ==' });
// html already contains syntax-highlighted listing-block markup
----

== Step 3 – Curly brace escaping

After highlighting, the renderer globally encodes every literal `{` and `}` in
the generated HTML as `&#123;` and `&#125;`. This prevents downstream Hexo tag
or template interpretation where applicable. Browsers decode numeric character
references in ordinary HTML text and attribute values for display or use, but
HTML raw-text elements such as `<script>` and `<style>` do not: the references
remain literal source text and can alter or break embedded JavaScript or CSS.

Raw HTML remains unsanitized, so this package is *not suitable for untrusted
input*. Sanitizing output markup cannot prevent an include from disclosing file
contents.

== Verifying the pipeline locally

After completing the root-invoked clean-checkout setup documented in
`examples/hexo-site/README.md`, stay at the repository root and run:

[source,bash]
----
mise exec -- pnpm --dir src/public/lib/hexo-renderer-asciidoc run build
mise exec -- pnpm --dir src/public/lib/hexo-renderer-asciidoc/examples/hexo-site run generate
xdg-open src/public/lib/hexo-renderer-asciidoc/examples/hexo-site/public/index.html
----

Inspect the resulting markup and you'll see the three stages above reflected
verbatim. After adjusting the parent renderer under `src/core/`, rerun the
parent-package build before regenerating the example with the commands above.
If you script the package directly instead of going through Hexo, remember that
`renderSync` is unsupported and `renderer(...)` must be awaited.
