metanorma-document 0.2.9 → 0.2.12

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 (390) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +164 -66
  3. data/CLAUDE.md +26 -0
  4. data/README.adoc +144 -0
  5. data/Rakefile +14 -2
  6. data/TODO.finalize/01-split-multi-class-files.md +8 -0
  7. data/TODO.finalize/02-remove-data-dist-iso-document-frontend.md +6 -0
  8. data/TODO.finalize/03-align-frontend-iife-and-gha-build.md +11 -0
  9. data/TODO.finalize/04-theme-per-flavor-config-driven.md +9 -0
  10. data/TODO.finalize/05-migrate-all-html-to-liquid.md +16 -0
  11. data/TODO.finalize/06-integrate-pubid-library.md +16 -0
  12. data/TODO.finalize/07-replace-relaton-models-with-relaton-bib.md +39 -0
  13. data/TODO.finalize/08-refactor-renderer-architecture.md +25 -0
  14. data/TODO.finalize/09-eliminate-code-smells.md +14 -0
  15. data/TODO.finalize/10-comprehensive-spec-coverage.md +24 -0
  16. data/TODO.finalize/11-config-driven-flavor-metadata.md +20 -0
  17. data/TODO.finalize/12-add-frozen-string-literal.md +6 -0
  18. data/TODO.finalize/13-extract-composition-from-god-class.md +96 -0
  19. data/TODO.finalize/14-config-driven-section-ordering.md +31 -0
  20. data/TODO.finalize/15-theme-directories-per-flavor.md +46 -0
  21. data/TODO.finalize/16-theme-lutaml-model-schema.md +44 -0
  22. data/data/javascripts/components/mn-footnotes.js +68 -0
  23. data/data/javascripts/components/mn-lightbox.js +18 -2
  24. data/data/javascripts/components/mn-shortcuts.js +2 -0
  25. data/data/javascripts/core/mn-navigation.js +8 -0
  26. data/data/javascripts/core/mn-theme.js +9 -9
  27. data/data/logos/oiml-logo-full-dark.svg +1 -0
  28. data/data/logos/oiml-logo-full-light.svg +1 -0
  29. data/data/logos/oiml-logo-icon-dark.svg +1 -0
  30. data/data/logos/oiml-logo-icon-light.svg +1 -0
  31. data/data/logos/oiml-logo.svg +1 -0
  32. data/data/logos/pdfa-logo.svg +31 -94
  33. data/data/stylesheets/base/_layout.css +3 -0
  34. data/data/stylesheets/base/_reset.css +3 -3
  35. data/data/stylesheets/base/_typography.css +0 -5
  36. data/data/stylesheets/components/bibliography.css +3 -3
  37. data/data/stylesheets/components/cover.css +3 -1
  38. data/data/stylesheets/components/figure.css +13 -1
  39. data/data/stylesheets/components/footnote.css +65 -5
  40. data/data/stylesheets/components/formula.css +44 -0
  41. data/data/stylesheets/components/header.css +17 -2
  42. data/data/stylesheets/components/inline.css +1 -1
  43. data/data/stylesheets/components/table.css +15 -2
  44. data/data/stylesheets/components/term.css +0 -1
  45. data/data/themes/bipm.yaml +60 -0
  46. data/data/themes/cc.yaml +43 -0
  47. data/data/themes/icc.yaml +39 -0
  48. data/data/themes/iec.yaml +44 -0
  49. data/data/themes/ieee.yaml +43 -0
  50. data/data/themes/ietf.yaml +45 -0
  51. data/data/themes/iho.yaml +46 -0
  52. data/data/themes/iso.yaml +40 -0
  53. data/data/themes/itu.yaml +45 -0
  54. data/data/themes/ogc.yaml +51 -0
  55. data/data/themes/oiml.yaml +56 -0
  56. data/data/themes/pdfa.yaml +44 -0
  57. data/data/themes/ribose.yaml +43 -0
  58. data/exe/metanorma-document +11 -0
  59. data/frontend/e2e/sample-html.test.ts +256 -0
  60. data/frontend/index.html +12 -0
  61. data/frontend/package-lock.json +4725 -0
  62. data/frontend/package.json +32 -0
  63. data/frontend/postcss.config.js +6 -0
  64. data/frontend/src/App.vue +79 -0
  65. data/frontend/src/app.ts +21 -0
  66. data/frontend/src/components/AppSidebar.vue +77 -0
  67. data/frontend/src/components/DocumentReader.vue +180 -0
  68. data/frontend/src/components/MirrorRenderer.vue +23 -0
  69. data/frontend/src/components/ReadingProgressBar.vue +29 -0
  70. data/frontend/src/components/TextRenderer.vue +131 -0
  71. data/frontend/src/components/TocItem.vue +57 -0
  72. data/frontend/src/components/TopBar.vue +49 -0
  73. data/frontend/src/components/__tests__/MirrorRenderer.test.ts +178 -0
  74. data/frontend/src/components/blocks/AdmonitionBlock.vue +74 -0
  75. data/frontend/src/components/blocks/ClauseBlock.vue +53 -0
  76. data/frontend/src/components/blocks/ExampleBlock.vue +21 -0
  77. data/frontend/src/components/blocks/FallbackBlock.vue +18 -0
  78. data/frontend/src/components/blocks/FigureBlock.vue +26 -0
  79. data/frontend/src/components/blocks/FootnotesBlock.vue +25 -0
  80. data/frontend/src/components/blocks/ListBlocks.vue +62 -0
  81. data/frontend/src/components/blocks/NoteBlock.vue +21 -0
  82. data/frontend/src/components/blocks/ParagraphBlock.vue +25 -0
  83. data/frontend/src/components/blocks/QuoteBlock.vue +25 -0
  84. data/frontend/src/components/blocks/ReviewBlock.vue +39 -0
  85. data/frontend/src/components/blocks/SourcecodeBlock.vue +52 -0
  86. data/frontend/src/components/blocks/TableBlock.vue +48 -0
  87. data/frontend/src/components/blocks/index.ts +36 -0
  88. data/frontend/src/stores/__tests__/documentStore.fixture.test.ts +272 -0
  89. data/frontend/src/stores/__tests__/documentStore.test.ts +143 -0
  90. data/frontend/src/stores/__tests__/ebookStore.test.ts +145 -0
  91. data/frontend/src/stores/__tests__/uiStore.test.ts +42 -0
  92. data/frontend/src/stores/documentStore.ts +153 -0
  93. data/frontend/src/stores/ebookStore.ts +179 -0
  94. data/frontend/src/stores/uiStore.ts +32 -0
  95. data/frontend/src/styles.css +156 -0
  96. data/frontend/src/types/__tests__/rendering-contract.test.ts +172 -0
  97. data/frontend/src/types/rendering-contract.ts +209 -0
  98. data/frontend/src/utils/__tests__/typeMetadata.test.ts +102 -0
  99. data/frontend/src/utils/typeMetadata.ts +121 -0
  100. data/frontend/tailwind.config.js +18 -0
  101. data/frontend/test/fixtures/iso-document.json +271 -0
  102. data/frontend/tmp/debug_e2e.cjs +46 -0
  103. data/frontend/tsconfig.json +25 -0
  104. data/frontend/tsconfig.node.json +11 -0
  105. data/frontend/vite.config.ts +37 -0
  106. data/frontend/vitest.e2e.config.ts +9 -0
  107. data/lib/metanorma/bipm_document/metadata/bipm_bibliographic_item.rb +0 -14
  108. data/lib/metanorma/bipm_document/metadata/depiction_element.rb +18 -0
  109. data/lib/metanorma/bipm_document/metadata.rb +1 -1
  110. data/lib/metanorma/document/cli.rb +116 -0
  111. data/lib/metanorma/document/components/ancillary_blocks/callout_annotation.rb +27 -0
  112. data/lib/metanorma/document/components/ancillary_blocks/sourcecode_block.rb +0 -65
  113. data/lib/metanorma/document/components/ancillary_blocks/sourcecode_body.rb +18 -0
  114. data/lib/metanorma/document/components/ancillary_blocks.rb +4 -0
  115. data/lib/metanorma/document/components/bib_data/bib_data.rb +7 -0
  116. data/lib/metanorma/document/components/blocks/classification_value.rb +21 -0
  117. data/lib/metanorma/document/components/blocks/permission_model.rb +28 -0
  118. data/lib/metanorma/document/components/blocks/recommendation_model.rb +28 -0
  119. data/lib/metanorma/document/components/blocks/requirement_base.rb +30 -0
  120. data/lib/metanorma/document/components/blocks/requirement_classification.rb +20 -0
  121. data/lib/metanorma/document/components/blocks/requirement_description.rb +43 -0
  122. data/lib/metanorma/document/components/blocks/requirement_inherit.rb +24 -0
  123. data/lib/metanorma/document/components/blocks/requirement_model.rb +0 -131
  124. data/lib/metanorma/document/components/blocks.rb +8 -7
  125. data/lib/metanorma/document/components/id_elements/image.rb +2 -0
  126. data/lib/metanorma/document/components/inline/asciimath_element.rb +2 -0
  127. data/lib/metanorma/document/components/inline/attribution_element.rb +2 -0
  128. data/lib/metanorma/document/components/inline/bcp14_element.rb +2 -0
  129. data/lib/metanorma/document/components/inline/biblio_tag_element.rb +2 -0
  130. data/lib/metanorma/document/components/inline/br_element.rb +2 -0
  131. data/lib/metanorma/document/components/inline/comma_element.rb +2 -0
  132. data/lib/metanorma/document/components/inline/concept_element.rb +2 -0
  133. data/lib/metanorma/document/components/inline/display_text_element.rb +2 -0
  134. data/lib/metanorma/document/components/inline/em_raw_element.rb +2 -0
  135. data/lib/metanorma/document/components/inline/enum_comma_element.rb +2 -0
  136. data/lib/metanorma/document/components/inline/eref_element.rb +2 -0
  137. data/lib/metanorma/document/components/inline/fmt_admitted_element.rb +4 -0
  138. data/lib/metanorma/document/components/inline/fmt_annotation_body_element.rb +4 -0
  139. data/lib/metanorma/document/components/inline/fmt_annotation_end_element.rb +4 -0
  140. data/lib/metanorma/document/components/inline/fmt_annotation_start_element.rb +4 -0
  141. data/lib/metanorma/document/components/inline/fmt_concept_element.rb +4 -0
  142. data/lib/metanorma/document/components/inline/fmt_definition_element.rb +4 -0
  143. data/lib/metanorma/document/components/inline/fmt_fn_body_element.rb +4 -0
  144. data/lib/metanorma/document/components/inline/fmt_fn_label_element.rb +4 -0
  145. data/lib/metanorma/document/components/inline/fmt_footnote_container_element.rb +4 -0
  146. data/lib/metanorma/document/components/inline/fmt_identifier_element.rb +4 -0
  147. data/lib/metanorma/document/components/inline/fmt_name_element.rb +4 -0
  148. data/lib/metanorma/document/components/inline/fmt_preferred_element.rb +4 -0
  149. data/lib/metanorma/document/components/inline/fmt_sourcecode_element.rb +4 -0
  150. data/lib/metanorma/document/components/inline/fmt_stem_element.rb +10 -0
  151. data/lib/metanorma/document/components/inline/fmt_termsource_element.rb +4 -0
  152. data/lib/metanorma/document/components/inline/fmt_title_element.rb +4 -0
  153. data/lib/metanorma/document/components/inline/fmt_xref_element.rb +4 -0
  154. data/lib/metanorma/document/components/inline/fmt_xref_label_element.rb +4 -0
  155. data/lib/metanorma/document/components/inline/fn_element.rb +2 -0
  156. data/lib/metanorma/document/components/inline/link_element.rb +2 -0
  157. data/lib/metanorma/document/components/inline/localized_string_element.rb +2 -0
  158. data/lib/metanorma/document/components/inline/localized_strings_element.rb +2 -0
  159. data/lib/metanorma/document/components/inline/location_element.rb +24 -0
  160. data/lib/metanorma/document/components/inline/math_element.rb +2 -0
  161. data/lib/metanorma/document/components/inline/name_with_id_element.rb +4 -0
  162. data/lib/metanorma/document/components/inline/rendered_display.rb +23 -0
  163. data/lib/metanorma/document/components/inline/rendered_math_element.rb +21 -0
  164. data/lib/metanorma/document/components/inline/semantic_content.rb +51 -0
  165. data/lib/metanorma/document/components/inline/semantic_math_element.rb +20 -0
  166. data/lib/metanorma/document/components/inline/semx_child_element.rb +2 -0
  167. data/lib/metanorma/document/components/inline/semx_element.rb +13 -1
  168. data/lib/metanorma/document/components/inline/small_cap_element.rb +2 -0
  169. data/lib/metanorma/document/components/inline/span_element.rb +10 -15
  170. data/lib/metanorma/document/components/inline/stem_inline_element.rb +7 -1
  171. data/lib/metanorma/document/components/inline/strong_raw_element.rb +2 -0
  172. data/lib/metanorma/document/components/inline/sub_element.rb +2 -0
  173. data/lib/metanorma/document/components/inline/sup_element.rb +2 -0
  174. data/lib/metanorma/document/components/inline/tab_element.rb +2 -0
  175. data/lib/metanorma/document/components/inline/title_with_annotation_element.rb +4 -0
  176. data/lib/metanorma/document/components/inline/tt_element.rb +2 -0
  177. data/lib/metanorma/document/components/inline/variant_title_element.rb +2 -0
  178. data/lib/metanorma/document/components/inline/vocabulary.rb +184 -0
  179. data/lib/metanorma/document/components/inline/xref_element.rb +10 -0
  180. data/lib/metanorma/document/components/inline.rb +12 -0
  181. data/lib/metanorma/document/components/multi_paragraph/quote_author_element.rb +20 -0
  182. data/lib/metanorma/document/components/multi_paragraph/quote_block.rb +0 -29
  183. data/lib/metanorma/document/components/multi_paragraph.rb +2 -0
  184. data/lib/metanorma/document/components/reference_elements/source_element.rb +0 -31
  185. data/lib/metanorma/document/components/reference_elements/source_modification.rb +21 -0
  186. data/lib/metanorma/document/components/reference_elements/source_origin.rb +28 -0
  187. data/lib/metanorma/document/components/reference_elements.rb +2 -2
  188. data/lib/metanorma/document/components/tables/col_element.rb +18 -0
  189. data/lib/metanorma/document/components/tables/col_group_element.rb +18 -0
  190. data/lib/metanorma/document/components/tables/table_block.rb +0 -22
  191. data/lib/metanorma/document/components/tables/table_body_section.rb +16 -0
  192. data/lib/metanorma/document/components/tables/table_foot_section.rb +16 -0
  193. data/lib/metanorma/document/components/tables/table_head_section.rb +16 -0
  194. data/lib/metanorma/document/components/tables/table_section.rb +0 -25
  195. data/lib/metanorma/document/components/tables.rb +5 -3
  196. data/lib/metanorma/document/relaton/address.rb +0 -27
  197. data/lib/metanorma/document/relaton/bib_item_locality.rb +3 -12
  198. data/lib/metanorma/document/relaton/copyright_association.rb +0 -10
  199. data/lib/metanorma/document/relaton/copyright_owner.rb +16 -0
  200. data/lib/metanorma/document/relaton/edition.rb +4 -7
  201. data/lib/metanorma/document/relaton/formatted_address.rb +29 -0
  202. data/lib/metanorma/document/relaton/logo_element.rb +18 -0
  203. data/lib/metanorma/document/relaton/organization.rb +0 -14
  204. data/lib/metanorma/document/relaton/phone.rb +3 -9
  205. data/lib/metanorma/document/relaton/place_type.rb +0 -13
  206. data/lib/metanorma/document/relaton/price_type.rb +3 -9
  207. data/lib/metanorma/document/relaton/region_element.rb +18 -0
  208. data/lib/metanorma/document/relaton.rb +6 -1
  209. data/lib/metanorma/document/version.rb +1 -1
  210. data/lib/metanorma/document.rb +2 -0
  211. data/lib/metanorma/html/asset_pipeline.rb +1 -0
  212. data/lib/metanorma/html/base_renderer.rb +261 -1008
  213. data/lib/metanorma/html/bipm_renderer.rb +15 -144
  214. data/lib/metanorma/html/cc_renderer.rb +1 -45
  215. data/lib/metanorma/html/component/base.rb +2 -7
  216. data/lib/metanorma/html/component/index_section.rb +41 -43
  217. data/lib/metanorma/html/drops/admonition_drop.rb +1 -4
  218. data/lib/metanorma/html/drops/biblio_entry_drop.rb +50 -0
  219. data/lib/metanorma/html/drops/block_element_drop.rb +7 -2
  220. data/lib/metanorma/html/drops/example_drop.rb +1 -4
  221. data/lib/metanorma/html/drops/figure_drop.rb +31 -22
  222. data/lib/metanorma/html/drops/footnote_drop.rb +1 -1
  223. data/lib/metanorma/html/drops/formula_drop.rb +45 -16
  224. data/lib/metanorma/html/drops/note_drop.rb +9 -7
  225. data/lib/metanorma/html/drops/sourcecode_drop.rb +12 -5
  226. data/lib/metanorma/html/drops.rb +2 -0
  227. data/lib/metanorma/html/generator.rb +2 -2
  228. data/lib/metanorma/html/icc_renderer.rb +0 -39
  229. data/lib/metanorma/html/iec_renderer.rb +1 -44
  230. data/lib/metanorma/html/ieee_renderer.rb +1 -45
  231. data/lib/metanorma/html/ietf_renderer.rb +1 -48
  232. data/lib/metanorma/html/iho_renderer.rb +1 -46
  233. data/lib/metanorma/html/iso_renderer.rb +290 -343
  234. data/lib/metanorma/html/itu_renderer.rb +1 -45
  235. data/lib/metanorma/html/ogc_renderer.rb +15 -76
  236. data/lib/metanorma/html/oiml_renderer.rb +18 -38
  237. data/lib/metanorma/html/pdfa_renderer.rb +0 -39
  238. data/lib/metanorma/html/renderers/block_renderer.rb +372 -0
  239. data/lib/metanorma/html/renderers/inline_renderer.rb +655 -0
  240. data/lib/metanorma/html/renderers/pubid_renderer.rb +69 -0
  241. data/lib/metanorma/html/renderers/section_renderer.rb +193 -0
  242. data/lib/metanorma/html/renderers.rb +8 -0
  243. data/lib/metanorma/html/ribose_renderer.rb +1 -45
  244. data/lib/metanorma/html/standard_renderer.rb +341 -229
  245. data/lib/metanorma/html/templates/_audio.html.liquid +1 -0
  246. data/lib/metanorma/html/templates/_biblio_entry.html.liquid +1 -0
  247. data/lib/metanorma/html/templates/_bipm_cover.html.liquid +27 -0
  248. data/lib/metanorma/html/templates/_boilerplate.html.liquid +1 -0
  249. data/lib/metanorma/html/templates/_bookmark.html.liquid +1 -0
  250. data/lib/metanorma/html/templates/_br.html.liquid +1 -0
  251. data/lib/metanorma/html/templates/_definition_list.html.liquid +6 -0
  252. data/lib/metanorma/html/templates/_element.html.liquid +1 -0
  253. data/lib/metanorma/html/templates/_fn_marker.html.liquid +1 -0
  254. data/lib/metanorma/html/templates/_footnotes.html.liquid +6 -6
  255. data/lib/metanorma/html/templates/_formula.html.liquid +1 -1
  256. data/lib/metanorma/html/templates/_header.html.liquid +1 -1
  257. data/lib/metanorma/html/templates/_heading.html.liquid +1 -0
  258. data/lib/metanorma/html/templates/_image.html.liquid +1 -0
  259. data/lib/metanorma/html/templates/_inline_span.html.liquid +1 -0
  260. data/lib/metanorma/html/templates/_iso_cover.html.liquid +1 -1
  261. data/lib/metanorma/html/templates/_link.html.liquid +1 -0
  262. data/lib/metanorma/html/templates/_list.html.liquid +3 -0
  263. data/lib/metanorma/html/templates/_list_item.html.liquid +1 -0
  264. data/lib/metanorma/html/templates/_main_content.html.liquid +1 -0
  265. data/lib/metanorma/html/templates/_math_container.html.liquid +1 -0
  266. data/lib/metanorma/html/templates/_paragraph.html.liquid +1 -0
  267. data/lib/metanorma/html/templates/_prefatory_section.html.liquid +1 -0
  268. data/lib/metanorma/html/templates/_pubid_identifier.html.liquid +1 -0
  269. data/lib/metanorma/html/templates/_quote.html.liquid +4 -0
  270. data/lib/metanorma/html/templates/_ref_date.html.liquid +1 -0
  271. data/lib/metanorma/html/templates/_ref_title.html.liquid +1 -0
  272. data/lib/metanorma/html/templates/_section.html.liquid +5 -0
  273. data/lib/metanorma/html/templates/_standard_cover.html.liquid +31 -0
  274. data/lib/metanorma/html/templates/_standard_doc_title.html.liquid +3 -0
  275. data/lib/metanorma/html/templates/_stem_span.html.liquid +1 -0
  276. data/lib/metanorma/html/templates/_table.html.liquid +9 -0
  277. data/lib/metanorma/html/templates/_term_domain.html.liquid +1 -0
  278. data/lib/metanorma/html/templates/_term_example.html.liquid +1 -0
  279. data/lib/metanorma/html/templates/_term_note.html.liquid +1 -0
  280. data/lib/metanorma/html/templates/_term_number.html.liquid +1 -0
  281. data/lib/metanorma/html/templates/_term_source.html.liquid +1 -0
  282. data/lib/metanorma/html/templates/_term_text_note.html.liquid +1 -0
  283. data/lib/metanorma/html/templates/_video.html.liquid +1 -0
  284. data/lib/metanorma/html/templates/_wrapped_preface.html.liquid +1 -0
  285. data/lib/metanorma/html/templates/document.html.liquid +4 -0
  286. data/lib/metanorma/html/theme.rb +180 -107
  287. data/lib/metanorma/html.rb +13 -0
  288. data/lib/metanorma/ietf_document/metadata/ietf_bib_data_extension_type.rb +0 -25
  289. data/lib/metanorma/ietf_document/metadata/pi_settings.rb +32 -0
  290. data/lib/metanorma/ietf_document/metadata.rb +2 -0
  291. data/lib/metanorma/iso_document/metadata/doctype_element.rb +20 -0
  292. data/lib/metanorma/iso_document/metadata/iso_bib_data_extension_type.rb +0 -48
  293. data/lib/metanorma/iso_document/metadata/iso_bibliographic_item.rb +0 -72
  294. data/lib/metanorma/iso_document/metadata/iso_document_status.rb +0 -30
  295. data/lib/metanorma/iso_document/metadata/iso_localized_title.rb +4 -1
  296. data/lib/metanorma/iso_document/metadata/language_element.rb +18 -0
  297. data/lib/metanorma/iso_document/metadata/project_number.rb +22 -0
  298. data/lib/metanorma/iso_document/metadata/script_element.rb +18 -0
  299. data/lib/metanorma/iso_document/metadata/stage_element.rb +26 -0
  300. data/lib/metanorma/iso_document/metadata/stagename_element.rb +18 -0
  301. data/lib/metanorma/iso_document/metadata/structured_identifier.rb +0 -17
  302. data/lib/metanorma/iso_document/metadata/title_collection.rb +1 -0
  303. data/lib/metanorma/iso_document/metadata.rb +9 -4
  304. data/lib/metanorma/iso_document/terms/iso_term.rb +0 -13
  305. data/lib/metanorma/iso_document/terms/term_domain_element.rb +18 -0
  306. data/lib/metanorma/iso_document/terms.rb +1 -0
  307. data/lib/metanorma/itu_document/metadata/itu_bib_data_extension_type.rb +0 -37
  308. data/lib/metanorma/itu_document/metadata/meeting_date.rb +18 -0
  309. data/lib/metanorma/itu_document/metadata/meeting_element.rb +18 -0
  310. data/lib/metanorma/itu_document/metadata/study_period.rb +18 -0
  311. data/lib/metanorma/itu_document/metadata.rb +3 -4
  312. data/lib/metanorma/mirror/default_registry.rb +170 -0
  313. data/lib/metanorma/mirror/handler_registry.rb +60 -0
  314. data/lib/metanorma/mirror/handler_result.rb +37 -0
  315. data/lib/metanorma/mirror/handlers/admonition.rb +18 -0
  316. data/lib/metanorma/mirror/handlers/example.rb +21 -0
  317. data/lib/metanorma/mirror/handlers/figure.rb +53 -0
  318. data/lib/metanorma/mirror/handlers/formula.rb +35 -0
  319. data/lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb +159 -0
  320. data/lib/metanorma/mirror/handlers/inline/text_extractor.rb +116 -0
  321. data/lib/metanorma/mirror/handlers/inline.rb +225 -0
  322. data/lib/metanorma/mirror/handlers/list.rb +110 -0
  323. data/lib/metanorma/mirror/handlers/note.rb +26 -0
  324. data/lib/metanorma/mirror/handlers/paragraph.rb +19 -0
  325. data/lib/metanorma/mirror/handlers/quote.rb +16 -0
  326. data/lib/metanorma/mirror/handlers/review.rb +19 -0
  327. data/lib/metanorma/mirror/handlers/section.rb +149 -0
  328. data/lib/metanorma/mirror/handlers/sourcecode.rb +27 -0
  329. data/lib/metanorma/mirror/handlers/structural.rb +68 -0
  330. data/lib/metanorma/mirror/handlers/table.rb +81 -0
  331. data/lib/metanorma/mirror/handlers/term.rb +100 -0
  332. data/lib/metanorma/mirror/handlers.rb +60 -0
  333. data/lib/metanorma/mirror/id_strategy/positional.rb +166 -0
  334. data/lib/metanorma/mirror/id_strategy/preserve.rb +12 -0
  335. data/lib/metanorma/mirror/id_strategy.rb +34 -0
  336. data/lib/metanorma/mirror/math_util.rb +53 -0
  337. data/lib/metanorma/mirror/metadata.rb +37 -0
  338. data/lib/metanorma/mirror/metanorma_to_mirror.rb +101 -0
  339. data/lib/metanorma/mirror/model/container.rb +47 -0
  340. data/lib/metanorma/mirror/model/factory.rb +52 -0
  341. data/lib/metanorma/mirror/model/guide.rb +25 -0
  342. data/lib/metanorma/mirror/model/leaf.rb +17 -0
  343. data/lib/metanorma/mirror/model/mark.rb +53 -0
  344. data/lib/metanorma/mirror/model/node.rb +47 -0
  345. data/lib/metanorma/mirror/model/soft_break.rb +33 -0
  346. data/lib/metanorma/mirror/model/text.rb +34 -0
  347. data/lib/metanorma/mirror/model.rb +16 -0
  348. data/lib/metanorma/mirror/output/builder.rb +39 -0
  349. data/lib/metanorma/mirror/output/formats/base_format.rb +90 -0
  350. data/lib/metanorma/mirror/output/formats/inline_format.rb +81 -0
  351. data/lib/metanorma/mirror/output/formats.rb +53 -0
  352. data/lib/metanorma/mirror/output/html_renderer.rb +95 -0
  353. data/lib/metanorma/mirror/output/html_renderers/block_renderers.rb +178 -0
  354. data/lib/metanorma/mirror/output/html_renderers/inline_renderer.rb +61 -0
  355. data/lib/metanorma/mirror/output/html_renderers/list_renderers.rb +96 -0
  356. data/lib/metanorma/mirror/output/html_renderers/mark_renderers.rb +64 -0
  357. data/lib/metanorma/mirror/output/html_renderers/section_renderers.rb +129 -0
  358. data/lib/metanorma/mirror/output/html_renderers/structural_renderers.rb +80 -0
  359. data/lib/metanorma/mirror/output/html_renderers/table_renderers.rb +87 -0
  360. data/lib/metanorma/mirror/output/html_renderers.rb +76 -0
  361. data/lib/metanorma/mirror/output/pipeline.rb +92 -0
  362. data/lib/metanorma/mirror/output/pipeline_context.rb +22 -0
  363. data/lib/metanorma/mirror/output.rb +14 -0
  364. data/lib/metanorma/mirror/rewriter.rb +121 -0
  365. data/lib/metanorma/mirror/safe_attr.rb +16 -0
  366. data/lib/metanorma/mirror/serialization/json_serializer.rb +25 -0
  367. data/lib/metanorma/mirror/serialization/yaml_serializer.rb +20 -0
  368. data/lib/metanorma/mirror/serialization.rb +10 -0
  369. data/lib/metanorma/mirror/transformer.rb +22 -0
  370. data/lib/metanorma/mirror.rb +32 -0
  371. data/lib/metanorma/standard_document/annotation.rb +37 -0
  372. data/lib/metanorma/standard_document/block_attributes.rb +15 -2
  373. data/lib/metanorma/standard_document/blocks/block_source.rb +0 -23
  374. data/lib/metanorma/standard_document/blocks/source_origin_element.rb +23 -0
  375. data/lib/metanorma/standard_document/blocks.rb +1 -1
  376. data/lib/metanorma/standard_document/terms/term_expression.rb +0 -31
  377. data/lib/metanorma/standard_document/terms/term_name_element.rb +29 -0
  378. data/lib/metanorma/standard_document/terms.rb +1 -0
  379. data/script/render_both.rb +18 -0
  380. metadata +262 -13
  381. data/.github/workflows/rake.yml +0 -21
  382. data/.github/workflows/release.yml +0 -25
  383. data/.github/workflows/roundtrip-samples.yml +0 -132
  384. data/.gitignore +0 -19
  385. data/.rspec +0 -3
  386. data/.rubocop.yml +0 -22
  387. data/Gemfile +0 -28
  388. data/bin/console +0 -15
  389. data/bin/setup +0 -8
  390. data/metanorma-document.gemspec +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da12347749776b99b68dcc3816de625289ce2e56f51a9716c05d38088a4913b7
