metanorma-document 0.2.12 → 0.4.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 (194) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +3 -2
  3. data/README.adoc +1 -1
  4. data/Rakefile +30 -5
  5. data/frontend/dist/app.css +1 -0
  6. data/frontend/dist/app.iife.js +24 -0
  7. data/frontend/package-lock.json +7 -505
  8. data/frontend/tailwind.config.js +5 -0
  9. data/lib/metanorma/csa_document/root.rb +27 -0
  10. data/lib/metanorma/csa_document.rb +9 -0
  11. data/lib/metanorma/document/cli.rb +52 -0
  12. data/lib/metanorma/document/components/ancillary_blocks/sourcecode_body.rb +14 -0
  13. data/lib/metanorma/document/components/inline/comma_element.rb +3 -0
  14. data/lib/metanorma/document/components/inline/enum_comma_element.rb +3 -0
  15. data/lib/metanorma/document/components/inline/eref_element.rb +4 -1
  16. data/lib/metanorma/document/components/inline/fmt_termsource_element.rb +4 -2
  17. data/lib/metanorma/document/components/inline/math_element.rb +13 -7
  18. data/lib/metanorma/document/components/inline/semx_element.rb +7 -8
  19. data/lib/metanorma/document/components/inline/vocabulary.rb +4 -0
  20. data/lib/metanorma/document/components/multi_paragraph/admonition_block.rb +6 -1
  21. data/lib/metanorma/document/components/paragraphs/paragraph_block.rb +3 -0
  22. data/lib/metanorma/document/components/reference_elements/callout.rb +3 -2
  23. data/lib/metanorma/document/components/tables/table_cell.rb +3 -0
  24. data/lib/metanorma/document/elements/input.rb +44 -0
  25. data/lib/metanorma/document/elements.rb +1 -0
  26. data/lib/metanorma/document/relaton/address.rb +5 -0
  27. data/lib/metanorma/document/relaton/affiliation.rb +3 -0
  28. data/lib/metanorma/document/relaton/bib_item_size.rb +8 -9
  29. data/lib/metanorma/document/relaton/bib_item_type.rb +3 -0
  30. data/lib/metanorma/document/relaton/bibliographic_date.rb +5 -0
  31. data/lib/metanorma/document/relaton/contact_method.rb +5 -0
  32. data/lib/metanorma/document/relaton/contribution_info.rb +6 -2
  33. data/lib/metanorma/document/relaton/contributor.rb +4 -0
  34. data/lib/metanorma/document/relaton/contributor_role.rb +3 -0
  35. data/lib/metanorma/document/relaton/copyright_association.rb +3 -0
  36. data/lib/metanorma/document/relaton/copyright_owner.rb +3 -0
  37. data/lib/metanorma/document/relaton/date_time.rb +3 -0
  38. data/lib/metanorma/document/relaton/document_identifier.rb +4 -0
  39. data/lib/metanorma/document/relaton/document_relation.rb +8 -0
  40. data/lib/metanorma/document/relaton/document_status.rb +4 -0
  41. data/lib/metanorma/document/relaton/formatted_address.rb +4 -0
  42. data/lib/metanorma/document/relaton/full_name.rb +14 -3
  43. data/lib/metanorma/document/relaton/keyword_type.rb +3 -0
  44. data/lib/metanorma/document/relaton/locality_stack.rb +6 -9
  45. data/lib/metanorma/document/relaton/localized_name.rb +8 -5
  46. data/lib/metanorma/document/relaton/logo_element.rb +5 -0
  47. data/lib/metanorma/document/relaton/medium_type.rb +5 -16
  48. data/lib/metanorma/document/relaton/org_identifier.rb +2 -0
  49. data/lib/metanorma/document/relaton/org_subdivision.rb +2 -0
  50. data/lib/metanorma/document/relaton/org_subdivision_identifier.rb +2 -0
  51. data/lib/metanorma/document/relaton/organization.rb +3 -0
  52. data/lib/metanorma/document/relaton/person.rb +7 -1
  53. data/lib/metanorma/document/relaton/person_identifier.rb +3 -0
  54. data/lib/metanorma/document/relaton/place_type.rb +5 -0
  55. data/lib/metanorma/document/relaton/region_element.rb +3 -9
  56. data/lib/metanorma/document/relaton/relaton_collection.rb +2 -0
  57. data/lib/metanorma/document/relaton/series_type.rb +7 -0
  58. data/lib/metanorma/document/relaton/typed_note.rb +4 -0
  59. data/lib/metanorma/document/relaton/typed_title_string.rb +4 -0
  60. data/lib/metanorma/document/relaton/typed_uri.rb +3 -8
  61. data/lib/metanorma/document/relaton/validity_type.rb +8 -10
  62. data/lib/metanorma/document/relaton/variant_full_name.rb +3 -0
  63. data/lib/metanorma/document/relaton/variant_org_name.rb +3 -0
  64. data/lib/metanorma/document/relaton/version_info.rb +5 -0
  65. data/lib/metanorma/document/relaton/vocab_id_type.rb +6 -12
  66. data/lib/metanorma/document/relaton.rb +0 -14
  67. data/lib/metanorma/document/version.rb +1 -1
  68. data/lib/metanorma/document.rb +1 -0
  69. data/lib/metanorma/html/base_renderer.rb +133 -307
  70. data/lib/metanorma/html/component/base.rb +2 -9
  71. data/lib/metanorma/html/concerns/metadata_extraction.rb +61 -0
  72. data/lib/metanorma/html/concerns/presentation_validation.rb +61 -0
  73. data/lib/metanorma/html/concerns/svg_processing.rb +32 -0
  74. data/lib/metanorma/html/concerns/text_extraction.rb +93 -0
  75. data/lib/metanorma/html/concerns/toc_registry.rb +47 -0
  76. data/lib/metanorma/html/csa_renderer.rb +9 -0
  77. data/lib/metanorma/html/drops/figure_drop.rb +33 -10
  78. data/lib/metanorma/html/drops/sourcecode_drop.rb +3 -6
  79. data/lib/metanorma/html/flavor.rb +50 -0
  80. data/lib/metanorma/html/flavor_registry.rb +49 -0
  81. data/lib/metanorma/html/generator.rb +113 -29
  82. data/lib/metanorma/html/iso_renderer.rb +0 -142
  83. data/lib/metanorma/html/renderer_delegation.rb +21 -0
  84. data/lib/metanorma/html/renderers/block_renderer.rb +10 -0
  85. data/lib/metanorma/html/renderers/element_order_traversal.rb +48 -0
  86. data/lib/metanorma/html/renderers/inline_renderer.rb +49 -124
  87. data/lib/metanorma/html/renderers/pubid_renderer.rb +4 -26
  88. data/lib/metanorma/html/renderers.rb +2 -0
  89. data/lib/metanorma/html/standard_renderer.rb +198 -36
  90. data/lib/metanorma/html.rb +4 -51
  91. data/lib/metanorma/iso_document/sections/iso_preface.rb +27 -13
  92. data/lib/metanorma/mirror/default_registry.rb +21 -0
  93. data/lib/metanorma/mirror/handlers/inline/catalog.rb +52 -0
  94. data/lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb +34 -35
  95. data/lib/metanorma/mirror/handlers/inline.rb +1 -0
  96. data/lib/metanorma/mirror/handlers/sourcecode.rb +1 -1
  97. data/lib/metanorma/mirror/model/guide.rb +3 -2
  98. data/lib/metanorma/mirror/output/formats/inline_format.rb +64 -3
  99. data/lib/metanorma/mirror/output/pipeline.rb +1 -0
  100. data/lib/metanorma/mirror/output.rb +0 -2
  101. data/lib/metanorma/mirror/rewriter.rb +3 -1
  102. data/lib/metanorma/mirror/transformer.rb +91 -3
  103. data/lib/metanorma/mirror.rb +0 -1
  104. data/lib/metanorma/registers/setup.rb +10 -0
  105. data/lib/metanorma/standard_document/annotation_container.rb +2 -0
  106. data/lib/metanorma/standard_document/elements/input.rb +4 -25
  107. data/lib/metanorma/standard_document/metadata/metanorma_extension.rb +12 -2
  108. data/lib/metanorma/standard_document/metadata/presentation_metadata.rb +107 -0
  109. data/lib/metanorma/standard_document/metadata/semantic_metadata.rb +18 -0
  110. data/lib/metanorma/standard_document/metadata/unitsml/amount_of_substance.rb +19 -0
  111. data/lib/metanorma/standard_document/metadata/unitsml/base_quantity.rb +34 -0
  112. data/lib/metanorma/standard_document/metadata/unitsml/dimension.rb +39 -0
  113. data/lib/metanorma/standard_document/metadata/unitsml/dimension_set.rb +19 -0
  114. data/lib/metanorma/standard_document/metadata/unitsml/electric_current.rb +19 -0
  115. data/lib/metanorma/standard_document/metadata/unitsml/enumerated_root_unit.rb +23 -0
  116. data/lib/metanorma/standard_document/metadata/unitsml/length.rb +19 -0
  117. data/lib/metanorma/standard_document/metadata/unitsml/luminous_intensity.rb +19 -0
  118. data/lib/metanorma/standard_document/metadata/unitsml/mass.rb +19 -0
  119. data/lib/metanorma/standard_document/metadata/unitsml/namespace.rb +17 -0
  120. data/lib/metanorma/standard_document/metadata/unitsml/plane_angle.rb +19 -0
  121. data/lib/metanorma/standard_document/metadata/unitsml/prefix.rb +30 -0
  122. data/lib/metanorma/standard_document/metadata/unitsml/prefix_name.rb +21 -0
  123. data/lib/metanorma/standard_document/metadata/unitsml/prefix_set.rb +19 -0
  124. data/lib/metanorma/standard_document/metadata/unitsml/prefix_symbol.rb +21 -0
  125. data/lib/metanorma/standard_document/metadata/unitsml/quantity.rb +28 -0
  126. data/lib/metanorma/standard_document/metadata/unitsml/quantity_name.rb +21 -0
  127. data/lib/metanorma/standard_document/metadata/unitsml/quantity_set.rb +19 -0
  128. data/lib/metanorma/standard_document/metadata/unitsml/root_units.rb +19 -0
  129. data/lib/metanorma/standard_document/metadata/unitsml/thermodynamic_temperature.rb +19 -0
  130. data/lib/metanorma/standard_document/metadata/unitsml/time.rb +19 -0
  131. data/lib/metanorma/standard_document/metadata/unitsml/unit.rb +32 -0
  132. data/lib/metanorma/standard_document/metadata/unitsml/unit_name.rb +21 -0
  133. data/lib/metanorma/standard_document/metadata/unitsml/unit_set.rb +19 -0
  134. data/lib/metanorma/standard_document/metadata/unitsml/unit_symbol.rb +36 -0
  135. data/lib/metanorma/standard_document/metadata/unitsml/unit_system.rb +23 -0
  136. data/lib/metanorma/standard_document/metadata/unitsml/unitsml_root.rb +28 -0
  137. data/lib/metanorma/standard_document/metadata/unitsml.rb +39 -0
  138. data/lib/metanorma/standard_document/metadata.rb +4 -0
  139. data/lib/metanorma/standard_document/sections/misc_container.rb +8 -6
  140. data/lib/metanorma/standard_document/sections/sections.rb +7 -0
  141. data/lib/metanorma/un_document/blocks/un_admonition_block.rb +86 -0
  142. data/lib/metanorma/un_document/blocks.rb +9 -0
  143. data/lib/metanorma/un_document/root.rb +8 -0
  144. data/lib/metanorma/un_document/sections/un_abstract_section.rb +48 -0
  145. data/lib/metanorma/un_document/sections/un_preface.rb +19 -2
  146. data/lib/metanorma/un_document/sections.rb +1 -0
  147. data/lib/metanorma/un_document/un_text_element.rb +116 -0
  148. data/lib/metanorma/un_document.rb +2 -0
  149. data/script/benchmark_render.rb +35 -0
  150. data/tasks/roundtrip_samples.rake +1 -1
  151. metadata +78 -50
  152. data/.rubocop_todo.yml +0 -327
  153. data/TODO.finalize/01-split-multi-class-files.md +0 -8
  154. data/TODO.finalize/02-remove-data-dist-iso-document-frontend.md +0 -6
  155. data/TODO.finalize/03-align-frontend-iife-and-gha-build.md +0 -11
  156. data/TODO.finalize/04-theme-per-flavor-config-driven.md +0 -9
  157. data/TODO.finalize/05-migrate-all-html-to-liquid.md +0 -16
  158. data/TODO.finalize/06-integrate-pubid-library.md +0 -16
  159. data/TODO.finalize/07-replace-relaton-models-with-relaton-bib.md +0 -39
  160. data/TODO.finalize/08-refactor-renderer-architecture.md +0 -25
  161. data/TODO.finalize/09-eliminate-code-smells.md +0 -14
  162. data/TODO.finalize/10-comprehensive-spec-coverage.md +0 -24
  163. data/TODO.finalize/11-config-driven-flavor-metadata.md +0 -20
  164. data/TODO.finalize/12-add-frozen-string-literal.md +0 -6
  165. data/TODO.finalize/13-extract-composition-from-god-class.md +0 -96
  166. data/TODO.finalize/14-config-driven-section-ordering.md +0 -31
  167. data/TODO.finalize/15-theme-directories-per-flavor.md +0 -46
  168. data/TODO.finalize/16-theme-lutaml-model-schema.md +0 -44
  169. data/docs/html-renderer.adoc +0 -261
  170. data/lib/data/dist/iso_document/frontend/assets/index-mwzbzmnK.js +0 -22
  171. data/lib/data/dist/iso_document/frontend/assets/index-pGvKTNid.css +0 -1
  172. data/lib/data/dist/iso_document/frontend/assets/iso-red.svg +0 -53
  173. data/lib/data/dist/iso_document/frontend/index.html +0 -13
  174. data/lib/metanorma/document/relaton/bib_item_size_type.rb +0 -21
  175. data/lib/metanorma/document/relaton/bibliographic_date_type.rb +0 -22
  176. data/lib/metanorma/document/relaton/document_relation_type.rb +0 -31
  177. data/lib/metanorma/document/relaton/iso4217_code.rb +0 -17
  178. data/lib/metanorma/document/relaton/iso8601_date.rb +0 -17
  179. data/lib/metanorma/document/relaton/personal_identifier_type.rb +0 -21
  180. data/lib/metanorma/document/relaton/region_type.rb +0 -20
  181. data/lib/metanorma/document/relaton/series_type_type.rb +0 -21
  182. data/lib/metanorma/document/relaton/specific_locality_type.rb +0 -25
  183. data/lib/metanorma/document/relaton/title_type.rb +0 -21
  184. data/lib/metanorma/mirror/metanorma_to_mirror.rb +0 -101
  185. data/lib/metanorma/mirror/output/html_renderer.rb +0 -95
  186. data/lib/metanorma/mirror/output/html_renderers/block_renderers.rb +0 -178
  187. data/lib/metanorma/mirror/output/html_renderers/inline_renderer.rb +0 -61
  188. data/lib/metanorma/mirror/output/html_renderers/list_renderers.rb +0 -96
  189. data/lib/metanorma/mirror/output/html_renderers/mark_renderers.rb +0 -64
  190. data/lib/metanorma/mirror/output/html_renderers/section_renderers.rb +0 -129
  191. data/lib/metanorma/mirror/output/html_renderers/structural_renderers.rb +0 -80
  192. data/lib/metanorma/mirror/output/html_renderers/table_renderers.rb +0 -87
  193. data/lib/metanorma/mirror/output/html_renderers.rb +0 -76
  194. data/lib/metanorma/standard_document/annotation.rb +0 -37
