docbook 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/CLAUDE.md +19 -0
  4. data/CODE_OF_CONDUCT.md +10 -0
  5. data/README.adoc +335 -0
  6. data/Rakefile +12 -0
  7. data/docs/.lycheeignore +33 -0
  8. data/docs/Gemfile +10 -0
  9. data/docs/INDEX.adoc +67 -0
  10. data/docs/_config.yml +186 -0
  11. data/docs/advanced/element-classes.adoc +185 -0
  12. data/docs/advanced/frontend-customization.adoc +193 -0
  13. data/docs/advanced/index.adoc +14 -0
  14. data/docs/advanced/templates.adoc +123 -0
  15. data/docs/features/element-coverage.adoc +373 -0
  16. data/docs/features/html-output/data-model.adoc +285 -0
  17. data/docs/features/html-output/directory-mode.adoc +180 -0
  18. data/docs/features/html-output/index.adoc +90 -0
  19. data/docs/features/html-output/single-file-mode.adoc +125 -0
  20. data/docs/features/index-generation.adoc +197 -0
  21. data/docs/features/index.adoc +63 -0
  22. data/docs/features/numbering.adoc +183 -0
  23. data/docs/features/toc-generation.adoc +150 -0
  24. data/docs/features/xinclude/fragid-schemes.adoc +287 -0
  25. data/docs/features/xinclude/index.adoc +119 -0
  26. data/docs/features/xinclude/text-includes.adoc +123 -0
  27. data/docs/features/xinclude/xml-includes.adoc +167 -0
  28. data/docs/getting-started/index.adoc +50 -0
  29. data/docs/getting-started/installation.adoc +113 -0
  30. data/docs/getting-started/quick-start.adoc +161 -0
  31. data/docs/guides/converting-article.adoc +188 -0
  32. data/docs/guides/converting-book.adoc +192 -0
  33. data/docs/guides/index.adoc +12 -0
  34. data/docs/guides/roundtrip-testing.adoc +129 -0
  35. data/docs/interfaces/cli/format-command.adoc +109 -0
  36. data/docs/interfaces/cli/index.adoc +73 -0
  37. data/docs/interfaces/cli/roundtrip-command.adoc +125 -0
  38. data/docs/interfaces/cli/to-html-command.adoc +178 -0
  39. data/docs/interfaces/cli/validate-command.adoc +104 -0
  40. data/docs/interfaces/index.adoc +101 -0
  41. data/docs/interfaces/ruby-api/html-output.adoc +186 -0
  42. data/docs/interfaces/ruby-api/index.adoc +111 -0
  43. data/docs/interfaces/ruby-api/parsing.adoc +202 -0
  44. data/docs/interfaces/ruby-api/xinclude.adoc +162 -0
  45. data/docs/interfaces/ruby-api/xref-resolution.adoc +156 -0
  46. data/docs/lychee.toml +42 -0
  47. data/docs/reference/cli-options.adoc +155 -0
  48. data/docs/reference/content-block-types.adoc +243 -0
  49. data/docs/reference/glossary.adoc +119 -0
  50. data/docs/reference/index.adoc +12 -0
  51. data/docs/reference/supported-elements.adoc +749 -0
  52. data/docs/understanding/architecture.adoc +145 -0
  53. data/docs/understanding/content-pipeline.adoc +102 -0
  54. data/docs/understanding/data-models.adoc +156 -0
  55. data/docs/understanding/index.adoc +34 -0
  56. data/exe/docbook +7 -0
  57. data/frontend/dist/app.css +1 -0
  58. data/frontend/dist/app.iife.js +24 -0
  59. data/frontend/package-lock.json +1445 -0
  60. data/frontend/package.json +22 -0
  61. data/frontend/src/App.vue +230 -0
  62. data/frontend/src/app.ts +8 -0
  63. data/frontend/src/components/AppSidebar.vue +116 -0
  64. data/frontend/src/components/AppendixSection.vue +39 -0
  65. data/frontend/src/components/BlockRenderer.vue +358 -0
  66. data/frontend/src/components/ChapterSection.vue +32 -0
  67. data/frontend/src/components/ContentRenderer.vue +13 -0
  68. data/frontend/src/components/EbookContainer.vue +147 -0
  69. data/frontend/src/components/EbookTopBar.vue +116 -0
  70. data/frontend/src/components/PartSection.vue +44 -0
  71. data/frontend/src/components/ReferenceEntry.vue +80 -0
  72. data/frontend/src/components/SearchModal.vue +286 -0
  73. data/frontend/src/components/SectionContent.vue +31 -0
  74. data/frontend/src/components/SettingsPanel.vue +236 -0
  75. data/frontend/src/components/TocTreeItem.vue +135 -0
  76. data/frontend/src/composables/useEbookStore.ts +191 -0
  77. data/frontend/src/composables/useSearch.ts +249 -0
  78. data/frontend/src/env.d.ts +7 -0
  79. data/frontend/src/stores/documentStore.ts +221 -0
  80. data/frontend/src/stores/uiStore.ts +98 -0
  81. data/frontend/src/styles.css +253 -0
  82. data/frontend/tsconfig.json +24 -0
  83. data/frontend/tsconfig.node.json +11 -0
  84. data/frontend/vite.config.ts +30 -0
  85. data/lib/docbook/cli.rb +123 -0
  86. data/lib/docbook/document.rb +67 -0
  87. data/lib/docbook/elements/abbrev.rb +16 -0
  88. data/lib/docbook/elements/acknowledgements.rb +22 -0
  89. data/lib/docbook/elements/address.rb +18 -0
  90. data/lib/docbook/elements/alt.rb +16 -0
  91. data/lib/docbook/elements/annotation.rb +18 -0
  92. data/lib/docbook/elements/appendix.rb +34 -0
  93. data/lib/docbook/elements/article.rb +31 -0
  94. data/lib/docbook/elements/att.rb +15 -0
  95. data/lib/docbook/elements/attribution.rb +20 -0
  96. data/lib/docbook/elements/audioobject.rb +18 -0
  97. data/lib/docbook/elements/author.rb +18 -0
  98. data/lib/docbook/elements/bibliography.rb +24 -0
  99. data/lib/docbook/elements/bibliomixed.rb +40 -0
  100. data/lib/docbook/elements/biblioref.rb +20 -0
  101. data/lib/docbook/elements/blockquote.rb +26 -0
  102. data/lib/docbook/elements/book.rb +36 -0
  103. data/lib/docbook/elements/buildtarget.rb +16 -0
  104. data/lib/docbook/elements/callout.rb +22 -0
  105. data/lib/docbook/elements/calloutlist.rb +22 -0
  106. data/lib/docbook/elements/caution.rb +30 -0
  107. data/lib/docbook/elements/chapter.rb +62 -0
  108. data/lib/docbook/elements/citation.rb +16 -0
  109. data/lib/docbook/elements/citerefentry.rb +26 -0
  110. data/lib/docbook/elements/citetitle.rb +20 -0
  111. data/lib/docbook/elements/classname.rb +16 -0
  112. data/lib/docbook/elements/code.rb +16 -0
  113. data/lib/docbook/elements/colophon.rb +22 -0
  114. data/lib/docbook/elements/computeroutput.rb +18 -0
  115. data/lib/docbook/elements/copyright.rb +17 -0
  116. data/lib/docbook/elements/danger.rb +28 -0
  117. data/lib/docbook/elements/date.rb +16 -0
  118. data/lib/docbook/elements/dedication.rb +22 -0
  119. data/lib/docbook/elements/dir.rb +16 -0
  120. data/lib/docbook/elements/emphasis.rb +18 -0
  121. data/lib/docbook/elements/entry.rb +30 -0
  122. data/lib/docbook/elements/entrytbl.rb +22 -0
  123. data/lib/docbook/elements/equation.rb +26 -0
  124. data/lib/docbook/elements/example.rb +30 -0
  125. data/lib/docbook/elements/fieldsynopsis.rb +21 -0
  126. data/lib/docbook/elements/figure.rb +28 -0
  127. data/lib/docbook/elements/filename.rb +16 -0
  128. data/lib/docbook/elements/firstname.rb +16 -0
  129. data/lib/docbook/elements/firstterm.rb +18 -0
  130. data/lib/docbook/elements/footnote.rb +22 -0
  131. data/lib/docbook/elements/footnoteref.rb +21 -0
  132. data/lib/docbook/elements/foreignphrase.rb +18 -0
  133. data/lib/docbook/elements/formalpara.rb +20 -0
  134. data/lib/docbook/elements/function.rb +16 -0
  135. data/lib/docbook/elements/glossary.rb +24 -0
  136. data/lib/docbook/elements/glossdef.rb +18 -0
  137. data/lib/docbook/elements/glossentry.rb +26 -0
  138. data/lib/docbook/elements/glosssee.rb +18 -0
  139. data/lib/docbook/elements/glossseealso.rb +18 -0
  140. data/lib/docbook/elements/glossterm.rb +18 -0
  141. data/lib/docbook/elements/holder.rb +16 -0
  142. data/lib/docbook/elements/honorific.rb +16 -0
  143. data/lib/docbook/elements/imagedata.rb +29 -0
  144. data/lib/docbook/elements/imageobject.rb +22 -0
  145. data/lib/docbook/elements/important.rb +30 -0
  146. data/lib/docbook/elements/index.rb +26 -0
  147. data/lib/docbook/elements/indexdiv.rb +22 -0
  148. data/lib/docbook/elements/indexentry.rb +22 -0
  149. data/lib/docbook/elements/indexterm.rb +34 -0
  150. data/lib/docbook/elements/info.rb +25 -0
  151. data/lib/docbook/elements/informalexample.rb +24 -0
  152. data/lib/docbook/elements/informalfigure.rb +20 -0
  153. data/lib/docbook/elements/inlinemediaobject.rb +22 -0
  154. data/lib/docbook/elements/itemizedlist.rb +21 -0
  155. data/lib/docbook/elements/legalnotice.rb +22 -0
  156. data/lib/docbook/elements/link.rb +26 -0
  157. data/lib/docbook/elements/listitem.rb +32 -0
  158. data/lib/docbook/elements/literal.rb +16 -0
  159. data/lib/docbook/elements/literallayout.rb +22 -0
  160. data/lib/docbook/elements/mediaobject.rb +26 -0
  161. data/lib/docbook/elements/msg.rb +20 -0
  162. data/lib/docbook/elements/msgexplan.rb +22 -0
  163. data/lib/docbook/elements/msgset.rb +22 -0
  164. data/lib/docbook/elements/note.rb +30 -0
  165. data/lib/docbook/elements/orderedlist.rb +23 -0
  166. data/lib/docbook/elements/orgname.rb +16 -0
  167. data/lib/docbook/elements/para.rb +61 -0
  168. data/lib/docbook/elements/paragraph_like.rb +18 -0
  169. data/lib/docbook/elements/parameter.rb +16 -0
  170. data/lib/docbook/elements/part.rb +38 -0
  171. data/lib/docbook/elements/personname.rb +22 -0
  172. data/lib/docbook/elements/phrase.rb +20 -0
  173. data/lib/docbook/elements/preface.rb +58 -0
  174. data/lib/docbook/elements/primary.rb +16 -0
  175. data/lib/docbook/elements/procedure.rb +24 -0
  176. data/lib/docbook/elements/productname.rb +18 -0
  177. data/lib/docbook/elements/productnumber.rb +16 -0
  178. data/lib/docbook/elements/programlisting.rb +28 -0
  179. data/lib/docbook/elements/property.rb +16 -0
  180. data/lib/docbook/elements/pubdate.rb +16 -0
  181. data/lib/docbook/elements/publishername.rb +16 -0
  182. data/lib/docbook/elements/quotation.rb +24 -0
  183. data/lib/docbook/elements/quote.rb +18 -0
  184. data/lib/docbook/elements/refentry.rb +32 -0
  185. data/lib/docbook/elements/refentrytitle.rb +16 -0
  186. data/lib/docbook/elements/reference.rb +26 -0
  187. data/lib/docbook/elements/refmeta.rb +29 -0
  188. data/lib/docbook/elements/refmiscinfo.rb +16 -0
  189. data/lib/docbook/elements/refname.rb +16 -0
  190. data/lib/docbook/elements/refnamediv.rb +22 -0
  191. data/lib/docbook/elements/refpurpose.rb +16 -0
  192. data/lib/docbook/elements/refsect1.rb +22 -0
  193. data/lib/docbook/elements/refsect2.rb +22 -0
  194. data/lib/docbook/elements/refsect3.rb +22 -0
  195. data/lib/docbook/elements/refsection.rb +32 -0
  196. data/lib/docbook/elements/releaseinfo.rb +16 -0
  197. data/lib/docbook/elements/remark.rb +20 -0
  198. data/lib/docbook/elements/replaceable.rb +16 -0
  199. data/lib/docbook/elements/row.rb +15 -0
  200. data/lib/docbook/elements/screen.rb +28 -0
  201. data/lib/docbook/elements/secondary.rb +16 -0
  202. data/lib/docbook/elements/sect1.rb +26 -0
  203. data/lib/docbook/elements/sect2.rb +24 -0
  204. data/lib/docbook/elements/sect3.rb +24 -0
  205. data/lib/docbook/elements/sect4.rb +24 -0
  206. data/lib/docbook/elements/sect5.rb +22 -0
  207. data/lib/docbook/elements/section.rb +66 -0
  208. data/lib/docbook/elements/see.rb +16 -0
  209. data/lib/docbook/elements/seealso.rb +18 -0
  210. data/lib/docbook/elements/set.rb +26 -0
  211. data/lib/docbook/elements/setindex.rb +24 -0
  212. data/lib/docbook/elements/sidebar.rb +22 -0
  213. data/lib/docbook/elements/simplesect.rb +32 -0
  214. data/lib/docbook/elements/step.rb +26 -0
  215. data/lib/docbook/elements/substeps.rb +18 -0
  216. data/lib/docbook/elements/subtitle.rb +16 -0
  217. data/lib/docbook/elements/surname.rb +16 -0
  218. data/lib/docbook/elements/table.rb +24 -0
  219. data/lib/docbook/elements/tag.rb +20 -0
  220. data/lib/docbook/elements/tbody.rb +15 -0
  221. data/lib/docbook/elements/term.rb +37 -0
  222. data/lib/docbook/elements/tertiary.rb +16 -0
  223. data/lib/docbook/elements/textobject.rb +18 -0
  224. data/lib/docbook/elements/tfoot.rb +15 -0
  225. data/lib/docbook/elements/tgroup.rb +21 -0
  226. data/lib/docbook/elements/thead.rb +15 -0
  227. data/lib/docbook/elements/tip.rb +30 -0
  228. data/lib/docbook/elements/title.rb +16 -0
  229. data/lib/docbook/elements/toc.rb +24 -0
  230. data/lib/docbook/elements/tocdiv.rb +22 -0
  231. data/lib/docbook/elements/tocentry.rb +20 -0
  232. data/lib/docbook/elements/topic.rb +26 -0
  233. data/lib/docbook/elements/type.rb +16 -0
  234. data/lib/docbook/elements/uri.rb +16 -0
  235. data/lib/docbook/elements/userinput.rb +18 -0
  236. data/lib/docbook/elements/variable.rb +16 -0
  237. data/lib/docbook/elements/variablelist.rb +19 -0
  238. data/lib/docbook/elements/varlistentry.rb +17 -0
  239. data/lib/docbook/elements/version.rb +16 -0
  240. data/lib/docbook/elements/videoobject.rb +18 -0
  241. data/lib/docbook/elements/warning.rb +30 -0
  242. data/lib/docbook/elements/xref.rb +18 -0
  243. data/lib/docbook/elements/year.rb +16 -0
  244. data/lib/docbook/elements.rb +204 -0
  245. data/lib/docbook/models/document_metadata.rb +30 -0
  246. data/lib/docbook/models/document_root.rb +33 -0
  247. data/lib/docbook/models/index_entry.rb +28 -0
  248. data/lib/docbook/models/reading_position.rb +22 -0
  249. data/lib/docbook/models/section_number.rb +18 -0
  250. data/lib/docbook/models/section_root.rb +29 -0
  251. data/lib/docbook/models/toc_node.rb +24 -0
  252. data/lib/docbook/models.rb +16 -0
  253. data/lib/docbook/output/data.rb +196 -0
  254. data/lib/docbook/output/html.rb +1450 -0
  255. data/lib/docbook/output/index_generator.rb +281 -0
  256. data/lib/docbook/output.rb +8 -0
  257. data/lib/docbook/services/document_builder.rb +258 -0
  258. data/lib/docbook/services/element_to_hash.rb +287 -0
  259. data/lib/docbook/services/index_generator.rb +134 -0
  260. data/lib/docbook/services/numbering_service.rb +186 -0
  261. data/lib/docbook/services/toc_generator.rb +138 -0
  262. data/lib/docbook/services.rb +14 -0
  263. data/lib/docbook/templates/document.html.liquid +20 -0
  264. data/lib/docbook/templates/partials/_head.liquid +39 -0
  265. data/lib/docbook/templates/partials/_scripts.liquid +10 -0
  266. data/lib/docbook/version.rb +5 -0
  267. data/lib/docbook/xinclude_resolver.rb +217 -0
  268. data/lib/docbook/xref_resolver.rb +78 -0
  269. data/lib/docbook.rb +17 -0
  270. data/sig/docbook.rbs +4 -0
  271. metadata +385 -0