4
- data.tar.gz: 2bf0989d205c0ab6a0c282fd5c4cab7d0c7deaccf012baafc64fa97c9160029f
3
+ metadata.gz: d75a3afa9e8f16619cd88b2bf610d81ecd5b6e4d7bc9b507a26c347832d01536
4
+ data.tar.gz: 2739411b950f3871a28eec551346ee5ded7f643c9f76438574f68d1314fc398b
5
5
  SHA512:
6
- metadata.gz: 1af9848d0640195e2176378b067214afe02f1da504893ed09686625e0a79f637bfad69fa5575d0959b59d31e78eff2b986dcdb42d63169db853ab808fb52bf22
7
- data.tar.gz: 8dd05a2a8ed9344e5d70a35ab3c4653ec9b4c69dc001ef3cd400c6822b4874b8582304df5eee0798f37f8da43388e90fc71dbd88402d41fc1e401cd95fcd396a
6
+ metadata.gz: 29980c2343686ad9ec1ebb5c582f6483a280c1ff0d7edd5354597ccb5241db71269a01c955ec2c19e215ec2eeaa0675c93563eae33b446926dad6781ed15d2d2
7
+ data.tar.gz: d6e50bf824ba8f7ea1efabb168743dfd79e3e655547434f9328ba8cea817bce57012f85809940cfd2c9a995784204c846d2964375132978de4cdadebb68efde9
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-05-21 09:20:40 UTC using RuboCop version 1.86.1.
3
+ # on 2026-07-17 09:09:03 UTC using RuboCop version 1.86.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -11,16 +11,53 @@ Gemspec/RequiredRubyVersion:
11
11
  Exclude:
12
12
  - 'metanorma-document.gemspec'
13
13
 
14
- # Offense count: 9
14
+ # Offense count: 2
15
15
  # This cop supports safe autocorrection (--autocorrect).
16
16
  # Configuration parameters: EnforcedStyle, IndentationWidth.
17
17
  # SupportedStyles: with_first_argument, with_fixed_indentation
18
18
  Layout/ArgumentAlignment:
19
19
  Exclude:
20
- - 'lib/metanorma/standard_document.rb'
21
- - 'spec/metanorma/flavor_roots/flavor_roots_spec.rb'
20
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
21
+
22
+ # Offense count: 2
23
+ # This cop supports safe autocorrection (--autocorrect).
24
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
25
+ # SupportedStyles: with_first_element, with_fixed_indentation
26
+ Layout/ArrayAlignment:
27
+ Exclude:
28
+ - 'spec/metanorma/document/components/inline/span_element_bug01_spec.rb'
29
+
30
+ # Offense count: 1
31
+ # This cop supports safe autocorrection (--autocorrect).
32
+ # Configuration parameters: EnforcedStyleAlignWith.
33
+ # SupportedStylesAlignWith: either, start_of_block, start_of_line
34
+ Layout/BlockAlignment:
35
+ Exclude:
36
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
37
+
38
+ # Offense count: 1
39
+ # This cop supports safe autocorrection (--autocorrect).
40
+ Layout/BlockEndNewline:
41
+ Exclude:
42
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
43
+
44
+ # Offense count: 2
45
+ # This cop supports safe autocorrection (--autocorrect).
46
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
47
+ # SupportedStyles: special_inside_parentheses, consistent, align_brackets
48
+ Layout/FirstArrayElementIndentation:
49
+ Exclude:
50
+ - 'spec/metanorma/document/components/inline/span_element_bug01_spec.rb'
51
+
52
+ # Offense count: 2
53
+ # This cop supports safe autocorrection (--autocorrect).
54
+ # Configuration parameters: Width, EnforcedStyleAlignWith, AllowedPatterns.
55
+ # SupportedStylesAlignWith: start_of_line, relative_to_receiver
56
+ Layout/IndentationWidth:
57
+ Exclude:
58
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
22
59
 