@@ -18,6 +18,14 @@ module Metanorma
18
18
  Metanorma::StandardDocument::Sections::AnnexSection,
19
19
  collection: true
20
20
 
21
+ # Validates the parsed document against the UN grammar restrictions
22
+ # the model does not enforce structurally (currently: the UN
23
+ # TextElement inline subset). Walks the model graph and returns an
24
+ # array of error strings; empty when the document is valid.
25
+ def grammar_errors
26
+ Metanorma::UnDocument::UnTextElement.validate(self)
27
+ end
28
+
21
29
  xml do
22
30
  element "metanorma"
23
31
  namespace Metanorma::StandardDocument::Namespace
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module UnDocument
5
+ module Sections
6
+ # Abstract of a UN document.
7
+ # Corresponds to un.rng:
8
+ # abstract = element abstract { Basic-Section }
9
+ # Basic-Section = Basic-Section-Attributes, section-title?, BasicBlock+
10
+ # Unlike the isodoc default (Content-Section), a UN abstract contains
11
+ # no subsections, so no `clause` mapping is declared. Composed from the
12
+ # shared mixins rather than inheriting ContentSection, because
13
+ # lutaml-model deep-duplicates a parent's XML mappings into subclasses
14
+ # (inheriting would keep the Content-Section `clause` mapping).
15
+ class UnAbstractSection < Lutaml::Model::Serializable
16
+ include Metanorma::StandardDocument::BlockAttributes
17
+ include Metanorma::StandardDocument::PresentationAttributes
18
+
19
+ attribute :id, :string
20
+ attribute :obligation, :string
21
+ attribute :title,
22
+ Metanorma::Document::Components::Inline::TitleWithAnnotationElement
23
+
24
+ xml do
25
+ element "abstract"
26
+ ordered
27
+
28
+ map_attribute "id", to: :id
29
+ map_attribute "obligation", to: :obligation
30
+ map_attribute "anchor", to: :anchor
31
+ map_attribute "semx-id", to: :semx_id
32
+ map_attribute "autonum", to: :autonum
33
+ map_attribute "displayorder", to: :displayorder
34
+
35
+ map_element "title", to: :title
36
+ map_element "variant-title", to: :variant_title
37
+ map_element "fmt-title", to: :fmt_title
38
+ map_element "fmt-xref-label", to: :fmt_xref_label
39
+
40
+ Metanorma::StandardDocument::BlockXmlMapping.apply_block_mappings(self)
41
+
42
+ map_element "fmt-annotation-start", to: :fmt_annotation_start
43
+ map_element "fmt-annotation-end", to: :fmt_annotation_end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -4,9 +4,26 @@ module Metanorma
4
4
  module UnDocument
