metanorma-document 0.3.0 → 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 (183) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +3 -2
  3. data/Rakefile +30 -5
  4. data/frontend/dist/app.css +1 -0
  5. data/frontend/dist/app.iife.js +24 -0
  6. data/frontend/package-lock.json +7 -505
  7. data/frontend/tailwind.config.js +5 -0
  8. data/lib/metanorma/csa_document/root.rb +27 -0
  9. data/lib/metanorma/csa_document.rb +9 -0
  10. data/lib/metanorma/document/cli.rb +52 -0
  11. data/lib/metanorma/document/components/ancillary_blocks/sourcecode_body.rb +14 -0
  12. data/lib/metanorma/document/components/inline/comma_element.rb +3 -0
  13. data/lib/metanorma/document/components/inline/enum_comma_element.rb +3 -0
  14. data/lib/metanorma/document/components/inline/eref_element.rb +4 -1
  15. data/lib/metanorma/document/components/inline/fmt_termsource_element.rb +4 -2
  16. data/lib/metanorma/document/components/inline/math_element.rb +13 -7
  17. data/lib/metanorma/document/components/inline/vocabulary.rb +4 -0
  18. data/lib/metanorma/document/components/multi_paragraph/admonition_block.rb +6 -1
  19. data/lib/metanorma/document/components/paragraphs/paragraph_block.rb +3 -0
  20. data/lib/metanorma/document/components/reference_elements/callout.rb +3 -2
  21. data/lib/metanorma/document/components/tables/table_cell.rb +3 -0
  22. data/lib/metanorma/document/elements/input.rb +44 -0
  23. data/lib/metanorma/document/elements.rb +1 -0
  24. data/lib/metanorma/document/relaton/address.rb +5 -0
  25. data/lib/metanorma/document/relaton/affiliation.rb +3 -0
  26. data/lib/metanorma/document/relaton/bib_item_size.rb +8 -9
  27. data/lib/metanorma/document/relaton/bib_item_type.rb +3 -0
  28. data/lib/metanorma/document/relaton/bibliographic_date.rb +5 -0
  29. data/lib/metanorma/document/relaton/contact_method.rb +5 -0
  30. data/lib/metanorma/document/relaton/contribution_info.rb +6 -2
  31. data/lib/metanorma/document/relaton/contributor.rb +4 -0
  32. data/lib/metanorma/document/relaton/contributor_role.rb +3 -0
  33. data/lib/metanorma/document/relaton/copyright_association.rb +3 -0
  34. data/lib/metanorma/document/relaton/copyright_owner.rb +3 -0
  35. data/lib/metanorma/document/relaton/date_time.rb +3 -0
  36. data/lib/metanorma/document/relaton/document_identifier.rb +4 -0
  37. data/lib/metanorma/document/relaton/document_relation.rb +8 -0
  38. data/lib/metanorma/document/relaton/document_status.rb +4 -0
  39. data/lib/metanorma/document/relaton/formatted_address.rb +4 -0
  40. data/lib/metanorma/document/relaton/full_name.rb +14 -3
  41. data/lib/metanorma/document/relaton/keyword_type.rb +3 -0
  42. data/lib/metanorma/document/relaton/locality_stack.rb +6 -9
  43. data/lib/metanorma/document/relaton/localized_name.rb +8 -5
  44. data/lib/metanorma/document/relaton/logo_element.rb +5 -0
  45. data/lib/metanorma/document/relaton/medium_type.rb +5 -16
  46. data/lib/metanorma/document/relaton/org_identifier.rb +2 -0
  47. data/lib/metanorma/document/relaton/org_subdivision.rb +2 -0
  48. data/lib/metanorma/document/relaton/org_subdivision_identifier.rb +2 -0
  49. data/lib/metanorma/document/relaton/organization.rb +3 -0
  50. data/lib/metanorma/document/relaton/person.rb +7 -1
  51. data/lib/metanorma/document/relaton/person_identifier.rb +3 -0
  52. data/lib/metanorma/document/relaton/place_type.rb +5 -0
  53. data/lib/metanorma/document/relaton/region_element.rb +3 -9
  54. data/lib/metanorma/document/relaton/relaton_collection.rb +2 -0
  55. data/lib/metanorma/document/relaton/series_type.rb +7 -0
  56. data/lib/metanorma/document/relaton/typed_note.rb +4 -0
  57. data/lib/metanorma/document/relaton/typed_title_string.rb +4 -0
  58. data/lib/metanorma/document/relaton/typed_uri.rb +3 -8
  59. data/lib/metanorma/document/relaton/validity_type.rb +8 -10
  60. data/lib/metanorma/document/relaton/variant_full_name.rb +3 -0
  61. data/lib/metanorma/document/relaton/variant_org_name.rb +3 -0
  62. data/lib/metanorma/document/relaton/version_info.rb +5 -0
  63. data/lib/metanorma/document/relaton/vocab_id_type.rb +6 -12
  64. data/lib/metanorma/document/relaton.rb +0 -14
  65. data/lib/metanorma/document/version.rb +1 -1
  66. data/lib/metanorma/document.rb +1 -0
  67. data/lib/metanorma/html/base_renderer.rb +86 -234
  68. data/lib/metanorma/html/concerns/metadata_extraction.rb +61 -0
  69. data/lib/metanorma/html/concerns/presentation_validation.rb +61 -0
  70. data/lib/metanorma/html/concerns/svg_processing.rb +32 -0
  71. data/lib/metanorma/html/concerns/text_extraction.rb +93 -0
  72. data/lib/metanorma/html/concerns/toc_registry.rb +47 -0
  73. data/lib/metanorma/html/csa_renderer.rb +9 -0
  74. data/lib/metanorma/html/drops/figure_drop.rb +33 -10
  75. data/lib/metanorma/html/drops/sourcecode_drop.rb +3 -6
  76. data/lib/metanorma/html/flavor.rb +6 -1
  77. data/lib/metanorma/html/generator.rb +8 -1
  78. data/lib/metanorma/html/iso_renderer.rb +0 -142
  79. data/lib/metanorma/html/renderers/block_renderer.rb +10 -0
  80. data/lib/metanorma/html/renderers/element_order_traversal.rb +15 -1
  81. data/lib/metanorma/html/renderers/inline_renderer.rb +13 -75
  82. data/lib/metanorma/html/standard_renderer.rb +195 -35
  83. data/lib/metanorma/html.rb +1 -51
  84. data/lib/metanorma/iso_document/sections/iso_preface.rb +27 -13
  85. data/lib/metanorma/mirror/default_registry.rb +21 -0
  86. data/lib/metanorma/mirror/handlers/inline/catalog.rb +7 -12
  87. data/lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb +2 -3
  88. data/lib/metanorma/mirror/handlers/sourcecode.rb +1 -1
  89. data/lib/metanorma/mirror/model/guide.rb +3 -2
  90. data/lib/metanorma/mirror/output/formats/inline_format.rb +64 -3
  91. data/lib/metanorma/mirror/output/pipeline.rb +1 -0
  92. data/lib/metanorma/mirror/output.rb +0 -2
  93. data/lib/metanorma/mirror/rewriter.rb +3 -1
  94. data/lib/metanorma/registers/setup.rb +10 -0
  95. data/lib/metanorma/standard_document/annotation_container.rb +2 -0
  96. data/lib/metanorma/standard_document/elements/input.rb +4 -25
  97. data/lib/metanorma/standard_document/metadata/metanorma_extension.rb +12 -2
  98. data/lib/metanorma/standard_document/metadata/presentation_metadata.rb +107 -0
  99. data/lib/metanorma/standard_document/metadata/semantic_metadata.rb +18 -0
  100. data/lib/metanorma/standard_document/metadata/unitsml/amount_of_substance.rb +19 -0
  101. data/lib/metanorma/standard_document/metadata/unitsml/base_quantity.rb +34 -0
  102. data/lib/metanorma/standard_document/metadata/unitsml/dimension.rb +39 -0
  103. data/lib/metanorma/standard_document/metadata/unitsml/dimension_set.rb +19 -0
  104. data/lib/metanorma/standard_document/metadata/unitsml/electric_current.rb +19 -0
  105. data/lib/metanorma/standard_document/metadata/unitsml/enumerated_root_unit.rb +23 -0
  106. data/lib/metanorma/standard_document/metadata/unitsml/length.rb +19 -0
  107. data/lib/metanorma/standard_document/metadata/unitsml/luminous_intensity.rb +19 -0
  108. data/lib/metanorma/standard_document/metadata/unitsml/mass.rb +19 -0
  109. data/lib/metanorma/standard_document/metadata/unitsml/namespace.rb +17 -0
  110. data/lib/metanorma/standard_document/metadata/unitsml/plane_angle.rb +19 -0
  111. data/lib/metanorma/standard_document/metadata/unitsml/prefix.rb +30 -0
  112. data/lib/metanorma/standard_document/metadata/unitsml/prefix_name.rb +21 -0
  113. data/lib/metanorma/standard_document/metadata/unitsml/prefix_set.rb +19 -0
  114. data/lib/metanorma/standard_document/metadata/unitsml/prefix_symbol.rb +21 -0
  115. data/lib/metanorma/standard_document/metadata/unitsml/quantity.rb +28 -0
  116. data/lib/metanorma/standard_document/metadata/unitsml/quantity_name.rb +21 -0
  117. data/lib/metanorma/standard_document/metadata/unitsml/quantity_set.rb +19 -0
  118. data/lib/metanorma/standard_document/metadata/unitsml/root_units.rb +19 -0
  119. data/lib/metanorma/standard_document/metadata/unitsml/thermodynamic_temperature.rb +19 -0
  120. data/lib/metanorma/standard_document/metadata/unitsml/time.rb +19 -0
  121. data/lib/metanorma/standard_document/metadata/unitsml/unit.rb +32 -0
  122. data/lib/metanorma/standard_document/metadata/unitsml/unit_name.rb +21 -0
  123. data/lib/metanorma/standard_document/metadata/unitsml/unit_set.rb +19 -0
  124. data/lib/metanorma/standard_document/metadata/unitsml/unit_symbol.rb +36 -0
  125. data/lib/metanorma/standard_document/metadata/unitsml/unit_system.rb +23 -0
  126. data/lib/metanorma/standard_document/metadata/unitsml/unitsml_root.rb +28 -0
  127. data/lib/metanorma/standard_document/metadata/unitsml.rb +39 -0
  128. data/lib/metanorma/standard_document/metadata.rb +4 -0
  129. data/lib/metanorma/standard_document/sections/misc_container.rb +8 -6
  130. data/lib/metanorma/standard_document/sections/sections.rb +7 -0
  131. data/lib/metanorma/un_document/blocks/un_admonition_block.rb +86 -0
  132. data/lib/metanorma/un_document/blocks.rb +9 -0
  133. data/lib/metanorma/un_document/root.rb +8 -0
  134. data/lib/metanorma/un_document/sections/un_abstract_section.rb +48 -0
  135. data/lib/metanorma/un_document/sections/un_preface.rb +19 -2
  136. data/lib/metanorma/un_document/sections.rb +1 -0
  137. data/lib/metanorma/un_document/un_text_element.rb +116 -0
  138. data/lib/metanorma/un_document.rb +2 -0
  139. data/script/benchmark_render.rb +35 -0
  140. data/tasks/roundtrip_samples.rake +1 -1
  141. metadata +63 -45
  142. data/.rubocop_todo.yml +0 -220
  143. data/TODO.finalize/01-split-multi-class-files.md +0 -8
  144. data/TODO.finalize/02-remove-data-dist-iso-document-frontend.md +0 -6
  145. data/TODO.finalize/03-align-frontend-iife-and-gha-build.md +0 -11
  146. data/TODO.finalize/04-theme-per-flavor-config-driven.md +0 -9
  147. data/TODO.finalize/05-migrate-all-html-to-liquid.md +0 -16
  148. data/TODO.finalize/06-integrate-pubid-library.md +0 -16
  149. data/TODO.finalize/07-replace-relaton-models-with-relaton-bib.md +0 -39
  150. data/TODO.finalize/08-refactor-renderer-architecture.md +0 -25
  151. data/TODO.finalize/09-eliminate-code-smells.md +0 -14
  152. data/TODO.finalize/10-comprehensive-spec-coverage.md +0 -24
  153. data/TODO.finalize/11-config-driven-flavor-metadata.md +0 -20
  154. data/TODO.finalize/12-add-frozen-string-literal.md +0 -6
  155. data/TODO.finalize/13-extract-composition-from-god-class.md +0 -96
  156. data/TODO.finalize/14-config-driven-section-ordering.md +0 -31
  157. data/TODO.finalize/15-theme-directories-per-flavor.md +0 -46
  158. data/TODO.finalize/16-theme-lutaml-model-schema.md +0 -44
  159. data/docs/html-renderer.adoc +0 -261
  160. data/lib/data/dist/iso_document/frontend/assets/index-mwzbzmnK.js +0 -22
  161. data/lib/data/dist/iso_document/frontend/assets/index-pGvKTNid.css +0 -1
  162. data/lib/data/dist/iso_document/frontend/assets/iso-red.svg +0 -53
  163. data/lib/data/dist/iso_document/frontend/index.html +0 -13
  164. data/lib/metanorma/document/relaton/bib_item_size_type.rb +0 -21
  165. data/lib/metanorma/document/relaton/bibliographic_date_type.rb +0 -22
  166. data/lib/metanorma/document/relaton/document_relation_type.rb +0 -31
  167. data/lib/metanorma/document/relaton/iso4217_code.rb +0 -17
  168. data/lib/metanorma/document/relaton/iso8601_date.rb +0 -17
  169. data/lib/metanorma/document/relaton/personal_identifier_type.rb +0 -21
  170. data/lib/metanorma/document/relaton/region_type.rb +0 -20
  171. data/lib/metanorma/document/relaton/series_type_type.rb +0 -21
  172. data/lib/metanorma/document/relaton/specific_locality_type.rb +0 -25
  173. data/lib/metanorma/document/relaton/title_type.rb +0 -21
  174. data/lib/metanorma/mirror/output/html_renderer.rb +0 -95
  175. data/lib/metanorma/mirror/output/html_renderers/block_renderers.rb +0 -178
  176. data/lib/metanorma/mirror/output/html_renderers/inline_renderer.rb +0 -61
  177. data/lib/metanorma/mirror/output/html_renderers/list_renderers.rb +0 -96
  178. data/lib/metanorma/mirror/output/html_renderers/mark_renderers.rb +0 -41
  179. data/lib/metanorma/mirror/output/html_renderers/section_renderers.rb +0 -129
  180. data/lib/metanorma/mirror/output/html_renderers/structural_renderers.rb +0 -80
  181. data/lib/metanorma/mirror/output/html_renderers/table_renderers.rb +0 -87
  182. data/lib/metanorma/mirror/output/html_renderers.rb +0 -76
  183. data/lib/metanorma/standard_document/annotation.rb +0 -37
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ class Time < Lutaml::Model::Serializable
8
+ include BaseQuantityAttributes
9
+
10
+ xml do
11
+ element "Time"
12
+ namespace Unitsml::Namespace
13
+ BaseQuantityXmlMapping.apply(self)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ class Unit < Lutaml::Model::Serializable
8
+ attribute :dimension_url, :string
9
+ attribute :id, :string
10
+ attribute :semx_id, :string
11
+
12
+ attribute :unit_system, UnitSystem
13
+ attribute :unit_name, UnitName
14
+ attribute :unit_symbol, UnitSymbol, collection: true
15
+ attribute :root_units, RootUnits
16
+
17
+ xml do
18
+ element "Unit"
19
+ namespace Unitsml::Namespace
20
+ map_attribute "dimensionURL", to: :dimension_url
21
+ map_attribute "id", to: :id
22
+ map_attribute "semx-id", to: :semx_id
23
+ map_element "UnitSystem", to: :unit_system
24
+ map_element "UnitName", to: :unit_name
25
+ map_element "UnitSymbol", to: :unit_symbol
26
+ map_element "RootUnits", to: :root_units
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ class UnitName < Lutaml::Model::Serializable
8
+ attribute :lang, :string
9
+ attribute :text, :string
10
+
11
+ xml do
12
+ element "UnitName"
13
+ namespace Unitsml::Namespace
14
+ map_attribute "lang", to: :lang
15
+ map_content to: :text
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ class UnitSet < Lutaml::Model::Serializable
8
+ attribute :unit, Unit, collection: true
9
+
10
+ xml do
11
+ element "UnitSet"
12
+ namespace Unitsml::Namespace
13
+ map_element "Unit", to: :unit
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mml"
4
+ require "mml/v3"
5
+
6
+ module Metanorma
7
+ module StandardDocument
8
+ module Metadata
9
+ module Unitsml
10
+ # Unit symbol. type="HTML" symbols can carry inline markup
11
+ # (e.g. "nmol mol <sup>−1</sup>"), type="MathMl" symbols carry a
12
+ # MathML <math> child, so this is a mixed-content model.
13
+ class UnitSymbol < Lutaml::Model::Serializable
14
+ attribute :type, :string
15
+ attribute :text, :string, collection: true
16
+ attribute :sup, Metanorma::Document::Components::Inline::SupElement,
17
+ collection: true
18
+ attribute :sub, Metanorma::Document::Components::Inline::SubElement,
19
+ collection: true
20
+ attribute :math, "Mml::V3::Math", collection: true
21
+
22
+ xml do
23
+ element "UnitSymbol"
24
+ namespace Unitsml::Namespace
25
+ mixed_content
26
+ map_attribute "type", to: :type
27
+ map_content to: :text
28
+ map_element "sup", to: :sup
29
+ map_element "sub", to: :sub
30
+ map_element "math", to: :math
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ class UnitSystem < Lutaml::Model::Serializable
8
+ attribute :name, :string
9
+ attribute :type, :string
10
+ attribute :lang, :string
11
+
12
+ xml do
13
+ element "UnitSystem"
14
+ namespace Unitsml::Namespace
15
+ map_attribute "name", to: :name
16
+ map_attribute "type", to: :type
17
+ map_attribute "lang", to: :lang
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ # Root <UnitsML> element embedded in metanorma-extension.
8
+ # Child sets serialize in schema order:
9
+ # UnitSet, QuantitySet, DimensionSet, PrefixSet.
10
+ class UnitsmlRoot < Lutaml::Model::Serializable
11
+ attribute :unit_set, UnitSet
12
+ attribute :quantity_set, QuantitySet
13
+ attribute :dimension_set, DimensionSet
14
+ attribute :prefix_set, PrefixSet
15
+
16
+ xml do
17
+ element "UnitsML"
18
+ namespace Unitsml::Namespace
19
+ map_element "UnitSet", to: :unit_set
20
+ map_element "QuantitySet", to: :quantity_set
21
+ map_element "DimensionSet", to: :dimension_set
22
+ map_element "PrefixSet", to: :prefix_set
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module StandardDocument
5
+ module Metadata
6
+ module Unitsml
7
+ autoload :AmountOfSubstance, "#{__dir__}/unitsml/amount_of_substance"
8
+ autoload :BaseQuantityAttributes, "#{__dir__}/unitsml/base_quantity"
9
+ autoload :BaseQuantityXmlMapping, "#{__dir__}/unitsml/base_quantity"
10
+ autoload :Dimension, "#{__dir__}/unitsml/dimension"
11
+ autoload :DimensionSet, "#{__dir__}/unitsml/dimension_set"
12
+ autoload :ElectricCurrent, "#{__dir__}/unitsml/electric_current"
13
+ autoload :EnumeratedRootUnit, "#{__dir__}/unitsml/enumerated_root_unit"
14
+ autoload :Length, "#{__dir__}/unitsml/length"
15
+ autoload :LuminousIntensity, "#{__dir__}/unitsml/luminous_intensity"
16
+ autoload :Mass, "#{__dir__}/unitsml/mass"
17
+ autoload :Namespace, "#{__dir__}/unitsml/namespace"
18
+ autoload :PlaneAngle, "#{__dir__}/unitsml/plane_angle"
19
+ autoload :Prefix, "#{__dir__}/unitsml/prefix"
20
+ autoload :PrefixName, "#{__dir__}/unitsml/prefix_name"
21
+ autoload :PrefixSet, "#{__dir__}/unitsml/prefix_set"
22
+ autoload :PrefixSymbol, "#{__dir__}/unitsml/prefix_symbol"
23
+ autoload :Quantity, "#{__dir__}/unitsml/quantity"
24
+ autoload :QuantityName, "#{__dir__}/unitsml/quantity_name"
25
+ autoload :QuantitySet, "#{__dir__}/unitsml/quantity_set"
26
+ autoload :RootUnits, "#{__dir__}/unitsml/root_units"
27
+ autoload :ThermodynamicTemperature,
28
+ "#{__dir__}/unitsml/thermodynamic_temperature"
29
+ autoload :Time, "#{__dir__}/unitsml/time"
30
+ autoload :Unit, "#{__dir__}/unitsml/unit"
31
+ autoload :UnitName, "#{__dir__}/unitsml/unit_name"
32
+ autoload :UnitSet, "#{__dir__}/unitsml/unit_set"
33
+ autoload :UnitSymbol, "#{__dir__}/unitsml/unit_symbol"
34
+ autoload :UnitSystem, "#{__dir__}/unitsml/unit_system"
35
+ autoload :UnitsmlRoot, "#{__dir__}/unitsml/unitsml_root"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -7,6 +7,9 @@ module Metanorma
7
7
  autoload :IcsType, "#{__dir__}/metadata/ics_type"