23
- # Offense count: 666
60
+ # Offense count: 700
24
61
  # This cop supports safe autocorrection (--autocorrect).
25
62
  # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
26
63
  # URISchemes: http, https
@@ -29,106 +66,101 @@ Layout/LineLength:
29
66
 
30
67
  # Offense count: 1
31
68
  # This cop supports safe autocorrection (--autocorrect).
32
- # Configuration parameters: AllowInHeredoc.
33
- Layout/TrailingWhitespace:
69
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
70
+ # SupportedStyles: aligned, indented, indented_relative_to_receiver
71
+ Layout/MultilineMethodCallIndentation:
34
72
  Exclude:
35
- - 'lib/metanorma/standard_document.rb'
73
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
36
74
 
37
- # Offense count: 1
75
+ # Offense count: 2
38
76
  # Configuration parameters: AllowedMethods.
39
77
  # AllowedMethods: enums
40
78
  Lint/ConstantDefinitionInBlock:
41
79
  Exclude:
42
80
  - 'spec/metanorma/html/renderer/class_ownership_spec.rb'
81
+ - 'spec/metanorma/html/renderer/liquid_templates_spec.rb'
43
82
 
44
- # Offense count: 1
83
+ # Offense count: 3
45
84
  # Configuration parameters: IgnoreLiteralBranches, IgnoreConstantBranches, IgnoreDuplicateElseBranch.