5
5
  module Sections
6
6
  # UN preface with only abstract, foreword, introduction.
7
- # Corresponds to un.rnc:
7
+ # Corresponds to un.rng:
8
8
  # preface = element preface { abstract?, foreword?, introduction? }
9
- class UnPreface < Metanorma::StandardDocument::Sections::Preface
9
+ #
10
+ # This class deliberately does NOT inherit StandardDocument::Preface:
11
+ # lutaml-model deep-duplicates a parent's XML mappings into subclasses,
12
+ # so inheriting would keep the isodoc-level acknowledgements,
13
+ # executivesummary and clause mappings that the UN grammar forbids.
14
+ # Attributes are composed directly instead.
15
+ #
16
+ # The UN abstract is a Basic-Section (UnAbstractSection); foreword and
17
+ # introduction keep the isodoc Content-Section model.
18
+ class UnPreface < Lutaml::Model::Serializable
19
+ attribute :abstract, UnAbstractSection
20
+ attribute :foreword, Metanorma::StandardDocument::Sections::ContentSection
21
+ attribute :introduction, Metanorma::StandardDocument::Sections::ContentSection
22
+
23
+ # Presentation-specific attributes
24
+ attribute :semx_id, :string
25
+ attribute :displayorder, :integer
26
+
10
27
  xml do