8
8
  autoload :MetanormaExtension,
9
9
  "#{__dir__}/metadata/metanorma_extension"
10
+ autoload :PresentationMetadata,
11
+ "#{__dir__}/metadata/presentation_metadata"
12
+ autoload :SemanticMetadata, "#{__dir__}/metadata/semantic_metadata"
10
13
  autoload :StandardBibData, "#{__dir__}/metadata/standard_bib_data"
11
14
  autoload :StandardBibDataExtensionType,
12
15
  "#{__dir__}/metadata/standard_bib_data_extension_type"
@@ -14,6 +17,7 @@ module Metanorma
14
17
  "#{__dir__}/metadata/structured_identifier_type"
15
18
  autoload :TechnicalCommitteeType,
16
19
  "#{__dir__}/metadata/technical_committee_type"
20
+ autoload :Unitsml, "#{__dir__}/metadata/unitsml"
17
21
  end
18
22
  end
19
23
  end
@@ -3,13 +3,15 @@
3
3
  module Metanorma
4
4
  module StandardDocument
5
5
  module Sections
6
- # Extension point for extraneous elements that need to be added to standards document
7
- # from other schemas, e.g. UnitsML.
6
+ # Extension point for extraneous elements that need to be added to
7
+ # standards documents from other schemas.
8
8
  #
