DocBook is a Ruby gem for parsing, validating, and converting DocBook 5 XML documents into interactive HTML readers and structured JSON. It provides a complete command-line interface and Ruby API for document processing.
Key features:
-
Interactive readerβββSelf-contained HTML with search, themes, TOC navigation
-
DocBook 5 parsingβββFull element support via lutaml-model
-
XInclude resolutionβββTransparent handling of multi-file documents
-
DocbookMirror JSONβββProseMirror-compatible structured representation
-
Output formatsβββInline, DOM (SEO), distribution directory, split-pages, and chunked (on-demand loading) modes
-
Library supportβββMulti-book collections with covers and manifests
Build an interactive reader from any DocBook XML:
$ docbook build guide.xmlThis produces guide.html in the same directory. Open it in a browserβββit works offline with no server required.
Specify a custom output path:
$ docbook build guide.xml -o output.htmlTry the bundled demo:
$ docbook build --demoSEO-friendly with pre-rendered content:
$ docbook build guide.xml --format dom -o reader.htmlBuild any DocBook XML into a self-contained interactive HTML reader:
# Single-file (images inlined as data URLs, works offline from file://)
$ docbook build book.xml
# Distribution directory (separate data/JSON, for HTTP hosting)
$ docbook build book.xml --format dist -o /var/www/book/
# Split pages (one HTML per chapter/section)
$ docbook build book.xml --format paged -o /var/www/book/
# On-demand section loading (lazy-loaded chunks, best for large books)
$ docbook build book.xml --format chunked -o /var/www/book/Try it with the bundled fixtures:
# Build the article fixture as a self-contained reader
$ docbook build spec/fixtures/article/article.xml -o article-reader.html
# Build the xslTNG sample book as a distribution directory
$ docbook build spec/fixtures/xslTNG/test/resources/xml/book.014.xml --format dist -o /tmp/book-dist/Build a collection of DocBooks into a single library SPA with a bookshelf UI:
# Inline single-file library
$ docbook library my-library/ --format inline -o library.html
# Distribution directory (separate data/JSON per book)
$ docbook library my-library/ --format dist -o /var/www/library/Try it with the bundled library fixture:
# Build the sample library as a self-contained HTML
$ docbook library spec/fixtures/library_sample/ --format inline -o /tmp/library.html
# Build as a distribution directory for HTTP hosting
$ docbook library spec/fixtures/library_sample/ --format dist -o /tmp/library-dist/A typical DocBook project with images and resources:
my-book/
βββ book.xml # Main DocBook XML (or article.xml)
βββ images/ # Image assets
β βββ fig-arch.png
β βββ logo.svg
βββ resources/ # Additional media
β βββ data.csv
βββ chapters/ # XInclude'd chapters (optional)
βββ intro.xml
βββ advanced.xmlFor a multi-book library:
my-library/
βββ library.yml # Library manifest (or library.json)
βββ book-one/
β βββ book-one.xml # Book XML
β βββ cover.png # Cover image (optional)
β βββ images/ # Book-specific images
β βββ fig1.png
βββ book-two/
βββ book-two.xml
βββ images/
βββ diagram.pngThe manifest (library.yml or library.json) defines the books in the collection:
# library.yml
name: "My Documentation Library"
description: "Technical documentation collection"
books:
- id: "user-guide"
source: "user-guide/book.xml"
title: "User Guide"
cover: "user-guide/cover.png"
- id: "api-reference"
source: "api-reference/api.xml"{
"name": "My Documentation Library",
"description": "Technical documentation collection",
"books": [
{
"id": "user-guide",
"source": "user-guide/book.xml",
"title": "User Guide",
"cover": "user-guide/cover.png"
},
{
"id": "api-reference",
"source": "api-reference/api.xml"
}
]
}Each book entry requires:
-
idβββUnique slug (used for filenames) -
sourceβββPath to DocBook XML (relative to manifest)
Optional fields:
-
titleβββOverride title (default: extracted from XML<title>) -
coverβββPath to cover image -
authorβββOverride author -
descriptionβββBook description
Format |
Description |
Use case |
|
Single self-contained |
Sharing via email, USB, local viewing. All assets inlined. |
|
Single |
SEO β content visible without JavaScript. |
|
Directory with |
HTTP hosting (Nginx, S3). Images as separate files. |
|
Directory with split HTML pages |
Large books, section-per-page navigation. |
|
Directory with lazy-loaded section chunks |
Very large books, on-demand section loading. |
Strategy |
Description |
Use case |
|
Embed images as base64 data URLs |
Default. Self-contained HTML, works offline. |
|
Resolve to |
Local filesystem viewing. |
|
Keep relative paths as-is |
HTTP hosting with external image files. |
require 'docbook'
# Build an interactive reader (any format)
Docbook::Output::Builder.new(
xml_path: 'guide.xml',
output_path: 'guide.html',
format: :inline # or :dom, :dist, :paged, :chunked
).build
# Build a multi-book library
Docbook::Output::LibraryBuilder.new(
input_path: 'library.yml',
output_path: 'library.html',
format: :inline
).build
# Export as DocbookMirror JSON
parsed = Docbook::Document.from_xml(File.read('guide.xml'))
json = Docbook::Output::DocbookMirror.new(parsed).to_pretty_json
File.write('guide.json', json)| Command | Description |
|---|---|
|
Build an interactive HTML reader from DocBook XML. Pass |
|
Build a multi-book library from a directory or manifest |
|
Export as DocbookMirror JSON |
|
Validate DocBook XML against RELAX NG schema |
|
Format/prettify DocBook XML |
Build an interactive HTML reader. The output is a single self-contained file that works offline (CSS, JS, and images are all inlined).
$ docbook build [INPUT] [options]
$ docbook build --demo [options]Options:
-
-o, --output FILEβββOutput HTML file path (default:<input>.htmlordemo.html) -
--demoβββUse the bundled DocBook sample as input (accepts name:xslTNGormodel-flow) -
--format FORMATβββOutput format:inline(default),dom,dist,paged, orchunked -
--image-search-dir DIRβββDirectories to search for images (default: XML file directory) -
--image-strategy STRATEGYβββImage handling:data_url(default),file_url, orrelative -
--title TITLEβββPage title (default: derived from document) -
--sort-glossaryβββSort glossary entries alphabetically -
--xinclude/--no-xincludeβββResolve XIncludes (default: true)
Examples:
# Basic (output defaults to book.html)
$ docbook build book.xml
# Custom output path
$ docbook build book.xml -o output.html
# SEO-friendly with pre-rendered content
$ docbook build book.xml --format dom -o output.html
# Distribution directory (separate assets)
$ docbook build book.xml --format dist -o /var/www/book/
# Split into individual pages
$ docbook build book.xml --format paged -o /var/www/book/
# On-demand section loading (best for large books)
$ docbook build book.xml --format chunked -o /var/www/book/
# With custom image paths
$ docbook build book.xml --image-search-dir media/ images/
# For web hosting (external image files)
$ docbook build book.xml --image-strategy relative
# Bundled demo
$ docbook build --demo
# Named demo
$ docbook build --demo=model-flowExport DocBook XML as DocbookMirror JSON (ProseMirror-compatible format):
$ docbook export INPUT -o output.json
# Or to stdout
$ docbook export INPUTValidate DocBook XML:
$ docbook validate input.xml
input.xml: valid
# Well-formedness only (no schema)
$ docbook validate --wellformed input.xmlBuild a multi-book library from a directory or manifest:
# From a directory (auto-discovers XML files)
$ docbook library my-library/ -o library.html
# From a YAML manifest
$ docbook library library.yml --format dist -o /var/www/library/
# From a JSON manifest
$ docbook library library.json --format paged -o /var/www/library/require 'docbook'
# Parse a DocBook document (auto-detects article, book, chapter, etc.)
doc = Docbook::Document.from_xml(File.read('guide.xml'))
# With XInclude resolution
xml_string = File.read('main.xml')
resolved = Docbook::XincludeResolver.resolve_string(xml_string, base_path: 'main.xml')
doc = Docbook::Document.from_xml(resolved.to_xml)# Full pipeline: parse + TOC + numbering + index + images + HTML
builder = Docbook::Output::Builder.new(
xml_path: 'guide.xml',
output_path: 'output/guide.html',
format: :inline, # :inline, :dom, :dist, :paged, or :chunked
image_search_dirs: ['media/'],
image_strategy: :data_url, # :data_url, :file_url, or :relative
title: "My Document"
)
builder.build
# Build a multi-book library
Docbook::Output::LibraryBuilder.new(
input_path: 'library.yml',
output_path: 'library.html',
format: :inline
).buildThe interactive reader built by docbook build includes:
- Themes
-
Day, Sepia, Night, OLEDβββall driven by CSS custom properties
- Search
-
Full-text search across headings and content (FlexSearch, lazy-loaded)
- TOC
-
Collapsible hierarchical table of contents
- Breadcrumb
-
Ancestor chain breadcrumb bar with collapsible chips
- Fonts
-
Sans-serif (Inter) and serif (Merriweather) options
- Navigation
-
Keyboard shortcuts (
/for search,Escto close) -
Clean print stylesheet
- Progressive load
-
Chunked format with on-demand sections, IndexedDB caching, skeleton screens, and prefetch
- Mobile gestures
-
Touch swipe from left edge opens sidebar
- Bookmarks
-
Press
bto bookmark any section - Accessibility
-
Reduced-motion support, focus-visible indicators, 44px touch targets
The readerβs frontend is a Vue 3 application pre-compiled into frontend/dist/.
cd frontend
npm install
npm run buildAfter building, docbook build automatically includes the compiled assets.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DocBook XML (input) β
β book.xml, article.xml, etc. β
ββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Lutaml::Model (gem) β
β Serialization Framework β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Lutaml::Model::Serializable β β
β β β’ XML β Ruby object mapping (from_xml / to_xml) β β
β β β’ Attribute definitions with types β β
β β β’ mixed_content, map_element, map_attribute β β
β β β’ Lutaml::Xml::W3c::XmlIdType for xml:id β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² base class for all element classes β
ββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Docbook Gem (metanorma/docbook) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Docbook::Elements::* (~100+ classes) β β
β β β β
β β Structural: Book, Article, Chapter, Part, Section, Appendix β β
β β Block: Para, FormalPara, BlockQuote, Example β β
β β List: OrderedList, ItemizedList, VariableList β β
β β Inline: Emphasis, Code, Link, Xref, Filename, Command β β
β β Media: MediaObject, ImageObject, ImageData, Figure β β
β β Table: Table, InformalTable, TGroup, Row, Entry β β
β β Admonition: Note, Warning, Caution, Important, Tip β β
β β Reference: RefEntry, RefSection, RefMeta, FieldSynopsis β β
β β ...and more β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Docbook::Document β
β β’ Root element dispatcher (from_xml β correct element class) β
β β
β ββββββββββββββββββ ββββββββββββββββββββββ βββββββββββββββββββββ β
β β XInclude β β XrefResolver β β Services::* β β
β β Resolver β β (link resolution)β β (helpers) β β
β ββββββββββββββββββ ββββββββββββββββββββββ βββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Output Layer β β
β β β β
β β ββββββββββββββββββββ ββββββββββββββββββ ββββββββββββββββββββ β β
β β β Output::Builder β β Output:: β β Output:: β β β
β β β Pipeline β β β HtmlRenderer β β Formats::* β β β
β β β Format β β (DOM/Paged) β β Inline/Dom/ β β β
β β β β β β β Dist/Paged/ β β β
β β β β β β β Chunked β β β
β β ββββββββββ¬ββββββββββ βββββββββββββββββββ ββββββββββββββββββββ β β
β β β β β
β βββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β βΌ β β
β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β DocbookMirror (Mirror::Transformer) β β β
β β β β β β
β β β Converts Docbook Element objects β ProseMirror-compatible β β β
β β β JSON document format (doc > nodes > text, with marks) β β β
β β β β β β
β β β Mirror::Node::Document βββ β β β
β β β Mirror::Node::Block βββββ€ tree structure β β β
β β β Mirror::Node::Text βββββ€ β β β
β β β Mirror::Mark::* βββββ inline annotations β β β
β β β (emphasis, code, link, xref, citation, tag) β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β β β β
β β export cmd (JSON) embedded in Builder β β
β β β β β β
β βββββββββββββββββββββββΌβββββββββββββββββββββββββββΌβββββββββββββββββββ β
β β β β
β βΌ βΌ β
ββββββββββββββββββββββββββΌβββββββββββββββββββββββββββΌββββββββββββββββββββββ
β β
βΌ βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Vue 3 SPA (frontend/dist/) β
β β
β Built by Vite β app.iife.js + app.css β
β Inlined into single-page HTML for file:// protocol support β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Pinia Stores β β
β β β’ documentStore (document data, TOC, numbering) β β
β β β’ uiStore (sidebar, search, active section state) β β
β β β’ ebookStore (themes, settings) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β MirrorRenderer.vue + TextRenderer.vue β β
β β Renders DocbookMirror JSON: β β
β β ββ doc, section, chapter, appendix, part, reference, refentry β β
β β ββ paragraph, heading, code_block, list, table, blockquote β β
β β ββ image, admonition, footnote β β
β β ββ text nodes with marks (emphasis, code, link, xref, citation) β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β UI Shell β β
β β EbookContainer, AppSidebar, TocTreeItem, EbookTopBar, β β
β β BreadcrumbBar, SearchModal, SettingsPanel, LibraryApp β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Interactive HTML Reader β
β Inline (single .html), DOM (pre-rendered), Dist (directory), β
β Paged (split pages), Chunked (on-demand sections) β
β -- all driven by Format strategy classes β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββCLI Commands:
docbook build [INPUT] [-o out.html] β Builder β Format (inline|dom|dist|paged|chunked)
docbook build --demo β Demo from bundled sample
docbook library DIRECTORY/manifest β Multi-book library
docbook export INPUT [-o out.json] β DocbookMirror JSON
docbook validate INPUT β RELAX NG schema validationKey relationships:
- Lutaml::Model
-
The foundation β every Docbook::Elements::* class inherits from Lutaml::Model::Serializable, providing XMLβRuby object serialization.
- DocbookMirror
-
A ProseMirror-compatible intermediate JSON format. The Ruby Mirror::Transformer walks Docbook element objects and produces a {doc: {content: [nodes]}} tree with typed nodes and marks.
- Vue SPA
-
Renders DocbookMirror JSON via MirrorRenderer and TextRenderer components. The data is embedded as window.DOCBOOK_DATA.
- Builder/Formats
-
The output layer. Pipeline processes XML into a guide hash, then a Format strategy class (Inline, Dom, Dist, Paged, Chunked) packages it into the chosen output structure.
Bug reports and pull requests are welcome at https://github.com/metanorma/docbook.
Copyright Ribose. MIT License.