11
28
  element "preface"
12
29
  ordered
@@ -3,6 +3,7 @@
3
3
  module Metanorma
4
4
  module UnDocument
5
5
  module Sections
6
+ autoload :UnAbstractSection, "#{__dir__}/sections/un_abstract_section"
6
7
  autoload :UnPreface, "#{__dir__}/sections/un_preface"
7
8
  autoload :UnSections, "#{__dir__}/sections/un_sections"
8
9
  end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module UnDocument
5
+ # UN TextElement restriction, per the current UN grammar
6
+ # (metanorma-un, lib/metanorma/un/un.rng v1.2.1):
7
+ #
8
+ # TextElement = text | em | eref | erefstack | strong | stem | sub |
9
+ # sup | tt | strike | smallcap | xref | br | hyperlink |
10
+ # bookmark
11
+ #
12
+ # UN allows only a strict subset of the isodoc inline vocabulary.
13
+ # Enforcing this structurally would require a UN-specific variant of every
14
+ # block type carrying inline content; instead this module validates the
15
+ # parsed model graph, flagging instances of excluded inline element
16
+ # classes found in inline content.
17
+ #
18
+ # Grammar-inline productions with no model class (date_inline) cannot be
19
+ # flagged here; the parser drops them before validation can see them.
20
+ module UnTextElement
21
+ # Inline element names (grammar names) permitted in UN inline content.
22
+ # `hyperlink` is the grammar production for the `<link>` element.
23
+ ALLOWED_ELEMENTS = %w[
24
+ em eref erefstack strong stem sub sup tt strike smallcap
25
+ xref br link bookmark
26
+ ].freeze
27
+
28
+ # Model classes of the isodoc TextElement productions the UN grammar
29
+ # excludes, mapped to their grammar (XML element) names.
30
+ EXCLUDED_ELEMENTS = {
31
+ Metanorma::Document::Components::TextElements::UnderlineElement => "underline",
32
+ Metanorma::Document::Components::TextElements::KeywordElement => "keyword",
33
+ Metanorma::Document::Components::TextElements::RubyElement => "ruby",
34
+ Metanorma::Document::Components::EmptyElements::HorizontalRuleElement => "hr",
35
+ Metanorma::Document::Components::EmptyElements::PageBreakElement => "pagebreak",
36
+ Metanorma::Document::Components::IdElements::Image => "image",
37
+ Metanorma::Document::Components::EmptyElements::IndexElement => "index",
38
+ Metanorma::Document::Components::ReferenceElements::IndexXrefElement => "index-xref",
39
+ Metanorma::Document::Components::Inline::ConceptElement => "concept",
40
+ Metanorma::Document::Elements::Add => "add",
41
+ Metanorma::Document::Elements::Del => "del",
42
+ Metanorma::Document::Components::Inline::SpanElement => "span",
43
+ }.freeze
44
+
45
+ # Model classes whose content model is inline text; an excluded instance
46
+ # under one of these is an inline use. Block-level occurrences (e.g.
47
+ # Image under FigureBlock, PageBreakElement under ClauseSection) are
48
+ # legal. ParagraphWithFootnote inherits from ParagraphBlock.
49
+ INLINE_CONTAINERS = [
50
+ Metanorma::Document::Components::Paragraphs::ParagraphBlock,
51
+ Metanorma::Document::Components::Inline::TitleWithAnnotationElement,
52
+ Metanorma::Document::Components::Inline::VariantTitleElement,
53
+ Metanorma::Document::Components::TextElements::TextElement,
54
+ Metanorma::Document::Components::Lists::DtElement,
55
+ Metanorma::Document::Components::Tables::TableCell,
56
+ ].freeze
57
+
58
+ # fmt-* classes wrap presentation-rendered copies of content, where
59
+ # `<span>` is rendering furniture rather than semantic inline markup.
60
+ FURNITURE_CLASS_PATTERN = /(^|::)Fmt/
61
+
62
+ # Returns an array of human-readable error strings for every excluded
63
+ # inline element instance in the given model tree; empty when valid.
64
+ def self.validate(model)
65
+ errors = []
66
+ walk(model, false, errors, {}.compare_by_identity)
67
+ errors
68
+ end
69
+
70
+ def self.walk(node, inline, errors, visited)
71
+ return unless node.is_a?(Lutaml::Model::Serializable)
72
+ return if visited[node]
73
+
74
+ visited[node] = true
75
+
76
+ furniture = furniture?(node)
77
+ excluded = furniture ? nil : excluded_name(node)
78
+ if inline && excluded
79
+ errors << "UN grammar forbids <#{excluded}> in inline " \
80
+ "content (#{node.class.name})"
81
+ end
82
+
83
+ child_inline = furniture ? false : inline || inline_container?(node)
84
+ each_child(node) { |child| walk(child, child_inline, errors, visited) }
85
+ end
86
+
87
+ # Iterates the model-valued children of a node. Attribute values are
88
+ # read via instance_variable_get, mirroring lutaml-model's own
89
+ # attribute access (Serialize#validate_attribute!) — the project's
90
+ # invariant specs forbid dynamic dispatch methods in model code.
91
+ def self.each_child(node)
92
+ node.class.attributes.each_key do |name|
93
+ value = node.instance_variable_get(:"@#{name}")
94
+ if value.is_a?(Enumerable) && !value.is_a?(String)
95
+ value.each { |item| yield item if item.is_a?(Lutaml::Model::Serializable) }
96
+ elsif value.is_a?(Lutaml::Model::Serializable)
97
+ yield value
98
+ end
99
+ end
100
+ end
101
+
102
+ def self.excluded_name(node)
103
+ pair = EXCLUDED_ELEMENTS.find { |klass, _| node.is_a?(klass) }
104
+ pair&.last
105
+ end
106
+
107
+ def self.inline_container?(node)
108
+ INLINE_CONTAINERS.any? { |klass| node.is_a?(klass) }
109
+ end
110
+
111
+ def self.furniture?(node)
112
+ FURNITURE_CLASS_PATTERN.match?(node.class.name)
113
+ end
114
+ end
115
+ end
116
+ end
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Metanorma
4
4
  module UnDocument