9
- # Content is stored as raw XML text since the children come from external
10
- # vocabularies not defined in the metanorma schema.
9
+ # Observed payload: legacy-serialization <presentation-metadata>
10
+ # name/value pairs (e.g. metanorma/demo-ab import_from_metanorma).
11
11
  class MiscContainer < Lutaml::Model::Serializable
12
- attribute :content, :string
12
+ attribute :presentation_metadata,
13
+ Metanorma::StandardDocument::Metadata::PresentationMetadata,
14
+ collection: true
13
15
 
14
16
  attribute :semx_id, :string
15
17
  attribute :original_id, :string
@@ -17,7 +19,7 @@ module Metanorma
17
19
 
18
20
  xml do
19
21
  element "misc-container"
20
- map_content to: :content
22
+ map_element "presentation-metadata", to: :presentation_metadata
21
23
 
22
24
  map_attribute "semx-id", to: :semx_id
23
25
  map_attribute "original-id", to: :original_id
@@ -27,11 +27,18 @@ module Metanorma
27
27
  attribute :semx_id, :string
28
28
  attribute :displayorder, :integer
29
29
 
30
+ # Loose paragraphs directly under <sections> (e.g. the ITU
31
+ # zzSTDTitle1 title paragraph at the start of sections).
32
+ attribute :p,
33
+ Metanorma::Document::Components::Paragraphs::ParagraphBlock,
34
+ collection: true
35
+
30
36
  xml do