46
85
  Lint/DuplicateBranch:
47
86
  Exclude:
48
87
  - 'lib/metanorma/html/base_renderer.rb'
88
+ - 'lib/metanorma/html/renderers/inline_renderer.rb'
89
+ - 'lib/metanorma/html/standard_renderer.rb'
49
90
 
50
- # Offense count: 3
91
+ # Offense count: 2
51
92
  # Configuration parameters: AllowComments, AllowEmptyLambdas.
52
93
  Lint/EmptyBlock:
53
94
  Exclude:
54
- - 'lib/metanorma/html/drops/formula_drop.rb'
55
95
  - 'spec/metanorma/iso_document/metadata/title_roundtrip_spec.rb'
56
96
 
57
97
  # Offense count: 4
58
98
  # Configuration parameters: AllowedParentClasses.
59
99
  Lint/MissingSuper:
60
100
  Exclude:
61
- - 'lib/metanorma/html/drops/block_element_drop.rb'
62
- - 'lib/metanorma/html/drops/figure_list_entry_drop.rb'
63
- - 'lib/metanorma/html/drops/footnote_drop.rb'
64
- - 'lib/metanorma/html/drops/toc_entry_drop.rb'
101
+ - 'lib/metanorma/html/drops/figure_drop.rb'
102
+ - 'lib/metanorma/html/drops/formula_drop.rb'
103
+ - 'lib/metanorma/html/drops/sourcecode_drop.rb'
104
+ - 'lib/metanorma/mirror/id_strategy/positional.rb'
65
105
 
66
106
  # Offense count: 1
67
107
  Lint/StructNewOverride:
68
108
  Exclude:
69
109
  - 'lib/metanorma/html/component/index_term_collector.rb'
70
110
 
71
- # Offense count: 80
111
+ # Offense count: 23
112
+ # This cop supports safe autocorrection (--autocorrect).
113
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
114
+ # NotImplementedExceptions: NotImplementedError
115
+ Lint/UnusedMethodArgument:
116
+ Exclude:
117
+ - 'lib/metanorma/mirror/handlers/formula.rb'
118
+ - 'lib/metanorma/mirror/handlers/sourcecode.rb'
119
+ - 'lib/metanorma/mirror/output/html_renderers/block_renderers.rb'
120
+ - 'lib/metanorma/mirror/output/html_renderers/list_renderers.rb'
121
+ - 'lib/metanorma/mirror/output/html_renderers/section_renderers.rb'
122
+ - 'lib/metanorma/mirror/output/html_renderers/structural_renderers.rb'
123
+ - 'lib/metanorma/mirror/output/html_renderers/table_renderers.rb'
124
+ - 'spec/metanorma/mirror/handler_registry_spec.rb'
125
+ - 'spec/metanorma/mirror/html_renderer_spec.rb'
126
+
127
+ # Offense count: 114
72
128
  # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
73
129
  Metrics/AbcSize:
74
130
  Enabled: false
75
131
 
76
- # Offense count: 23
132
+ # Offense count: 11
77
133
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode.
78
134
  # AllowedMethods: refine
79
135
  Metrics/BlockLength:
80
- Max: 80
136
+ Max: 47
81
137
 
82
- # Offense count: 1
138
+ # Offense count: 3
83
139
  # Configuration parameters: CountBlocks, CountModifierForms.
84
140
  Metrics/BlockNesting:
85
141
  Max: 4
86
142
 
87
- # Offense count: 56
143
+ # Offense count: 86
88
144
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
89
145
  Metrics/CyclomaticComplexity:
90
- Exclude:
91
- - 'lib/metanorma/document/components/lists/list_item.rb'
92
- - 'lib/metanorma/html/base_renderer.rb'
93
- - 'lib/metanorma/html/bipm_renderer.rb'
94
- - 'lib/metanorma/html/component/index_term_collector.rb'
95
- - 'lib/metanorma/html/drops/figure_drop.rb'
96
- - 'lib/metanorma/html/drops/formula_drop.rb'
97
- - 'lib/metanorma/html/generator.rb'
98
- - 'lib/metanorma/html/iso_renderer.rb'
99
- - 'lib/metanorma/html/ogc_renderer.rb'
100
- - 'lib/metanorma/html/standard_renderer.rb'
101
- - 'lib/metanorma/html/theme.rb'
102
- - 'lib/metanorma/iso_document/metadata/iso_localized_title.rb'
146
+ Enabled: false
103
147
 
104
- # Offense count: 101
148
+ # Offense count: 149
105
149
  # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
106
150
  Metrics/MethodLength:
107
- Max: 95
151
+ Max: 102
108
152
 
109
- # Offense count: 1
153
+ # Offense count: 3
110
154
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
111
155
  Metrics/ParameterLists:
112
156
  Max: 7
113
157
 
114
- # Offense count: 51
158
+ # Offense count: 69
115
159
  # Configuration parameters: AllowedMethods, AllowedPatterns, Max.
116
160
  Metrics/PerceivedComplexity:
117
- Exclude:
118
- - 'lib/metanorma/document/components/lists/list_item.rb'
119
- - 'lib/metanorma/html/base_renderer.rb'
120
- - 'lib/metanorma/html/bipm_renderer.rb'
121
- - 'lib/metanorma/html/component/index_term_collector.rb'
122
- - 'lib/metanorma/html/drops/figure_drop.rb'
123
- - 'lib/metanorma/html/drops/formula_drop.rb'
124
- - 'lib/metanorma/html/generator.rb'
125
- - 'lib/metanorma/html/iso_renderer.rb'
126
- - 'lib/metanorma/html/ogc_renderer.rb'
127
- - 'lib/metanorma/html/standard_renderer.rb'
128
- - 'lib/metanorma/html/theme.rb'
129
- - 'lib/metanorma/iso_document/metadata/iso_localized_title.rb'
161
+ Enabled: false
130
162
 