5
+ autoload :Blocks, "metanorma/un_document/blocks"
5
6
  autoload :Metadata, "metanorma/un_document/metadata"
6
7
  autoload :Root, "metanorma/un_document/root"
7
8
  autoload :Sections, "metanorma/un_document/sections"
9
+ autoload :UnTextElement, "metanorma/un_document/un_text_element"
8
10
  end
9
11
  end
10
12
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Benchmark: parse + HTML-render a presentation XML fixture.
4
+ #
5
+ # Usage:
6
+ # bundle install # benchmark-ips is a dev dependency
7
+ # bundle exec ruby script/benchmark_render.rb [fixture.xml]
8
+
9
+ require "benchmark/ips"
10
+ require_relative "../lib/metanorma/document"
11
+ require_relative "../lib/metanorma/html"
12
+
13
+ fixture = ARGV[0] ||
14
+ File.expand_path("../spec/fixtures/iso/is/document-en.presentation.xml",
15
+ __dir__)
16
+ xml = File.read(fixture)
17
+ puts "Fixture: #{fixture} (#{(xml.size / 1024.0).round(1)} KB)"
18
+
19
+ doc = Metanorma::IsoDocument::Root.from_xml(xml)
20
+ html = Metanorma::Html::Generator.generate(doc)
21
+ puts "Sanity: rendered #{html.size} bytes of HTML"
22
+
23
+ Benchmark.ips do |x|
24
+ x.config(time: 5, warmup: 1)
25
+
26
+ x.report("parse") do
27
+ Metanorma::IsoDocument::Root.from_xml(xml)
28
+ end
29
+
30
+ x.report("render") do
31
+ Metanorma::Html::Generator.generate(doc)
32
+ end
33
+
34
+ x.compare!
35
+ end
@@ -49,7 +49,7 @@ module RoundtripSamples
49
49
  "ogc" => Metanorma::OgcDocument::Root,
50
50
  "ribose" => Metanorma::RiboseDocument::Root,
51
51
  "ietf" => Metanorma::IetfDocument::Root,
52
- "csa" => nil,
52
+ "csa" => Metanorma::CsaDocument::Root,
53
53
  "un" => nil,
54
54
  }.freeze
55
55
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-document
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.12
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-17 00:00:00.000000000 Z
11
+ date: 2026-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: mml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: pubid
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +56,22 @@ dependencies:
42
56
  name: relaton-bib
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '2.1'
61
+ version: 2.2.0.pre.alpha.1
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: 2.3.0
48
65
  type: :runtime
49
66
  prerelease: false
50
67
  version_requirements: !ruby/object:Gem::Requirement
51
68
  requirements:
52
- - - "~>"
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 2.2.0.pre.alpha.1
72
+ - - "<"
53
73
  - !ruby/object:Gem::Version
54
- version: '2.1'
74
+ version: 2.3.0
55
75
  description: A Ruby library for representing and processing Metanorma document XML,
56
76
  providing a comprehensive model for standards documents with support for various
57
77
  metadata, content blocks, and structured markup.
@@ -62,28 +82,11 @@ executables:
62
82
  extensions: []
63
83
  extra_rdoc_files: []
64
84
  files:
65
- - ".rubocop_todo.yml"
66
85
  - CHANGELOG.md
67
86
  - CLAUDE.md
68
87
  - LICENSE.txt
69
88
  - README.adoc
70
89
  - Rakefile
71
- - TODO.finalize/01-split-multi-class-files.md
72
- - TODO.finalize/02-remove-data-dist-iso-document-frontend.md
73
- - TODO.finalize/03-align-frontend-iife-and-gha-build.md
74
- - TODO.finalize/04-theme-per-flavor-config-driven.md
75
- - TODO.finalize/05-migrate-all-html-to-liquid.md
76
- - TODO.finalize/06-integrate-pubid-library.md
77
- - TODO.finalize/07-replace-relaton-models-with-relaton-bib.md
78
- - TODO.finalize/08-refactor-renderer-architecture.md
79
- - TODO.finalize/09-eliminate-code-smells.md
80
- - TODO.finalize/10-comprehensive-spec-coverage.md
81
- - TODO.finalize/11-config-driven-flavor-metadata.md
82
- - TODO.finalize/12-add-frozen-string-literal.md
83
- - TODO.finalize/13-extract-composition-from-god-class.md
84
- - TODO.finalize/14-config-driven-section-ordering.md
85
- - TODO.finalize/15-theme-directories-per-flavor.md
86
- - TODO.finalize/16-theme-lutaml-model-schema.md
87
90
  - data/javascripts/components/mn-code-copy.js
88
91
  - data/javascripts/components/mn-footnotes.js
89
92
  - data/javascripts/components/mn-glossary.js
@@ -152,8 +155,9 @@ files:
152
155
  - data/themes/oiml.yaml
153
156
  - data/themes/pdfa.yaml
154
157
  - data/themes/ribose.yaml
155
- - docs/html-renderer.adoc
156
158
  - exe/metanorma-document
159
+ - frontend/dist/app.css
160
+ - frontend/dist/app.iife.js
157
161
  - frontend/e2e/sample-html.test.ts
158
162
  - frontend/index.html
159
163
  - frontend/package-lock.json
@@ -202,10 +206,6 @@ files:
202
206
  - frontend/tsconfig.node.json
203
207
  - frontend/vite.config.ts
204
208
  - frontend/vitest.e2e.config.ts
205
- - lib/data/dist/iso_document/frontend/assets/index-mwzbzmnK.js
206
- - lib/data/dist/iso_document/frontend/assets/index-pGvKTNid.css
207
- - lib/data/dist/iso_document/frontend/assets/iso-red.svg
208
- - lib/data/dist/iso_document/frontend/index.html
209
209
  - lib/metanorma/basic_document.rb
210
210
  - lib/metanorma/basic_document/ancillary_blocks.rb
211
211
  - lib/metanorma/basic_document/ancillary_blocks/example_block.rb
@@ -355,6 +355,8 @@ files:
355
355
  - lib/metanorma/collection/doc_container.rb
356
356
  - lib/metanorma/collection/entry.rb
357
357
  - lib/metanorma/collection/root.rb
358
+ - lib/metanorma/csa_document.rb
359
+ - lib/metanorma/csa_document/root.rb
358
360
  - lib/metanorma/document.rb
359
361
  - lib/metanorma/document/cli.rb
360
362
  - lib/metanorma/document/components.rb
@@ -564,15 +566,14 @@ files:
564
566
  - lib/metanorma/document/elements.rb
565
567
  - lib/metanorma/document/elements/add.rb
566
568
  - lib/metanorma/document/elements/del.rb
569
+ - lib/metanorma/document/elements/input.rb
567
570
  - lib/metanorma/document/relaton.rb
568
571
  - lib/metanorma/document/relaton/address.rb
569
572
  - lib/metanorma/document/relaton/affiliation.rb
570
573
  - lib/metanorma/document/relaton/bib_item_locality.rb
571
574
  - lib/metanorma/document/relaton/bib_item_size.rb
572
- - lib/metanorma/document/relaton/bib_item_size_type.rb
573
575
  - lib/metanorma/document/relaton/bib_item_type.rb
574
576
  - lib/metanorma/document/relaton/bibliographic_date.rb
575
- - lib/metanorma/document/relaton/bibliographic_date_type.rb
576
577
  - lib/metanorma/document/relaton/contact_method.rb
577
578
  - lib/metanorma/document/relaton/contribution_info.rb
578
579
  - lib/metanorma/document/relaton/contributor.rb
@@ -582,13 +583,10 @@ files:
582
583
  - lib/metanorma/document/relaton/date_time.rb
583
584
  - lib/metanorma/document/relaton/document_identifier.rb
584
585
  - lib/metanorma/document/relaton/document_relation.rb
585
- - lib/metanorma/document/relaton/document_relation_type.rb
586
586
  - lib/metanorma/document/relaton/document_status.rb
587
587
  - lib/metanorma/document/relaton/edition.rb
588
588
  - lib/metanorma/document/relaton/formatted_address.rb
589
589
  - lib/metanorma/document/relaton/full_name.rb
590
- - lib/metanorma/document/relaton/iso4217_code.rb
591
- - lib/metanorma/document/relaton/iso8601_date.rb
592
590
  - lib/metanorma/document/relaton/keyword_type.rb
