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,253 @@
1
+ /* Tailwind-like utility classes and custom styles */
2
+ /* Google Fonts loaded via <link> in HTML for file:// compatibility */
3
+
4
+ * {
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ html {
9
+ scroll-behavior: smooth;
10
+ }
11
+
12
+ body {
13
+ font-family: 'Inter', system-ui, sans-serif;
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ }
17
+
18
+ body.font-serif {
19
+ font-family: 'Merriweather', Georgia, serif;
20
+ }
21
+
22
+ body.font-sans {
23
+ font-family: 'Inter', system-ui, sans-serif;
24
+ }
25
+
26
+ .font-mono {
27
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
28
+ }
29
+
30
+ /* Dark mode */
31
+ .dark {
32
+ color-scheme: dark;
33
+ }
34
+
35
+ /* Print styles */
36
+ @media print {
37
+ .lg\:translate-x-0, #sidebar, #sidebar-toggle, .sticky {
38
+ display: none !important;
39
+ }
40
+ }
41
+
42
+ /* TOC active highlighting */
43
+ .toc-active {
44
+ color: #2563eb;
45
+ background: #dbeafe;
46
+ }
47
+
48
+ .dark .toc-active {
49
+ color: #60a5fa;
50
+ background: #1e3a5f;
51
+ }
52
+
53
+ /* Bibliography styling */
54
+ .db-bibentry {
55
+ padding-left: 2em;
56
+ text-indent: -2em;
57
+ margin-bottom: 0.5em;
58
+ }
59
+
60
+ /* Changelog release styling */
61
+ .db-changelog-release {
62
+ border-left: 3px solid #60a5fa;
63
+ padding-left: 1rem;
64
+ margin: 1.5rem 0;
65
+ }
66
+
67
+ .dark .db-changelog-release {
68
+ border-left-color: #3b82f6;
69
+ }
70
+
71
+ /* Appendix styling */
72
+ .db-appendix-wrap {
73
+ border-left: 4px solid #8b5cf6;
74
+ padding-left: 1rem;
75
+ margin-left: -1rem;
76
+ }
77
+
78
+ .dark .db-appendix-wrap {
79
+ border-left-color: #a78bfa;
80
+ }
81
+
82
+ /* Preface styling */
83
+ .db-preface-wrap {
84
+ border-left: 4px solid #22c55e;
85
+ padding-left: 1rem;
86
+ margin-left: -1rem;
87
+ }
88
+
89
+ .dark .db-preface-wrap {
90
+ border-left-color: #16a34a;
91
+ }
92
+
93
+ /* Search highlight */
94
+ mark.bg-yellow-200,
95
+ mark.bg-yellow-600 {
96
+ padding: 0 2px;
97
+ border-radius: 2px;
98
+ }
99
+
100
+ /* Alpine.js cloak */
101
+ [x-cloak] {
102
+ display: none !important;
103
+ }
104
+
105
+ /* Scrollbar styling */
106
+ ::-webkit-scrollbar {
107
+ width: 8px;
108
+ height: 8px;
109
+ }
110
+
111
+ ::-webkit-scrollbar-track {
112
+ background: transparent;
113
+ }
114
+
115
+ ::-webkit-scrollbar-thumb {
116
+ background: #cbd5e1;
117
+ border-radius: 4px;
118
+ }
119
+
120
+ .dark ::-webkit-scrollbar-thumb {
121
+ background: #4b5563;
122
+ }
123
+
124
+ ::-webkit-scrollbar-thumb:hover {
125
+ background: #94a3b8;
126
+ }
127
+
128
+ .dark ::-webkit-scrollbar-thumb:hover {
129
+ background: #6b7280;
130
+ }
131
+
132
+ /* Content typography */
133
+ .db-content h1 {
134
+ font-size: 1.875rem;
135
+ font-weight: 700;
136
+ margin-bottom: 1rem;
137
+ }
138
+
139
+ .db-content h2 {
140
+ font-size: 1.25rem;
141
+ font-weight: 600;
142
+ margin-top: 2rem;
143
+ margin-bottom: 0.75rem;
144
+ }
145
+
146
+ .db-content h3 {
147
+ font-size: 1.125rem;
148
+ font-weight: 600;
149
+ margin-top: 1.5rem;
150
+ margin-bottom: 0.5rem;
151
+ }
152
+
153
+ .db-content p {
154
+ margin-bottom: 1rem;
155
+ line-height: 1.75;
156
+ }
157
+
158
+ .db-content ul,
159
+ .db-content ol {
160
+ margin-bottom: 1rem;
161
+ padding-left: 1.5rem;
162
+ }
163
+
164
+ .db-content li {
165
+ margin-bottom: 0.25rem;
166
+ line-height: 1.6;
167
+ }
168
+
169
+ .db-content code {
170
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
171
+ font-size: 0.875em;
172
+ background: #f1f5f9;
173
+ padding: 0.125rem 0.375rem;
174
+ border-radius: 0.25rem;
175
+ }
176
+
177
+ .dark .db-content code {
178
+ background: #374151;
179
+ }
180
+
181
+ .db-content pre {
182
+ font-family: 'JetBrains Mono', ui-monospace, monospace;
183
+ font-size: 0.875rem;
184
+ background: #f1f5f9;
185
+ padding: 1rem;
186
+ border-radius: 0.5rem;
187
+ overflow-x: auto;
188
+ margin-bottom: 1rem;
189
+ }
190
+
191
+ .dark .db-content pre {
192
+ background: #1f2937;
193
+ }
194
+
195
+ .db-content a {
196
+ color: #2563eb;
197
+ text-decoration: underline;
198
+ }
199
+
200
+ .dark .db-content a {
201
+ color: #60a5fa;
202
+ }
203
+
204
+ .db-content img {
205
+ max-width: 100%;
206
+ height: auto;
207
+ border-radius: 0.5rem;
208
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
209
+ }
210
+
211
+ .dark .db-content img {
212
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
213
+ }
214
+
215
+ .db-content blockquote {
216
+ border-left: 4px solid #d1d5db;
217
+ padding-left: 1rem;
218
+ margin: 1rem 0;
219
+ font-style: italic;
220
+ color: #6b7280;
221
+ }
222
+
223
+ .dark .db-content blockquote {
224
+ border-left-color: #4b5563;
225
+ color: #9ca3af;
226
+ }
227
+
228
+ .db-content table {
229
+ width: 100%;
230
+ border-collapse: collapse;
231
+ margin-bottom: 1rem;
232
+ }
233
+
234
+ .db-content th,
235
+ .db-content td {
236
+ border: 1px solid #e5e7eb;
237
+ padding: 0.5rem;
238
+ text-align: left;
239
+ }
240
+
241
+ .dark .db-content th,
242
+ .dark .db-content td {
243
+ border-color: #374151;
244
+ }
245
+
246
+ .db-content th {
247
+ background: #f9fafb;
248
+ font-weight: 600;
249
+ }
250
+
251
+ .dark .db-content th {
252
+ background: #1f2937;
253
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "preserve",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "paths": {
19
+ "@/*": ["./src/*"]
20
+ }
21
+ },
22
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
23
+ "references": [{ "path": "./tsconfig.node.json" }]
24
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true,
8
+ "strict": true
9
+ },
10
+ "include": ["vite.config.ts"]
11
+ }
@@ -0,0 +1,30 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+ import { resolve } from 'path'
4
+
5
+ export default defineConfig({
6
+ plugins: [vue()],
7
+ build: {
8
+ lib: {
9
+ entry: resolve(__dirname, 'src/app.ts'),
10
+ name: 'DocbookSpa',
11
+ fileName: 'app',
12
+ formats: ['iife']
13
+ },
14
+ rollupOptions: {
15
+ output: {
16
+ inlineDynamicImports: true,
17
+ assetFileNames: 'app.[ext]'
18
+ }
19
+ },
20
+ minify: 'esbuild'
21
+ },
22
+ define: {
23
+ 'process.env.NODE_ENV': JSON.stringify('production')
24
+ },
25
+ resolve: {
26
+ alias: {
27
+ '@': resolve(__dirname, 'src')
28
+ }
29
+ }
30
+ })
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require "nokogiri"
5
+ require "fileutils"
6
+
7
+ module Docbook
8
+ class CLI < Thor
9
+ desc "format INPUT", "Format/prettify DocBook XML"
10
+ option :output, aliases: "-o", desc: "Output file (default: stdout)"
11
+ option :xinclude, type: :boolean, default: false, desc: "Resolve XIncludes before processing"
12
+ def format(input)
13
+ xml_string = read_input(input, options[:xinclude])
14
+ parsed = parse_input(xml_string)
15
+ output = parsed.to_xml(pretty: true, declaration: true, encoding: "utf-8")
16
+ write_output(output, options[:output], :single_file)
17
+ end
18
+
19
+ desc "validate INPUT", "Validate DocBook XML well-formedness"
20
+ def validate(input)
21
+ xml_string = File.read(input)
22
+ doc = Nokogiri::XML(xml_string)
23
+ if doc.errors.empty?
24
+ puts "#{input}: valid"
25
+ else
26
+ doc.errors.each { |e| warn "#{input}: #{e}" }
27
+ exit 1
28
+ end
29
+ end
30
+
31
+ desc "to-html INPUT", "Convert DocBook XML to HTML"
32
+ option :output, aliases: "-o", desc: "Output file or directory"
33
+ option :xinclude, type: :boolean, default: true, desc: "Resolve XIncludes before processing"
34
+ option :output_type, default: :single_file, desc: "Output type: single_file or directory"
35
+ def to_html(input)
36
+ xml_string = read_input(input, options[:xinclude])
37
+ parsed = parse_input(xml_string)
38
+ xref_resolver = Docbook::XrefResolver.new(parsed).resolve!
39
+ base_path = File.dirname(File.expand_path(input))
40
+ output_mode = options[:output_type].to_sym
41
+ output_path = if output_mode == :directory && options[:output]
42
+ File.expand_path(options[:output])
43
+ elsif output_mode == :single_file && options[:output]
44
+ File.dirname(File.expand_path(options[:output]))
45
+ end
46
+
47
+ html = Docbook::Output::Html.new(
48
+ parsed,
49
+ xref_resolver: xref_resolver,
50
+ output_mode: output_mode,
51
+ base_path: base_path,
52
+ output_path: output_path
53
+ ).to_html
54
+
55
+ write_output(html, options[:output], output_mode)
56
+ end
57
+
58
+ desc "roundtrip INPUT...", "Round-trip test DocBook XML files"
59
+ def roundtrip(*inputs)
60
+ failures = 0
61
+ inputs.each do |input|
62
+ xml_string = File.read(input)
63
+ begin
64
+ parsed = parse_input(xml_string)
65
+ output = parsed.to_xml(declaration: true, encoding: "utf-8")
66
+ reparsed = parse_input(output)
67
+ puts "#{input}: OK"
68
+ rescue StandardError => e
69
+ warn "#{input}: FAIL - #{e.message}"
70
+ failures += 1
71
+ end
72
+ end
73
+ warn "#{inputs.size} files, #{failures} failures"
74
+ exit 1 if failures > 0
75
+ end
76
+
77
+ def self.exit_on_failure?
78
+ true
79
+ end
80
+
81
+ private
82
+
83
+ FRONTEND_ROOT = File.expand_path("../../frontend/dist", __dir__)
84
+
85
+ def read_input(input, resolve_xinclude = false)
86
+ xml_string = File.read(input)
87
+ if resolve_xinclude
88
+ resolved = Docbook::XIncludeResolver.resolve_string(xml_string, base_path: input)
89
+ resolved.to_xml
90
+ else
91
+ xml_string
92
+ end
93
+ end
94
+
95
+ def parse_input(xml_string)
96
+ Docbook::Document.from_xml(xml_string)
97
+ end
98
+
99
+ def write_output(content, output_path, output_type)
100
+ if output_type == :directory
101
+ raise ArgumentError, "Output path required for directory mode" unless output_path
102
+
103
+ FileUtils.mkdir_p(output_path)
104
+ File.write(File.join(output_path, "index.html"), content)
105
+
106
+ # Copy frontend assets to output_dir/assets/
107
+ assets_dir = File.join(output_path, "assets")
108
+ FileUtils.mkdir_p(assets_dir)
109
+ FileUtils.cp(File.join(FRONTEND_ROOT, "app.css"), File.join(assets_dir, "app.css"))
110
+ FileUtils.cp(File.join(FRONTEND_ROOT, "app.iife.js"), File.join(assets_dir, "app.iife.js"))
111
+
112
+ puts "Written to #{File.join(output_path, "index.html")} and assets/"
113
+ else
114
+ if output_path
115
+ File.write(output_path, content)
116
+ puts "Written to #{output_path}"
117
+ else
118
+ $stdout.write(content)
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require "nokogiri"
5
+
6
+ module Docbook
7
+ class Document
8
+ ROOT_ELEMENT_MAP = {
9
+ "article" => Elements::Article,
10
+ "book" => Elements::Book,
11
+ "chapter" => Elements::Chapter,
12
+ "appendix" => Elements::Appendix,
13
+ "preface" => Elements::Preface,
14
+ "part" => Elements::Part,
15
+ "section" => Elements::Section,
16
+ "refentry" => Elements::RefEntry,
17
+ "bibliography" => Elements::Bibliography,
18
+ "glossary" => Elements::Glossary,
19
+ "set" => Elements::Set,
20
+ "reference" => Elements::Reference,
21
+ "topic" => Elements::Topic,
22
+ "dedication" => Elements::Dedication,
23
+ "acknowledgements" => Elements::Acknowledgements,
24
+ "colophon" => Elements::Colophon,
25
+ "index" => Elements::Index,
26
+ "toc" => Elements::Toc,
27
+ "sect1" => Elements::Sect1,
28
+ "sect2" => Elements::Sect2,
29
+ "sect3" => Elements::Sect3,
30
+ "sect4" => Elements::Sect4,
31
+ "sect5" => Elements::Sect5,
32
+ "refsection" => Elements::RefSection,
33
+ "refsect1" => Elements::RefSect1,
34
+ "refsect2" => Elements::RefSect2,
35
+ "refsect3" => Elements::RefSect3,
36
+ "setindex" => Elements::SetIndex,
37
+ "para" => Elements::Para,
38
+ "simplesect" => Elements::Simplesect,
39
+ }.freeze
40
+
41
+ class << self
42
+ def from_xml(xml_string)
43
+ doc = Nokogiri::XML(xml_string)
44
+ root = doc.root
45
+ raise Docbook::Error, "Empty or invalid XML document" unless root
46
+
47
+ root_name = root.name
48
+ klass = ROOT_ELEMENT_MAP[root_name]
49
+
50
+ if klass.nil?
51
+ raise Docbook::Error, "Unsupported DocBook root element: #{root_name}"
52
+ end
53
+
54
+ klass.from_xml(xml_string)
55
+ end
56
+
57
+ def supports?(root_name)
58
+ klass = ROOT_ELEMENT_MAP[root_name]
59
+ !klass.nil?
60
+ end
61
+
62
+ def supported_root_elements
63
+ ROOT_ELEMENT_MAP.select { |_, v| v }.keys
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Abbrev < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+
9
+ xml do
10
+ element "abbrev"
11
+ mixed_content
12
+ map_content to: :content
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Acknowledgements < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+ attribute :xml_id, Lutaml::Xml::W3c::XmlIdType
9
+ attribute :title, Title
10
+ attribute :para, Para, collection: true
11
+
12
+ xml do
13
+ element "acknowledgements"
14
+ mixed_content
15
+ map_content to: :content
16
+ map_attribute "xml:id", to: :xml_id
17
+ map_element "title", to: :title
18
+ map_element "para", to: :para
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Address < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+ attribute :xml_id, Lutaml::Xml::W3c::XmlIdType
9
+
10
+ xml do
11
+ element "address"
12
+ mixed_content
13
+ map_content to: :content
14
+ map_attribute "xml:id", to: :xml_id
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Alt < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+
9
+ xml do
10
+ element "alt"
11
+ mixed_content
12
+ map_content to: :content
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Annotation < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+ attribute :xml_id, Lutaml::Xml::W3c::XmlIdType
9
+
10
+ xml do
11
+ element "annotation"
12
+ mixed_content
13
+ map_content to: :content
14
+ map_attribute "xml:id", to: :xml_id
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Appendix < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+ attribute :xml_id, Lutaml::Xml::W3c::XmlIdType
9
+ attribute :version, :string
10
+ attribute :info, Info
11
+ attribute :title, Title
12
+ attribute :para, Para, collection: true
13
+ attribute :section, Section, collection: true
14
+ attribute :literallayout, LiteralLayout, collection: true
15
+ attribute :simplesect, Simplesect, collection: true
16
+ attribute :indexterm, IndexTerm, collection: true
17
+
18
+ xml do
19
+ element "appendix"
20
+ mixed_content
21
+ map_content to: :content
22
+ map_attribute "xml:id", to: :xml_id
23
+ map_attribute "version", to: :version
24
+ map_element "info", to: :info
25
+ map_element "title", to: :title
26
+ map_element "para", to: :para
27
+ map_element "section", to: :section
28
+ map_element "literallayout", to: :literallayout
29
+ map_element "simplesect", to: :simplesect
30
+ map_element "indexterm", to: :indexterm
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+
4
+ module Docbook
5
+ module Elements
6
+ class Article < Lutaml::Model::Serializable
7
+ attribute :content, :string
8
+ attribute :version, :string
9
+ attribute :xml_id, Lutaml::Xml::W3c::XmlIdType
10
+ attribute :lang, Lutaml::Xml::W3c::XmlLangType
11
+ attribute :info, Info
12
+ attribute :para, Para, collection: true
13
+ attribute :simplesect, Simplesect, collection: true
14
+ attribute :section, Section, collection: true
15
+
16
+ xml do
17
+ element "article"
18
+ mixed_content
19
+
20
+ map_content to: :content
21
+ map_attribute "version", to: :version
22
+ map_attribute "xml:id", to: :xml_id
23
+ map_attribute "lang", to: :lang
24
+ map_element "info", to: :info
25
+ map_element "para", to: :para
26
+ map_element "simplesect", to: :simplesect
27
+ map_element "section", to: :section
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Docbook
4
+ module Elements
5
+ class Att < Lutaml::Model::Serializable
6
+ attribute :content, :string
7
+
8
+ xml do
9
+ element "att"
10
+ mixed_content
11
+ map_content to: :content
12
+ end
13
+ end
14
+ end
15
+ end