131
- # Offense count: 28
163
+ # Offense count: 52
132
164
  # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
133
165
  # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
134
166
  Naming/MethodParameterName:
@@ -137,23 +169,35 @@ Naming/MethodParameterName:
137
169
  - 'lib/metanorma/html/component/footnote_collector.rb'
138
170
  - 'lib/metanorma/html/drops/sourcecode_drop.rb'
139
171
  - 'lib/metanorma/html/iso_renderer.rb'
172
+ - 'lib/metanorma/html/renderers/block_renderer.rb'
173
+ - 'lib/metanorma/html/renderers/inline_renderer.rb'
140
174
  - 'spec/metanorma/html/renderer/footnote_collector_spec.rb'
141
175
 
142
- # Offense count: 2
176
+ # Offense count: 4
143
177
  # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
144
178
  # AllowedMethods: call
145
179
  # WaywardPredicates: infinite?, nonzero?
146
180
  Naming/PredicateMethod:
147
181
  Exclude:
148
182
  - 'lib/metanorma/html/base_renderer.rb'
183
+ - 'lib/metanorma/html/drops/biblio_entry_drop.rb'
184
+ - 'lib/metanorma/html/renderers/inline_renderer.rb'
149
185
 
150
- # Offense count: 1
186
+ # Offense count: 3
151
187
  # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
152
188
  # NamePrefix: is_, has_, have_, does_
153
189
  # ForbiddenPrefixes: is_, has_, have_, does_
154
190
  # AllowedMethods: is_a?
155
191
  # MethodDefinitionMacros: define_method, define_singleton_method
156
192
  Naming/PredicatePrefix:
193
+ Exclude:
194
+ - 'spec/**/*'
195
+ - 'lib/metanorma/html/base_renderer.rb'
196
+ - 'lib/metanorma/html/drops/biblio_entry_drop.rb'
197
+
198
+ # Offense count: 1
199
+ # Configuration parameters: MinSize.
200
+ Performance/CollectionLiteralInLoop:
157
201
  Exclude:
158
202
  - 'lib/metanorma/html/standard_renderer.rb'
159
203
 
@@ -162,30 +206,60 @@ Performance/MapMethodChain:
162
206
  Exclude:
163
207
  - 'spec/metanorma/flavor_roots/flavor_roots_spec.rb'
164
208
 
209
+ # Offense count: 1
210
+ # This cop supports unsafe autocorrection (--autocorrect-all).
211
+ # Configuration parameters: AllowRegexpMatch.
212
+ Performance/RedundantEqualityComparisonBlock:
213
+ Exclude:
214
+ - 'spec/metanorma/document/components/inline/fmt_stem_element_bug03_spec.rb'
215
+
165
216
  # Offense count: 7
166
217
  RSpec/BeforeAfterAll:
167
218
  Exclude:
219
+ - '**/spec/spec_helper.rb'
220
+ - '**/spec/rails_helper.rb'
221
+ - '**/spec/support/**/*.rb'
168
222
  - 'spec/metanorma/flavor_roots/flavor_roots_spec.rb'
169
223
 
170
- # Offense count: 18
224
+ # Offense count: 14
225
+ # Configuration parameters: Prefixes, AllowedPatterns.
226
+ # Prefixes: when, with, without
227
+ RSpec/ContextWording:
228
+ Exclude:
229
+ - 'spec/metanorma/html/renderer/theme_spec.rb'
230
+ - 'spec/metanorma/mirror/html_renderer_spec.rb'
231
+
232
+ # Offense count: 32
171
233
  # Configuration parameters: IgnoredMetadata.
172
234
  RSpec/DescribeClass:
173
235
  Enabled: false
174
236
 
175
- # Offense count: 95
237
+ # Offense count: 8
238
+ # This cop supports unsafe autocorrection (--autocorrect-all).
239
+ # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants.
240
+ # SupportedStyles: described_class, explicit
241
+ RSpec/DescribedClass:
242
+ Exclude:
243
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
244
+ - 'spec/metanorma/document/components/inline/xref_element_bug04_spec.rb'
245
+
246
+ # Offense count: 234
176
247
  # Configuration parameters: CountAsOne.
177
248
  RSpec/ExampleLength:
178
- Max: 29
249
+ Max: 37
179
250
 
180
- # Offense count: 1
251
+ # Offense count: 2
181
252
  RSpec/LeakyConstantDeclaration:
182
253
  Exclude:
183
254
  - 'spec/metanorma/html/renderer/class_ownership_spec.rb'
255
+ - 'spec/metanorma/html/renderer/liquid_templates_spec.rb'
184
256
 
185
- # Offense count: 2
257
+ # Offense count: 4
186
258
  RSpec/MultipleDescribes:
187
259
  Exclude:
188
260
  - 'spec/metanorma/document_spec.rb'
261
+ - 'spec/metanorma/mirror/handlers/remaining_handlers_spec.rb'
262
+ - 'spec/metanorma/mirror/serialization_spec.rb'
189
263
  - 'spec/metanorma/standard_document/sections_spec.rb'
190
264
 
191
265
  # Offense count: 1
@@ -200,30 +274,54 @@ RSpec/NamedSubject:
200
274
  Exclude:
201
275
  - 'spec/metanorma/flavor_roots/flavor_roots_spec.rb'
202
276
 
203
- # Offense count: 599
277
+ # Offense count: 1061
204
278
  # Configuration parameters: AllowedPatterns.
205
279
  # AllowedPatterns: ^expect_, ^assert_
206
280
  RSpec/NoExpectationExample:
207
281
  Enabled: false
208
282
 
209
- # Offense count: 25
283
+ # Offense count: 29
210
284
  # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
211
285
  # SupportedInflectors: default, active_support
212
286
  RSpec/SpecFilePathFormat:
213
287
  Enabled: false
214
288
 
289
+ # Offense count: 1
290
+ # This cop supports safe autocorrection (--autocorrect).
291
+ # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
292
+ # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
293
+ # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
294
+ # FunctionalMethods: let, let!, subject, watch
295
+ # AllowedMethods: lambda, proc, it
296
+ Style/BlockDelimiters:
297
+ Exclude:
298
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
299
+
215
300
  # Offense count: 5
216
301
  # This cop supports safe autocorrection (--autocorrect).
217
302
  Style/ComparableClamp:
218
303
  Exclude:
219
- - 'lib/metanorma/html/base_renderer.rb'
220
304
  - 'lib/metanorma/html/iso_renderer.rb'
305
+ - 'lib/metanorma/html/renderers/section_renderer.rb'
221
306
  - 'lib/metanorma/html/standard_renderer.rb'
222
307
 
223
308
  # Offense count: 1
224
309
  # This cop supports unsafe autocorrection (--autocorrect-all).
225
- # Configuration parameters: EnforcedStyle.
226
- # SupportedStyles: literals, strict
227
- Style/MutableConstant:
310
+ Style/PredicateWithKind:
228
311
  Exclude:
229
- - 'lib/metanorma/html/base_renderer.rb'
312
+ - 'spec/metanorma/document/components/inline/fmt_stem_element_bug03_spec.rb'
313
+
314
+ # Offense count: 2
315
+ # This cop supports unsafe autocorrection (--autocorrect-all).
316
+ Style/SelectByKind:
317
+ Exclude:
318
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
319
+
320
+ # Offense count: 3
321
+ # This cop supports safe autocorrection (--autocorrect).
322
+ # Configuration parameters: EnforcedStyleForMultiline.
323
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
324
+ Style/TrailingCommaInArguments:
325
+ Exclude:
326
+ - 'spec/metanorma/document/components/inline/semantic_content_bug05_spec.rb'
327
+ - 'spec/metanorma/document/components/inline/xref_element_bug04_spec.rb'
data/CLAUDE.md ADDED
@@ -0,0 +1,26 @@
1
+ # metanorma-document — Project Rules
2
+
3
+ ## ABSOLUTE RULE: NEVER use Nokogiri on document model XML
4
+
5
+ Document XML (presentation XML) is parsed into lutaml-model objects. All access to document content MUST go through the model object graph — typed attributes, `element_order`, `each_mixed_content`, etc.
6
+
7
+ NEVER:
8
+ - Call `to_xml` on a model object and then parse that XML with Nokogiri
9
+ - Use Nokogiri to strip, transform, or manipulate document XML content
10
+ - Use Nokogiri CSS selectors on document XML to find elements
11
+
12
+ The HTML renderer must use the model's typed attributes and the rendering pipeline (`render_paragraph`, `render_mixed_inline`, etc.) to produce HTML. Nokogiri is only acceptable for processing non-document strings (e.g., SVG logo files).
13
+
14
+ ## ABSOLUTE RULE: Use `each_mixed_content` for mixed content nodes
15
+
16
+ For any node with `mixed? == true`, you MUST use `each_mixed_content` to iterate children. This provides the full sequence of text nodes and elements in correct order.
17
+
18
+ Do NOT:
19
+ - Use only typed attributes (like `paragraphs`, `title`) for rendering — these only give mapped elements, not text nodes
20
+ - Use `element_order` for inline content — it only shows element children, not interleaved text
21
+
22
+ `render_ordered_content` uses `element_order` and is acceptable for block-level sections (which contain only element children like paragraphs and lists). But for paragraphs and inline content containers, `each_mixed_content` is mandatory.
23
+
24
+ ## ABSOLUTE RULE: No regex for HTML stripping
25
+
26
+ Never use regex (`/<[^>]+>/`) to strip HTML tags from rendered output. Text extraction must work directly on model objects via `extract_plain_text` (which walks `element_order` and typed attributes). If you need plain text from a model element, use `extract_plain_text(element)`, not `strip_html(render(element))`.
data/README.adoc CHANGED
@@ -210,6 +210,150 @@ This library targets the modern Metanorma XML format which uses `<metanorma>` as
210
210
 
211
211
  Legacy XML formats that use flavor-specific root elements (e.g. `<iso-standard>`, `<m3d-standard>`, `<csa-standard>`, `<un-standard>`) are *not supported*.
212
212
 
213
+ == Mirror Format
214
+
215
+ The `Metanorma::Mirror` module is a ProseMirror-style document model that captures the structural and inline content of a Metanorma document. It serves as an intermediate representation suitable for serialization, round-tripping, alternate rendering pipelines, and editor integrations.
216
+
217
+ The mirror format is fully model-driven: every node, mark, and document is an instance of a `Model` class. There are no hashes at the API boundary.
218
+
219
+ === Model Layer
220
+
221
+ [horizontal]
222
+ `Model::Container` :: A node with children (`#content`)
223
+ `Model::Leaf` :: A node without children (e.g. `image`, `sourcecode`)
224
+ `Model::Text` :: Inline text carrying a string and a list of `Mark`s
225
+ `Model::SoftBreak` :: A soft line break inside a paragraph
226
+ `Model::Mark` :: An inline decoration (`emphasis`, `strong`, `link`, `xref`, `eref`, `footnote`, `stem`, ...)
227
+ `Model::Guide` :: Output wrapper with `content`, `meta`, and `title`
228
+ `Model::Factory.from_h(hash)` :: Rebuilds a model graph from a serialized hash
229
+
230
+ Each model class encapsulates its attributes via bounded accessors. `Mark` exposes `[]`, `[]=`, `set_attr`, and `fetch` for safe attribute mutation. `#to_h` is the canonical serialization method.
231
+
232
+ === Forward Conversion (Metanorma → Mirror)
233
+
234
+ [source,ruby]
235
+ require "metanorma/document"
236
+ require "metanorma/mirror"
237
+
238
+ xml = File.read("spec/fixtures/iso/is/document-en.presentation.xml")
239
+ doc = Metanorma::IsoDocument::Root.from_xml(xml)
240
+
241
+ transformer = Metanorma::Mirror::Transformer.new
242
+ document = transformer.from_metanorma(doc)
243
+ document.class # => Metanorma::Mirror::Model::Container
244
+
245
+ === Reverse Conversion (Mirror → Mirror, with Rewriting)
246
+
247
+ The `Rewriter` walks a Model graph and produces a new Model graph, applying skip rules and optional per-type customization. (The historical name `MirrorToMetanorma` is no longer accurate: the output is a Model graph, not Metanorma XML. The class was renamed to `Rewriter` to reflect this.)
248
+
249
+ [source,ruby]
250
+ rewriter = Metanorma::Mirror::Rewriter.new
251
+ rebuilt = rewriter.call(document)
252
+
253
+ Each `Rewriter` instance seeds its skip set and builder map from class-level defaults at `new` time, so two instances never share state. Instance-level mutation does not leak back to the class, and class-level mutation does not retroactively affect existing instances.
254
+
255
+ [source,ruby]
256
+ # Instance API — only affects this instance
257
+ rewriter.skip("my_type")
258
+ rewriter.register("my_type") do |node, _rewriter|
259
+ Metanorma::Mirror::Model::Leaf.new(type: "customized")
260
+ end
261
+
262
+ # Class API — seeds defaults copied into future instances
263
+ Metanorma::Mirror::Rewriter.skip("always_skip")
264
+ Metanorma::Mirror::Rewriter.register("always_customize") { |n, _r| ... }
265
+
266
+ Model dispatch is polymorphic: each `Model::*` class implements `accept_rewriter(rewriter)`, which calls the matching `rewriter#rewrite_container` / `#rewrite_leaf` / `#rewrite_text` / `#rewrite_soft_break`. There is no `case/when` on node classes in the dispatch path.
267
+
268
+ === Default Handler Registry
269
+
270
+ `Metanorma::Mirror::DefaultRegistry.build` returns a fresh `HandlerRegistry` pre-populated with the standard Metanorma → Mirror mappings (paragraphs, blocks, lists, sections, terms, structural containers). It is the single source of truth for the default handler set — adding a new model-to-handler mapping is a single `register` call here, with no edits to `HandlerRegistry` itself.
271
+
272
+ [source,ruby]
273
+ Metanorma::Mirror.build_default_registry
274
+ # => #<Metanorma::Mirror::HandlerRegistry> (fresh instance each call)
275
+
276
+ === Metadata Service
277
+
278
+ `Metanorma::Mirror::Metadata` is a standalone service that extracts document metadata (title, etc.) from a parsed bibdata object. It is consumed by both the forward pipeline (`Output::Pipeline::AttachMetadata`) and the forward transformer (`MetanormaToMirror#extract_root_title`), keeping title-extraction logic in one place rather than duplicated across the Handlers layer.
279
+
280
+ [source,ruby]
281
+ Metanorma::Mirror::Metadata.title_from_bibdata(doc.bibdata)
282
+ # => "First title string"
283
+
284
+ === Serialization
285
+
286
+ Mirror documents round-trip cleanly through JSON and YAML:
287
+
288
+ [source,ruby]
289
+ json = Metanorma::Mirror::Serialization::JsonSerializer.serialize(document)
290
+ restored = Metanorma::Mirror::Serialization::JsonSerializer.deserialize(json)
291
+
292
+ === ID Strategies
293
+
294
+ ID assignment is pluggable via `Metanorma::Mirror::IdStrategy`:
295
+
296
+ [horizontal]
297
+ `IdStrategy::Preserve` :: Default. Keeps element IDs as-is.
298
+ `IdStrategy::Positional` :: Rewrites UUID-style IDs to positional IDs (`sec-X.Y.Z`, `anx-X`, `fig-N`, `table-N`) and translates cross-reference targets.
299
+
300
+ The `Positional` strategy exposes `register_category(model_class, category)` so new flavors can declare their model classes without editing dispatch code.
301
+
302
+ === HTML Rendering from Mirror
303
+
304
+ `Metanorma::Mirror::Output::HtmlRenderer` produces SSR-ready HTML directly from a mirror Model graph. Renderer behavior is split into pluggable modules registered by node type (`clause`, `paragraph`, `bullet_list`, `table`, ...) and by mark type (`emphasis`, `link`, `xref`, ...). All dispatch is registry-driven (no `case/when` on types), so new node and mark types can be added without modifying core rendering code.
305
+
306
+ All HTML construction goes through `Nokogiri::HTML4::Builder` (or `Nokogiri::HTML5::Builder` for full documents). String concatenation of HTML is not permitted anywhere in the renderer layer. The `HtmlRenderers` module exposes shared helpers (`build`, `build_fragment`, `embed`, `wrap`, `escape_text`) so each renderer stays declarative.
307
+
308
+ Node handlers are stored as `UnboundMethod`s bound to the renderer instance at dispatch time. Register a new node handler by passing an instance method reference:
309
+
310
+ [source,ruby]
311
+ module MyRenderers
312
+ def self.register(registry)
313
+ registry.register_node_handler("callout",
314
+ instance_method(:render_callout))
315
+ end
316
+
317
+ def render_callout(node, depth: 0)
318
+ HtmlRenderers.build { |doc| doc.span(class: "callout") { doc.text node.attrs["text"] } }
319
+ end
320
+ end
321
+ MyRenderers.register(Metanorma::Mirror::Output::HtmlRenderer)
322
+
323
+ Mark handlers are stored as `Proc`s that receive the already-rendered inner HTML and the `Mark` instance:
324
+
325
+ [source,ruby]
326
+ Metanorma::Mirror::Output::HtmlRenderer.register_mark_handler("kbd",
327
+ ->(inner_html, _mark) { HtmlRenderers.wrap(:kbd, inner_html) })
328
+
329
+ === Output Pipeline
330
+
331
+ `Metanorma::Mirror::Output::Pipeline` runs the full conversion: parse XML → forward transform → attach metadata. `Metanorma::Mirror::Output::Builder` orchestrates the pipeline and writes through a pluggable `Formats` registry (default: `InlineFormat`).
332
+
333
+ [source,ruby]
334
+ builder = Metanorma::Mirror::Output::Builder.new(
335
+ xml_path: "document.presentation.xml",
336
+ output_path: "output.html",
337
+ format: :inline,
338
+ flavor: "iso",
339
+ id_strategy: Metanorma::Mirror::IdStrategy::Positional.new,
340
+ )
341
+ builder.build
342
+
343
+ New formats register themselves without editing lookup code:
344
+
345
+ [source,ruby]
346
+ Metanorma::Mirror::Output::Formats.register(:pdf, MyPdfFormat)
347
+
348
+ === CLI
349
+
350
+ [source,bash]
351
+ # Convert presentation XML to mirror JSON
352
+ metanorma-document to-mirror document.presentation.xml \
353
+ -o document.mirror.json \
354
+ --id-strategy positional \
355
+ --title "My Document"
356
+
213
357
  == Documentation