@@ -0,0 +1,119 @@
1
+ ---
2
+ layout: default
3
+ title: XInclude Resolution
4
+ parent: Features
5
+ nav_order: 2
6
+ has_children: true
7
+ ---
8
+
9
+ # XInclude Resolution
10
+
11
+ The DocBook gem provides custom XInclude resolution for composing documents from multiple XML files. It supports the standard XInclude namespace (`http://www.w3.org/2001/XInclude`) with both XML and text parsing modes, plus advanced text filtering via `fragid` schemes.
12
+
13
+ ## Why a Custom Resolver?
14
+
15
+ The gem implements its own XInclude resolution rather than using Nokogiri's built-in `do_xinclude`. This provides:
16
+
17
+ - **Iterative resolution** -- Handles nested includes (file A includes file B which includes file C) by re-scanning the document after each resolution
18
+ - **fragid support** -- Text includes support three filtering schemes (`search=`, `line=`, `char=`) for extracting portions of a file
19
+ - **Robust error handling** -- Failed includes are silently skipped, allowing partial document builds
20
+
21
+ ## Namespace
22
+
23
+ XInclude elements use the standard namespace:
24
+
25
+ [source,xml]
26
+ ----
27
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
28
+ <chapter>
29
+ <xi:include href="intro.xml"/>
30
+ </chapter>
31
+ </book>
32
+ ----
33
+
34
+ The resolver finds `xi:include` elements using XPath:
35
+
36
+ [source,ruby]
37
+ ----
38
+ XINCLUDE_NS = "http://www.w3.org/2001/XInclude"
39
+ includes = doc.xpath("//xi:include", "xi" => XINCLUDE_NS)
40
+ ----
41
+
42
+ ## Iterative Resolution
43
+
44
+ The resolver processes includes iteratively rather than recursively. After each include is resolved, the document is re-scanned for new `xi:include` elements:
45
+
46
+ [source,ruby]
47
+ ----
48
+ def self.resolve(doc)
49
+ loop do
50
+ includes = doc.xpath("//xi:include", "xi" => XINCLUDE_NS)
51
+ break if includes.empty?
52
+
53
+ resolved_any = false
54
+ includes.each do |inc|
55
+ # ... resolve each include ...
56
+ resolved_any = true
57
+ break # re-scan after each resolve (tree changes)
58
+ end
59
+ break unless resolved_any
60
+ end
61
+ doc
62
+ end
63
+ ----
64
+
65
+ This approach handles:
66
+
67
+ - **Nested includes** -- A resolved file may contain its own `xi:include` elements
68
+ - **Self-referential text includes** -- A file can include portions of itself using `fragid`
69
+ - **Document tree mutations** -- The break-and-rescan pattern avoids stale XPath results
70
+
71
+ ## Parse Modes
72
+
73
+ Two parse modes are supported, controlled by the `parse` attribute on `xi:include`:
74
+
75
+ [cols="1,3,3"]
76
+ |===
77
+ | Mode | Attribute | Description
78
+
79
+ | XML | `parse="xml"` (default) | Reads the referenced file, parses it as XML, and replaces the `xi:include` element with the root element of the included document
80
+ | Text | `parse="text"` | Reads the referenced file as plain text and replaces the `xi:include` element with a text node
81
+ |===
82
+
83
+ ## Base Path Resolution
84
+
85
+ Include paths are resolved relative to the including document's URL. When using `resolve_string`, the base path is set from the input file:
86
+
87
+ [source,ruby]
88
+ ----
89
+ def self.resolve_string(xml_string, base_path: nil)
90
+ file_uri = "file://#{File.expand_path(base_path)}"
91
+ doc = Nokogiri::XML(xml_string, file_uri)
92
+ resolve(doc)
93
+ end
94
+ ----
95
+
96
+ ## CLI Integration
97
+
98
+ XInclude resolution is enabled by default in the `to-html` command and disabled by default in the `format` command:
99
+
100
+ [source,bash]
101
+ ----
102
+ # XInclude enabled (default for to-html)
103
+ docbook to-html book.xml -o output.html
104
+
105
+ # Explicitly disable XInclude
106
+ docbook to-html book.xml -o output.html --no-xinclude
107
+
108
+ # XInclude disabled (default for format)
109
+ docbook format book.xml
110
+
111
+ # Enable XInclude for format
112
+ docbook format book.xml --xinclude
113
+ ----
114
+
115
+ ## Child Pages
116
+
117
+ - <<xml-includes,XML Includes>> -- Standard XML inclusion with namespace handling
118
+ - <<text-includes,Text Includes>> -- Plain text inclusion for source code and verbatim content
119
+ - <<fragid-schemes,fragid Schemes>> -- Text filtering with `search=`, `line=`, and `char=` schemes
@@ -0,0 +1,123 @@
1
+ ---
2
+ layout: default
3
+ title: Text Includes
4
+ parent: XInclude Resolution
5
+ grand_parent: Features
6
+ nav_order: 2
7
+ ---
8
+
9
+ # Text Includes
10
+
11
+ Text includes (`parse="text"`) read the referenced file as plain text and insert its content as a text node. This is the standard way to include source code, configuration files, or other verbatim text content in DocBook documents.
12
+
13
+ ## Basic Usage
14
+
15
+ [source,xml]
16
+ ----
17
+ <chapter xmlns:xi="http://www.w3.org/2001/XInclude">
18
+ <title>Installation</title>
19
+
20
+ <para>Run the following command to install the gem:</para>
21
+
22
+ <screen><xi:include href="examples/install.sh" parse="text"/></screen>
23
+
24
+ <para>Then create a configuration file:</para>
25
+
26
+ <programlisting language="yaml"><xi:include href="examples/config.yaml" parse="text"/></programlisting>
27
+ </chapter>
28
+ ----
29
+
30
+ The file content is inserted verbatim as a text node, replacing the `xi:include` element. No XML parsing is performed on the included content.
31
+
32
+ ## How It Works
33
+
34
+ [source,ruby]
35
+ ----
36
+ def self.resolve_text_include(doc, inc, file_path, fragid)
37
+ content = File.read(file_path)
38
+ if fragid && !fragid.empty?
39
+ filtered = apply_fragid(content, fragid)
40
+ content = filtered if filtered
41
+ end
42
+ text_node = doc.create_text_node(content)
43
+ inc.replace(text_node)
44
+ end
45
+ ----
46
+
47
+ The process is straightforward:
48
+
49
+ . **Read the file** -- The file is read as a plain string with `File.read`
50
+ . **Apply fragid filter** -- If a `fragid` attribute is present, the content is filtered (see <<fragid-schemes,fragid Schemes>>)
51
+ . **Create text node** -- The content is wrapped in a Nokogiri text node
52
+ . **Replace the include** -- The `xi:include` element is replaced with the text node
53
+
54
+ ## Without fragid
55
+
56
+ When no `fragid` attribute is present, the entire file content is included:
57
+
58
+ [source,xml]
59
+ ----
60
+ <!-- Include an entire source file -->
61
+ <programlisting language="ruby"><xi:include href="lib/docbook.rb" parse="text"/></programlisting>
62
+ ----
63
+
64
+ [source,xml]
65
+ ----
66
+ <!-- Include a shell script -->
67
+ <screen><xi:include href="scripts/setup.sh" parse="text"/></screen>
68
+ ----
69
+
70
+ [source,xml]
71
+ ----
72
+ <!-- Include a configuration file -->
73
+ <programlisting language="json"><xi:include href="config.json" parse="text"/></programlisting>
74
+ ----
75
+
76
+ ## Common Use Cases
77
+
78
+ ### Source Code Listings
79
+
80
+ Text includes are most commonly used to embed source code files directly in documentation, ensuring the documented code is always synchronized with the actual codebase:
81
+
82
+ [source,xml]
83
+ ----
84
+ <section>
85
+ <title>The Html Output Class</title>
86
+ <para>The main output class handles HTML generation:</para>
87
+ <programlisting language="ruby"><xi:include href="lib/docbook/output/html.rb" parse="text"/></programlisting>
88
+ </section>
89
+ ----
90
+
91
+ ### Configuration Examples
92
+
93
+ [source,xml]
94
+ ----
95
+ <section>
96
+ <title>Default Configuration</title>
97
+ <programlisting language="yaml"><xi:include href="config/default.yaml" parse="text"/></programlisting>
98
+ </section>
99
+ ----
100
+
101
+ ### Log Output and Results
102
+
103
+ [source,xml]
104
+ ----
105
+ <section>
106
+ <title>Expected Output</title>
107
+ <screen><xi:include href="test/fixtures/expected-output.txt" parse="text"/></screen>
108
+ </section>
109
+ ----
110
+
111
+ ## Combined with fragid
112
+
113
+ Text includes become significantly more powerful when combined with the `fragid` attribute, which allows extracting specific portions of a file rather than the entire content. This is particularly useful for:
114
+
115
+ - Extracting specific functions from source files
116
+ - Including only relevant lines from large files
117
+ - Showing a specific section between two markers
118
+
119
+ See <<fragid-schemes,fragid Schemes>> for detailed documentation of the three filtering schemes:
120
+
121
+ - `search=` -- Pattern-based extraction (literal or regex)
122
+ - `line=` -- Line number range extraction (RFC 5147)
123
+ - `char=` -- Character offset extraction (RFC 5147)
@@ -0,0 +1,167 @@
1
+ ---
2
+ layout: default
3
+ title: XML Includes
4
+ parent: XInclude Resolution
5
+ grand_parent: Features
6
+ nav_order: 1
7
+ ---
8
+
9
+ # XML Includes
10
+
11
+ XML includes (`parse="xml"`) are the default XInclude mode. The referenced file is read, parsed as XML, and its root element replaces the `xi:include` element in the including document.
12
+
13
+ ## Basic Usage
14
+
15
+ The simplest form includes an entire XML file:
16
+
17
+ [source,xml]
18
+ ----
19
+ <!-- book.xml -->
20
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
21
+ <title>My Book</title>
22
+ <xi:include href="chapters/introduction.xml"/>
23
+ <xi:include href="chapters/advanced.xml"/>
24
+ </book>
25
+ ----
26
+
27
+ [source,xml]
28
+ ----
29
+ <!-- chapters/introduction.xml -->
30
+ <chapter xml:id="intro">
31
+ <title>Introduction</title>
32
+ <para>This is the introduction chapter.</para>
33
+ </chapter>
34
+ ----
35
+
36
+ After resolution, the `xi:include` element is replaced with the root `<chapter>` element:
37
+
38
+ [source,xml]
39
+ ----
40
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
41
+ <title>My Book</title>
42
+ <chapter xml:id="intro">
43
+ <title>Introduction</title>
44
+ <para>This is the introduction chapter.</para>
45
+ </chapter>
46
+ <xi:include href="chapters/advanced.xml"/>
47
+ </book>
48
+ ----
49
+
50
+ Note that only the first include is resolved per iteration. The document is re-scanned and the second include is resolved in the next pass.
51
+
52
+ ## How It Works
53
+
54
+ The resolution process:
55
+
56
+ . **Read the file** -- The referenced file is read from disk
57
+ . **Parse as XML** -- The file content is parsed with Nokogiri, using the file's full path as the base URL
58
+ . **Handle namespaces** -- If the included root element has a namespace, it is registered on the main document's root element if not already present
59
+ . **Replace the include** -- The `xi:include` element is replaced with the root element of the included document
60
+
61
+ [source,ruby]
62
+ ----
63
+ def self.resolve_xml_include(doc, inc, file_path)
64
+ included_xml = File.read(file_path)
65
+ included_doc = Nokogiri::XML(included_xml, "file://#{File.expand_path(file_path)}")
66
+
67
+ root = included_doc.root
68
+ # Ensure namespace is declared in target document
69
+ if root.namespace
70
+ ns = root.namespace
71
+ existing = doc.root.namespace_definitions.find { |n| n.href == ns.href }
72
+ doc.root.add_namespace_definition(ns.prefix, ns.href) unless existing
73
+ end
74
+
75
+ # Replace the xi:include with the root element itself
76
+ inc.replace(root.dup)
77
+ end
78
+ ----
79
+
80
+ ## Namespace Handling
81
+
82
+ When the included document uses namespaces (e.g., DocBook namespace `xmlns:db="http://docbook.org/ns/docbook"`), the resolver ensures the namespace is registered on the target document's root element. This prevents namespace conflicts and ensures the merged document is well-formed.
83
+
84
+ ## Base Path Resolution
85
+
86
+ File paths in `href` attributes are resolved relative to the including document's location:
87
+
88
+ [source,xml]
89
+ ----
90
+ <!-- /project/book.xml -->
91
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
92
+ <!-- Resolves to /project/chapters/ch01.xml -->
93
+ <xi:include href="chapters/ch01.xml"/>
94
+
95
+ <!-- Resolves to /project/shared/legal.xml -->
96
+ <xi:include href="shared/legal.xml"/>
97
+ </book>
98
+ ----
99
+
100
+ The base path is extracted from the document's URL:
101
+
102
+ [source,ruby]
103
+ ----
104
+ def self.base_dir_for(document)
105
+ url = document.url
106
+ return nil unless url
107
+ File.dirname(url.sub(%r{^file://}, ""))
108
+ end
109
+ ----
110
+
111
+ ## Nested Includes
112
+
113
+ Because the resolver works iteratively, nested includes are handled automatically. When a file is included that itself contains `xi:include` elements, those are resolved in subsequent iterations:
114
+
115
+ [source,xml]
116
+ ----
117
+ <!-- book.xml -->
118
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
119
+ <xi:include href="part1.xml"/>
120
+ </book>
121
+
122
+ <!-- part1.xml -->
123
+ <part>
124
+ <title>Part I</title>
125
+ <xi:include href="chapters/ch01.xml"/>
126
+ <xi:include href="chapters/ch02.xml"/>
127
+ </part>
128
+
129
+ <!-- chapters/ch01.xml -->
130
+ <chapter xml:id="ch01">
131
+ <title>Chapter 1</title>
132
+ <para>Content here.</para>
133
+ </chapter>
134
+ ----
135
+
136
+ The resolution order is:
137
+
138
+ . `book.xml` includes `part1.xml` -- `xi:include` replaced with `<part>` element
139
+ . Re-scan finds two new `xi:include` elements inside the included `<part>`
140
+ . `part1.xml`'s first include (`ch01.xml`) is resolved
141
+ . Re-scan finds one remaining `xi:include`
142
+ . `part1.xml`'s second include (`ch02.xml`) is resolved
143
+ . Re-scan finds no more `xi:include` elements -- done
144
+
145
+ ## Common Patterns
146
+
147
+ **Book with per-chapter files:**
148
+
149
+ [source,xml]
150
+ ----
151
+ <book xmlns:xi="http://www.w3.org/2001/XInclude">
152
+ <xi:include href="frontmatter.xml"/>
153
+ <xi:include href="part1.xml"/>
154
+ <xi:include href="part2.xml"/>
155
+ <xi:include href="appendices.xml"/>
156
+ </book>
157
+ ----
158
+
159
+ **Shared boilerplate:**
160
+
161
+ [source,xml]
162
+ ----
163
+ <!-- Including a common legal notice in multiple documents -->
164
+ <preface>
165
+ <xi:include href="../shared/legal-notice.xml"/>
166
+ </preface>
167
+ ----
@@ -0,0 +1,50 @@
1
+ ---
2
+ layout: default
3
+ title: Getting Started
4
+ nav_order: 2
5
+ has_children: true
6
+ ---
7
+
8
+ == Getting Started
9
+
10
+ Welcome to the *Metanorma DocBook* gem -- a Ruby library for parsing *DocBook 5 XML* documents and converting them to rich, interactive HTML output.
11
+
12
+ DocBook 5 is an OASIS standard XML vocabulary designed for marking up technical documentation, including books, articles, reference pages, and more. The `docbook` gem provides a complete toolkit for working with DocBook XML files: parsing them into Ruby object models, resolving cross-references and XIncludes, and producing self-contained HTML documents or directory-based output ready for deployment.
13
+
14
+ The gem is built on top of https://github.com/lutaml/lutaml-model[`lutaml-model`], which provides a type-safe, declarative way to define XML-to-Ruby mappings. Every DocBook element -- from `<book>` down to inline elements like `<emphasis>` and `<xref>` -- is represented as a first-class Ruby object with typed attributes.
15
+
16
+ === Prerequisites
17
+
18
+ Before you begin, make sure you have the following:
19
+
20
+ * *Ruby >= 3.2* installed on your system
21
+ * *Bundler* (optional, but recommended for project integration)
22
+ * Basic familiarity with XML and the DocBook 5 vocabulary
23
+
24
+ === What You Will Learn
25
+
26
+ This section covers everything you need to start using the gem:
27
+
28
+ * *<<installation,Installation>>* -- Install the gem via RubyGems or Bundler, and verify your setup.
29
+ * *<<quick-start,Quick Start>>* -- Run your first validation, format, and HTML conversion from the command line.
30
+
31
+ === About DocBook 5 XML
32
+
33
+ DocBook 5 is a semantic markup language for technical documentation. Unlike presentation-oriented formats, DocBook describes the *structure* and *meaning* of your content. A DocBook `<book>` contains chapters, sections, paragraphs, code listings, figures, tables, cross-references, and much more. This separation of content from presentation makes DocBook ideal for single-source publishing pipelines.
34
+
35
+ The `docbook` gem supports 39 root element types, including the most commonly used: `<article>`, `<book>`, `<chapter>`, `<appendix>`, `<section>`, `<preface>`, `<part>`, and `<reference>`.
36
+
37
+ === What the Gem Provides
38
+
39
+ [cols="2,5"]
40
+ |===
41
+ | Feature | Description
42
+
43
+ | *CLI* | A Thor-based command-line interface with four commands: `validate`, `format`, `to-html`, and `roundtrip`.
44
+ | *Ruby API* | Programmatic access to parsing, XInclude resolution, cross-reference resolution, and HTML generation.
45
+ | *HTML Output* | Two output modes: a self-contained single HTML file (with embedded Base64 images) and a directory mode (with a Vue.js-powered reading experience).
46
+ | *XInclude Support* | Full resolution of XInclude elements including nested includes, text includes, and `text+fragid` extensions.
47
+ | *Cross-Reference Resolution* | Automatic resolution of `xml:id` references to section titles and other targets.
48
+ |===
49
+
50
+ Dive into <<installation>> to get the gem installed, then head to <<quick-start>> for hands-on examples.
@@ -0,0 +1,113 @@
1
+ ---
2
+ layout: default
3
+ title: Installation
4
+ parent: Getting Started
5
+ nav_order: 1
6
+ ---
7
+
8
+ == Installation
9
+
10
+ Install the Metanorma DocBook gem to start parsing and converting DocBook XML files.
11
+
12
+ === Requirements
13
+
14
+ The gem has the following runtime requirements:
15
+
16
+ [cols="1,4"]
17
+ |===
18
+ | Requirement | Details
19
+
20
+ | *Ruby* | Version 3.2 or later (`>= 3.2.0`)
21
+ | *Nokogiri* | XML parsing library (installed automatically as a dependency)
22
+ | *lutaml-model* | Declarative XML-to-Ruby object mapping (`~> 0.8.0`, installed automatically)
23
+ | *Thor* | CLI framework (installed automatically)
24
+ | *Liquid* | Template engine for HTML generation (`~> 5.0`, installed automatically)
25
+ | *Marcel* | MIME type detection for image embedding (installed automatically)
26
+ |===
27
+
28
+ === Install with RubyGems
29
+
30
+ The simplest way to install the gem is directly from the command line:
31
+
32
+ [source,bash]
33
+ ----
34
+ $ gem install docbook
35
+ ----
36
+
37
+ This installs the `docbook` command-line tool and all required dependencies.
38
+
39
+ === Install with Bundler
40
+
41
+ For Ruby projects, add the gem to your `Gemfile`:
42
+
43
+ [source,ruby]
44
+ ----
45
+ # Gemfile
46
+ gem "docbook"
47
+ ----
48
+
49
+ Then run Bundler to install:
50
+
51
+ [source,bash]
52
+ ----
53
+ $ bundle install
54
+ ----
55
+
56
+ If you want to track the latest development version from the repository:
57
+
58
+ [source,ruby]
59
+ ----
60
+ # Gemfile
61
+ gem "docbook", github: "metanorma/docbook", branch: "main"
62
+ ----
63
+
64
+ === Verify the Installation
65
+
66
+ After installing, confirm that the `docbook` CLI is available:
67
+
68
+ [source,bash]
69
+ ----
70
+ $ docbook --help
71
+ ----
72
+
73
+ You should see output listing the available commands:
74
+
75
+ [source]
76
+ ----
77
+ Commands:
78
+ docbook format INPUT # Format/prettify DocBook XML
79
+ docbook help [COMMAND] # Describe available commands or one specific command
80
+ docbook roundtrip INPUT... # Round-trip test DocBook XML files
81
+ docbook to-html INPUT # Convert DocBook XML to HTML
82
+ docbook validate INPUT # Validate DocBook XML well-formedness
83
+ ----
84
+
85
+ You can also check the gem version from Ruby:
86
+
87
+ [source,ruby]
88
+ ----
89
+ require "docbook"
90
+ puts Docbook::VERSION # => "0.1.0"
91
+ ----
92
+
93
+ === Building from Source
94
+
95
+ To build and install from the source repository:
96
+
97
+ [source,bash]
98
+ ----
99
+ $ git clone https://github.com/metanorma/docbook.git
100
+ $ cd docbook
101
+ $ bundle install
102
+ $ rake install
103
+ ----
104
+
105
+ This builds the gem from the current source and installs it locally. The `docbook` executable will be available in your path.
106
+
107
+ === Troubleshooting
108
+
109
+ *Nokogiri compilation errors:* If Nokogiri fails to build native extensions, ensure you have the required system libraries. On macOS, `xcode-select --install` usually resolves this. On Ubuntu/Debian, install `libxml2-dev` and `libxslt1-dev`.
110
+
111
+ *Ruby version mismatch:* The gem requires Ruby 3.2 or later. Check your version with `ruby --version`. Use a version manager like `rbenv` or `rvm` if you need to install a newer Ruby.
112
+
113
+ Once installed, proceed to the <<quick-start>> page to start using the gem.