593
591
  - lib/metanorma/document/relaton/locality_stack.rb
594
592
  - lib/metanorma/document/relaton/localized_name.rb
@@ -600,17 +598,12 @@ files:
600
598
  - lib/metanorma/document/relaton/organization.rb
601
599
  - lib/metanorma/document/relaton/person.rb
602
600
  - lib/metanorma/document/relaton/person_identifier.rb
603
- - lib/metanorma/document/relaton/personal_identifier_type.rb
604
601
  - lib/metanorma/document/relaton/phone.rb
605
602
  - lib/metanorma/document/relaton/place_type.rb
606
603
  - lib/metanorma/document/relaton/price_type.rb
607
604
  - lib/metanorma/document/relaton/region_element.rb
608
- - lib/metanorma/document/relaton/region_type.rb
609
605
  - lib/metanorma/document/relaton/relaton_collection.rb
610
606
  - lib/metanorma/document/relaton/series_type.rb
611
- - lib/metanorma/document/relaton/series_type_type.rb
612
- - lib/metanorma/document/relaton/specific_locality_type.rb
613
- - lib/metanorma/document/relaton/title_type.rb
614
607
  - lib/metanorma/document/relaton/typed_note.rb
615
608
  - lib/metanorma/document/relaton/typed_title_string.rb
616
609
  - lib/metanorma/document/relaton/typed_uri.rb
@@ -638,6 +631,12 @@ files:
638
631
  - lib/metanorma/html/component/footnote_collector.rb
639
632
  - lib/metanorma/html/component/index_section.rb
640
633
  - lib/metanorma/html/component/index_term_collector.rb
634
+ - lib/metanorma/html/concerns/metadata_extraction.rb
635
+ - lib/metanorma/html/concerns/presentation_validation.rb
636
+ - lib/metanorma/html/concerns/svg_processing.rb
637
+ - lib/metanorma/html/concerns/text_extraction.rb
638
+ - lib/metanorma/html/concerns/toc_registry.rb
639
+ - lib/metanorma/html/csa_renderer.rb
641
640
  - lib/metanorma/html/drops.rb
642
641
  - lib/metanorma/html/drops/admonition_drop.rb
643
642
  - lib/metanorma/html/drops/biblio_entry_drop.rb
@@ -650,6 +649,8 @@ files:
650
649
  - lib/metanorma/html/drops/note_drop.rb
651
650
  - lib/metanorma/html/drops/sourcecode_drop.rb
652
651
  - lib/metanorma/html/drops/toc_entry_drop.rb
652
+ - lib/metanorma/html/flavor.rb
653
+ - lib/metanorma/html/flavor_registry.rb
653
654
  - lib/metanorma/html/generator.rb
654
655
  - lib/metanorma/html/icc_renderer.rb
655
656
  - lib/metanorma/html/iec_renderer.rb
@@ -661,8 +662,10 @@ files:
661
662
  - lib/metanorma/html/ogc_renderer.rb
662
663
  - lib/metanorma/html/oiml_renderer.rb
663
664
  - lib/metanorma/html/pdfa_renderer.rb
665
+ - lib/metanorma/html/renderer_delegation.rb
664
666
  - lib/metanorma/html/renderers.rb
665
667
  - lib/metanorma/html/renderers/block_renderer.rb
668
+ - lib/metanorma/html/renderers/element_order_traversal.rb
666
669
  - lib/metanorma/html/renderers/inline_renderer.rb
667
670
  - lib/metanorma/html/renderers/pubid_renderer.rb
668
671
  - lib/metanorma/html/renderers/section_renderer.rb
@@ -842,6 +845,7 @@ files:
842
845
  - lib/metanorma/mirror/handlers/figure.rb
843
846
  - lib/metanorma/mirror/handlers/formula.rb
844
847
  - lib/metanorma/mirror/handlers/inline.rb
848
+ - lib/metanorma/mirror/handlers/inline/catalog.rb
845
849
  - lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb
846
850
  - lib/metanorma/mirror/handlers/inline/text_extractor.rb
847
851
  - lib/metanorma/mirror/handlers/list.rb
@@ -859,7 +863,6 @@ files:
859
863
  - lib/metanorma/mirror/id_strategy/preserve.rb
860
864
  - lib/metanorma/mirror/math_util.rb
861
865
  - lib/metanorma/mirror/metadata.rb
862
- - lib/metanorma/mirror/metanorma_to_mirror.rb
863
866
  - lib/metanorma/mirror/model.rb
864
867
  - lib/metanorma/mirror/model/container.rb
865
868
  - lib/metanorma/mirror/model/factory.rb
@@ -874,15 +877,6 @@ files:
874
877
  - lib/metanorma/mirror/output/formats.rb
875
878
  - lib/metanorma/mirror/output/formats/base_format.rb
876
879
  - lib/metanorma/mirror/output/formats/inline_format.rb
877
- - lib/metanorma/mirror/output/html_renderer.rb
878
- - lib/metanorma/mirror/output/html_renderers.rb
879
- - lib/metanorma/mirror/output/html_renderers/block_renderers.rb
880
- - lib/metanorma/mirror/output/html_renderers/inline_renderer.rb
881
- - lib/metanorma/mirror/output/html_renderers/list_renderers.rb
882
- - lib/metanorma/mirror/output/html_renderers/mark_renderers.rb
883
- - lib/metanorma/mirror/output/html_renderers/section_renderers.rb
884
- - lib/metanorma/mirror/output/html_renderers/structural_renderers.rb
885
- - lib/metanorma/mirror/output/html_renderers/table_renderers.rb
886
880
  - lib/metanorma/mirror/output/pipeline.rb
887
881
  - lib/metanorma/mirror/output/pipeline_context.rb
888
882
  - lib/metanorma/mirror/rewriter.rb