214
358
 
215
359
  Detailed architecture documentation is in the `docs/` directory:
data/Rakefile CHANGED
@@ -9,6 +9,18 @@ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
12
- task default: %i[spec rubocop]
12
+ # Load custom tasks
13
+ Dir.glob("lib/tasks/*.rake").each { |task| load task }
14
+
15
+ # Build the frontend SPA (frontend/dist/)
16
+ desc "Build frontend SPA assets"
17
+ task :build_frontend do
18
+ frontend_dir = File.join(__dir__, "frontend")
19
+ puts "Building frontend..."
20
+ system("cd #{frontend_dir} && npm install && npm run build") || raise("Frontend build failed")
21
+ end
13
22
 
14
- Dir[File.join(__dir__, "tasks", "*.rake")].each { |f| import f }
23
+ # Hook into bundler's release task to ensure frontend is built
24
+ Rake::Task["release"].enhance(["build_frontend"]) if Rake::Task.task_defined?("release")
25
+
26
+ task default: %i[spec rubocop]
@@ -0,0 +1,8 @@
1
+ # 01 — Split multi-class files into one-class-per-file — DONE
2
+
3
+ All model files now contain exactly one class per file. Verified: every file under `lib/metanorma/document/`, `lib/metanorma/standard_document/`, `lib/metanorma/iso_document/`, `lib/metanorma/bipm_document/`, `lib/metanorma/itu_document/`, `lib/metanorma/ietf_document/`, `lib/metanorma/cc_document/` is single-class.
4
+
5
+ Nested classes that are only used internally by their parent (e.g. `AnnotationContainer::Annotation`) are legitimate and NOT split.
6
+
7
+ ## Code quality requirements
8
+ Ensure code cleanliness and OOP and MECE and fully model-driven, semantically-driven and open/closed principle, DRY, performance. ultrathink. Always think about what can we improve here in architecture and code? Make sure we have good specs throughout. Never use private send methods (breaks encapsulation), instance_variable_set/get, and never use respond_to? (poor typing).
@@ -0,0 +1,6 @@
1
+ # 02 — Remove misplaced `data/dist/iso_document/frontend/` artifacts — DONE
2
+
3
+ `data/dist/iso_document/frontend/` directory no longer exists. Frontend build artifacts are correctly placed in `frontend/dist/` and included in gemspec via `Dir.glob("frontend/dist/*")`.
4
+
5
+ ## Code quality requirements
6
+ Ensure code cleanliness and OOP and MECE and fully model-driven, semantically-driven and open/closed principle, DRY, performance. ultrathink. Always think about what can we improve here in architecture and code? Make sure we have good specs throughout. Never use private send methods (breaks encapsulation), instance_variable_set/get, and never use respond_to? (poor typing).
@@ -0,0 +1,11 @@
1
+ # 03 — Align frontend IIFE build and GHA gem release with docbook pattern — DONE
2
+
3
+ Aligned with docbook project:
4
+ - `Rakefile` has `build_frontend` task + release hook
5
+ - `gemspec` includes `frontend/dist/*`
6
+ - `.github/workflows/rake.yml` has `after-setup-ruby: cd frontend && npm install && npm run build`
7
+ - `frontend/vite.config.ts` produces `app.iife.js` + `app.css`
8
+ - `.gitignore` has `frontend/node_modules/` and `frontend/dist/`
9
+
10
+ ## Code quality requirements
11
+ Ensure code cleanliness and OOP and MECE and fully model-driven, semantically-driven and open/closed principle, DRY, performance. ultrathink. Always think about what can we improve here in architecture and code? Make sure we have good specs throughout. Never use private send methods (breaks encapsulation), instance_variable_set/get, and never use respond_to? (poor typing).
@@ -0,0 +1,9 @@
1
+ # 04 — Data-centric theme system: config files per flavor — DONE
2
+
3
+ All 13 flavor themes extracted to `data/themes/{flavor}.yaml`. `Theme.load(:iso)` reads YAML and applies overrides. BaseRenderer provides default `Theme.new`. Every flavor renderer uses `Theme.load(:flavor_name)`.
4
+
5
+ ### Remaining enhancement
6
+ Publisher metadata (publishers, publisher_name, logo_map, font_url) still hardcoded in flavor renderers. These should move into theme YAML config so flavor renderers can be auto-generated from config alone.
7
+
8
+ ## Code quality requirements
9
+ Ensure code cleanliness and OOP and MECE and fully model-driven, semantically-driven and open/closed principle, DRY, performance. ultrathink. Always think about what can we improve here in architecture and code? Make sure we have good specs throughout. Never use private send methods (breaks encapsulation), instance_variable_set/get, and never use respond_to? (poor typing).
@@ -0,0 +1,16 @@
1
+ # 05 — Migrate all HTML generation to Liquid templates — DONE
2
+
3
+ All HTML element generation uses Liquid templates. Zero raw HTML string injection via `@output <<` remains. The `tag()` helper has been removed from `base_renderer.rb`. All remaining `@output <<` calls are text streaming (`escape_html`, whitespace, raw content passthrough) — not HTML element generation.
4
+
5
+ 32+ Liquid templates exist in `lib/metanorma/html/templates/`. The generic `_element.html.liquid` handles most tag wrapping. Specialized templates exist for tables, lists, figures, headings, math, links, etc.
6
+
7
+ ### OOP Liquid pattern
8
+ All rendering uses the `capture_output` + `render_liquid` pattern:
9
+ 1. Capture child content into a Ruby string via `capture_output`
10
+ 2. Pass captured content to `render_liquid("_template.html.liquid", assigns)`
11
+ 3. Result is appended to `@output` by the caller
12
+
13
+ Drop classes (`Drops::*`) are used for complex objects that need pre-rendered HTML fields (e.g. `BiblioEntryDrop`, `FigureDrop`).
14
+
15
+ ## Code quality requirements
16
+ Ensure code cleanliness and OOP and MECE and fully model-driven, semantically-driven and open/closed principle, DRY, performance. ultrathink. Always think about what can we improve here in architecture and code? Make sure we have good specs throughout. Never use private send methods (breaks encapsulation), instance_variable_set/get, and never use respond_to? (poor typing).