31
37
  element "sections"
32
38
  ordered
33
39
 
34
40
  Metanorma::StandardDocument::SectionXmlMapping.apply_sections_elements(self)
41
+ map_element "p", to: :p
35
42
  Metanorma::StandardDocument::SectionXmlMapping.apply_sections_attributes(self)
36
43
  end
37
44
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module UnDocument
5
+ module Blocks
6
+ # Admonition block of a UN document.
7
+ # Corresponds to un.rng:
8
+ # AdmonitionType = danger | caution | warning | important |
9
+ # "safety precautions"
10
+ # AdmonitionBody = tname?,
11
+ # ( paragraph-with-footnote | table | formula | ol | ul | dl |
12
+ # figure | quote | sourcecode | example | review )+,
13
+ # note*
14
+ # The UN grammar widens the isodoc admonition body from paragraphs only
15
+ # to most block types, with notes permitted after the body.
16
+ # `uri` keeps the base model's element mapping (the current basicdoc
17
+ # grammar declares it an attribute — a base-level divergence affecting
18
+ # all flavors, left as-is here).
19
+ class UnAdmonitionBlock < Metanorma::Document::Components::MultiParagraph::AdmonitionBlock
20
+ # UN restricts AdmonitionType to five values.
21
+ attribute :type, :string,
22
+ values: ["danger", "caution", "warning", "important",
23
+ "safety precautions"]
24
+
25
+ attribute :tables,
26
+ Metanorma::Document::Components::Tables::TableBlock,
27
+ collection: true
28
+ attribute :formulas,
29
+ Metanorma::Document::Components::AncillaryBlocks::FormulaBlock,
30
+ collection: true
31
+ attribute :ordered_lists,
32
+ Metanorma::Document::Components::Lists::OrderedList,
33
+ collection: true
34
+ attribute :unordered_lists,
35
+ Metanorma::Document::Components::Lists::UnorderedList,
36
+ collection: true
37
+ attribute :definition_lists,
38
+ Metanorma::Document::Components::Lists::DefinitionList,
39
+ collection: true
40
+ attribute :figures,
41
+ Metanorma::Document::Components::AncillaryBlocks::FigureBlock,
42
+ collection: true
43
+ attribute :quote_blocks,
44
+ Metanorma::Document::Components::MultiParagraph::QuoteBlock,
45
+ collection: true
46
+ attribute :sourcecode_blocks,
47
+ Metanorma::Document::Components::AncillaryBlocks::SourcecodeBlock,
48
+ collection: true
49
+ attribute :examples,
50
+ Metanorma::Document::Components::AncillaryBlocks::ExampleBlock,
51
+ collection: true
52
+ attribute :reviews,
53
+ Metanorma::Document::Components::MultiParagraph::ReviewBlock,
54
+ collection: true
55
+ attribute :notes,
56
+ Metanorma::Document::Components::Blocks::NoteBlock,
57
+ collection: true
58
+
59
+ xml do
60
+ element "admonition"
61
+ ordered
62
+
63
+ map_attribute "id", to: :id
64
+ map_attribute "type", to: :type
65
+ map_attribute "class", to: :block_class
66
+ map_attribute "unnumbered", to: :unnumbered
67
+
68
+ map_element "name", to: :name
69
+ map_element "fmt-name", to: :fmt_name
70
+ map_element "p", to: :paragraphs
71
+ map_element "table", to: :tables
72
+ map_element "formula", to: :formulas
73
+ map_element "ol", to: :ordered_lists
74
+ map_element "ul", to: :unordered_lists
75
+ map_element "dl", to: :definition_lists
76
+ map_element "figure", to: :figures
77
+ map_element "quote", to: :quote_blocks
78
+ map_element "sourcecode", to: :sourcecode_blocks
79
+ map_element "example", to: :examples
80
+ map_element "review", to: :reviews
81
+ map_element "note", to: :notes
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module UnDocument
5
+ module Blocks
6
+ autoload :UnAdmonitionBlock, "#{__dir__}/blocks/un_admonition_block"
7
+ end
8
+ end
9
+ end
@@ -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