@@ -920,7 +914,6 @@ files:
920
914
  - lib/metanorma/ribose_document/metadata/ribose_bibliographic_item.rb
921
915
  - lib/metanorma/ribose_document/root.rb
922
916
  - lib/metanorma/standard_document.rb
923
- - lib/metanorma/standard_document/annotation.rb
924
917
  - lib/metanorma/standard_document/annotation_container.rb
925
918
  - lib/metanorma/standard_document/block_attributes.rb
926
919
  - lib/metanorma/standard_document/blocks.rb
@@ -978,10 +971,40 @@ files:
978
971
  - lib/metanorma/standard_document/metadata/editorial_group_type.rb
979
972
  - lib/metanorma/standard_document/metadata/ics_type.rb
980
973
  - lib/metanorma/standard_document/metadata/metanorma_extension.rb
974
+ - lib/metanorma/standard_document/metadata/presentation_metadata.rb
975
+ - lib/metanorma/standard_document/metadata/semantic_metadata.rb
981
976
  - lib/metanorma/standard_document/metadata/standard_bib_data.rb
982
977
  - lib/metanorma/standard_document/metadata/standard_bib_data_extension_type.rb
983
978
  - lib/metanorma/standard_document/metadata/structured_identifier_type.rb
984
979
  - lib/metanorma/standard_document/metadata/technical_committee_type.rb
980
+ - lib/metanorma/standard_document/metadata/unitsml.rb
981
+ - lib/metanorma/standard_document/metadata/unitsml/amount_of_substance.rb
982
+ - lib/metanorma/standard_document/metadata/unitsml/base_quantity.rb
983
+ - lib/metanorma/standard_document/metadata/unitsml/dimension.rb
984
+ - lib/metanorma/standard_document/metadata/unitsml/dimension_set.rb
985
+ - lib/metanorma/standard_document/metadata/unitsml/electric_current.rb
986
+ - lib/metanorma/standard_document/metadata/unitsml/enumerated_root_unit.rb
987
+ - lib/metanorma/standard_document/metadata/unitsml/length.rb
988
+ - lib/metanorma/standard_document/metadata/unitsml/luminous_intensity.rb
989
+ - lib/metanorma/standard_document/metadata/unitsml/mass.rb
990
+ - lib/metanorma/standard_document/metadata/unitsml/namespace.rb
991
+ - lib/metanorma/standard_document/metadata/unitsml/plane_angle.rb
992
+ - lib/metanorma/standard_document/metadata/unitsml/prefix.rb
993
+ - lib/metanorma/standard_document/metadata/unitsml/prefix_name.rb
994
+ - lib/metanorma/standard_document/metadata/unitsml/prefix_set.rb
995
+ - lib/metanorma/standard_document/metadata/unitsml/prefix_symbol.rb
996
+ - lib/metanorma/standard_document/metadata/unitsml/quantity.rb
997
+ - lib/metanorma/standard_document/metadata/unitsml/quantity_name.rb
998
+ - lib/metanorma/standard_document/metadata/unitsml/quantity_set.rb
999
+ - lib/metanorma/standard_document/metadata/unitsml/root_units.rb
1000
+ - lib/metanorma/standard_document/metadata/unitsml/thermodynamic_temperature.rb
1001
+ - lib/metanorma/standard_document/metadata/unitsml/time.rb
1002
+ - lib/metanorma/standard_document/metadata/unitsml/unit.rb
1003
+ - lib/metanorma/standard_document/metadata/unitsml/unit_name.rb
1004
+ - lib/metanorma/standard_document/metadata/unitsml/unit_set.rb
1005
+ - lib/metanorma/standard_document/metadata/unitsml/unit_symbol.rb
1006
+ - lib/metanorma/standard_document/metadata/unitsml/unit_system.rb
1007
+ - lib/metanorma/standard_document/metadata/unitsml/unitsml_root.rb
985
1008
  - lib/metanorma/standard_document/namespace.rb
986
1009
  - lib/metanorma/standard_document/refs.rb
987
1010
  - lib/metanorma/standard_document/refs/reference_to_term.rb
@@ -1042,13 +1065,18 @@ files:
1042
1065
  - lib/metanorma/standard_document/terms/term_source_type.rb
1043
1066
  - lib/metanorma/standard_document/terms/verbal_expression.rb
1044
1067
  - lib/metanorma/un_document.rb
1068
+ - lib/metanorma/un_document/blocks.rb
1069
+ - lib/metanorma/un_document/blocks/un_admonition_block.rb
1045
1070
  - lib/metanorma/un_document/metadata.rb
1046
1071
  - lib/metanorma/un_document/metadata/un_bib_data_extension_type.rb
1047
1072
  - lib/metanorma/un_document/metadata/un_bibliographic_item.rb
1048
1073
  - lib/metanorma/un_document/root.rb
1049
1074
  - lib/metanorma/un_document/sections.rb
1075
+ - lib/metanorma/un_document/sections/un_abstract_section.rb
1050
1076
  - lib/metanorma/un_document/sections/un_preface.rb
1051
1077
  - lib/metanorma/un_document/sections/un_sections.rb
1078
+ - lib/metanorma/un_document/un_text_element.rb
1079
+ - script/benchmark_render.rb
1052
1080
  - script/render_both.rb
1053
1081
  - tasks/roundtrip_samples.rake
1054
1082
  homepage: https://github.com/metanorma/metanorma-document
@@ -1067,7 +1095,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
1067
1095
  requirements:
1068
1096
  - - ">="
1069
1097
  - !ruby/object:Gem::Version
1070
- version: '3.1'
1098
+ version: '3.3'
1071
1099
  required_rubygems_version: !ruby/object:Gem::Requirement
1072
1100
  requirements:
1073
1101
  - - ">="