metanorma-document 0.3.0 → 0.5.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.
- checksums.yaml +4 -4
- data/BUGS.sts/08-list-items-duplicate-bullets.md +45 -0
- data/CLAUDE.md +3 -2
- data/Rakefile +30 -5
- data/data/stylesheets/components/header.css +3 -5
- data/data/stylesheets/components/lists.css +14 -0
- data/frontend/dist/app.css +1 -0
- data/frontend/dist/app.iife.js +24 -0
- data/frontend/package-lock.json +7 -505
- data/frontend/tailwind.config.js +5 -0
- data/lib/metanorma/{oiml_document → csa_document}/root.rb +2 -2
- data/lib/metanorma/csa_document.rb +9 -0
- data/lib/metanorma/document/cli.rb +52 -0
- data/lib/metanorma/document/components/ancillary_blocks/sourcecode_body.rb +14 -0
- data/lib/metanorma/document/components/inline/comma_element.rb +3 -0
- data/lib/metanorma/document/components/inline/enum_comma_element.rb +3 -0
- data/lib/metanorma/document/components/inline/eref_element.rb +4 -1
- data/lib/metanorma/document/components/inline/fmt_termsource_element.rb +4 -2
- data/lib/metanorma/document/components/inline/math_element.rb +13 -7
- data/lib/metanorma/document/components/inline/vocabulary.rb +4 -0
- data/lib/metanorma/document/components/multi_paragraph/admonition_block.rb +6 -1
- data/lib/metanorma/document/components/paragraphs/paragraph_block.rb +3 -0
- data/lib/metanorma/document/components/reference_elements/callout.rb +3 -2
- data/lib/metanorma/document/components/tables/table_cell.rb +3 -0
- data/lib/metanorma/document/elements/input.rb +44 -0
- data/lib/metanorma/document/elements.rb +1 -0
- data/lib/metanorma/document/relaton/address.rb +5 -0
- data/lib/metanorma/document/relaton/affiliation.rb +3 -0
- data/lib/metanorma/document/relaton/bib_item_size.rb +8 -9
- data/lib/metanorma/document/relaton/bib_item_type.rb +3 -0
- data/lib/metanorma/document/relaton/bibliographic_date.rb +5 -0
- data/lib/metanorma/document/relaton/contact_method.rb +5 -0
- data/lib/metanorma/document/relaton/contribution_info.rb +6 -2
- data/lib/metanorma/document/relaton/contributor.rb +4 -0
- data/lib/metanorma/document/relaton/contributor_role.rb +3 -0
- data/lib/metanorma/document/relaton/copyright_association.rb +3 -0
- data/lib/metanorma/document/relaton/copyright_owner.rb +3 -0
- data/lib/metanorma/document/relaton/date_time.rb +3 -0
- data/lib/metanorma/document/relaton/document_identifier.rb +4 -0
- data/lib/metanorma/document/relaton/document_relation.rb +8 -0
- data/lib/metanorma/document/relaton/document_status.rb +4 -0
- data/lib/metanorma/document/relaton/formatted_address.rb +4 -0
- data/lib/metanorma/document/relaton/full_name.rb +14 -3
- data/lib/metanorma/document/relaton/keyword_type.rb +3 -0
- data/lib/metanorma/document/relaton/locality_stack.rb +6 -9
- data/lib/metanorma/document/relaton/localized_name.rb +8 -5
- data/lib/metanorma/document/relaton/logo_element.rb +5 -0
- data/lib/metanorma/document/relaton/medium_type.rb +5 -16
- data/lib/metanorma/document/relaton/org_identifier.rb +2 -0
- data/lib/metanorma/document/relaton/org_subdivision.rb +2 -0
- data/lib/metanorma/document/relaton/org_subdivision_identifier.rb +2 -0
- data/lib/metanorma/document/relaton/organization.rb +3 -0
- data/lib/metanorma/document/relaton/person.rb +7 -1
- data/lib/metanorma/document/relaton/person_identifier.rb +3 -0
- data/lib/metanorma/document/relaton/place_type.rb +5 -0
- data/lib/metanorma/document/relaton/region_element.rb +3 -9
- data/lib/metanorma/document/relaton/relaton_collection.rb +2 -0
- data/lib/metanorma/document/relaton/series_type.rb +7 -0
- data/lib/metanorma/document/relaton/typed_note.rb +4 -0
- data/lib/metanorma/document/relaton/typed_title_string.rb +4 -0
- data/lib/metanorma/document/relaton/typed_uri.rb +3 -8
- data/lib/metanorma/document/relaton/validity_type.rb +8 -10
- data/lib/metanorma/document/relaton/variant_full_name.rb +3 -0
- data/lib/metanorma/document/relaton/variant_org_name.rb +3 -0
- data/lib/metanorma/document/relaton/version_info.rb +5 -0
- data/lib/metanorma/document/relaton/vocab_id_type.rb +6 -12
- data/lib/metanorma/document/relaton.rb +0 -14
- data/lib/metanorma/document/version.rb +1 -1
- data/lib/metanorma/document.rb +2 -1
- data/lib/metanorma/html/asset_pipeline.rb +1 -0
- data/lib/metanorma/html/base_renderer.rb +106 -236
- data/lib/metanorma/html/concerns/metadata_extraction.rb +61 -0
- data/lib/metanorma/html/concerns/presentation_validation.rb +61 -0
- data/lib/metanorma/html/concerns/svg_processing.rb +32 -0
- data/lib/metanorma/html/concerns/text_extraction.rb +93 -0
- data/lib/metanorma/html/concerns/toc_registry.rb +47 -0
- data/lib/metanorma/html/csa_renderer.rb +9 -0
- data/lib/metanorma/html/drops/figure_drop.rb +33 -10
- data/lib/metanorma/html/drops/sourcecode_drop.rb +3 -6
- data/lib/metanorma/html/flavor.rb +6 -1
- data/lib/metanorma/html/generator.rb +8 -8
- data/lib/metanorma/html/iso_renderer.rb +0 -142
- data/lib/metanorma/html/renderers/block_renderer.rb +41 -5
- data/lib/metanorma/html/renderers/element_order_traversal.rb +15 -1
- data/lib/metanorma/html/renderers/inline_renderer.rb +16 -76
- data/lib/metanorma/html/standard_renderer.rb +195 -35
- data/lib/metanorma/html/templates/_list_item.html.liquid +1 -1
- data/lib/metanorma/html/theme.rb +38 -11
- data/lib/metanorma/html.rb +1 -52
- data/lib/metanorma/iso_document/sections/iso_preface.rb +27 -13
- data/lib/metanorma/mirror/default_registry.rb +21 -0
- data/lib/metanorma/mirror/handlers/inline/catalog.rb +7 -12
- data/lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb +2 -3
- data/lib/metanorma/mirror/handlers/sourcecode.rb +1 -1
- data/lib/metanorma/mirror/model/guide.rb +3 -2
- data/lib/metanorma/mirror/output/formats/inline_format.rb +64 -3
- data/lib/metanorma/mirror/output/pipeline.rb +1 -0
- data/lib/metanorma/mirror/output.rb +0 -2
- data/lib/metanorma/mirror/rewriter.rb +3 -1
- data/lib/metanorma/registers/setup.rb +6 -2
- data/lib/metanorma/standard_document/annotation_container.rb +2 -0
- data/lib/metanorma/standard_document/elements/input.rb +4 -25
- data/lib/metanorma/standard_document/metadata/metanorma_extension.rb +12 -2
- data/lib/metanorma/standard_document/metadata/presentation_metadata.rb +107 -0
- data/lib/metanorma/standard_document/metadata/semantic_metadata.rb +18 -0
- data/lib/metanorma/standard_document/metadata/unitsml/amount_of_substance.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/base_quantity.rb +34 -0
- data/lib/metanorma/standard_document/metadata/unitsml/dimension.rb +39 -0
- data/lib/metanorma/standard_document/metadata/unitsml/dimension_set.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/electric_current.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/enumerated_root_unit.rb +23 -0
- data/lib/metanorma/standard_document/metadata/unitsml/length.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/luminous_intensity.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/mass.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/namespace.rb +17 -0
- data/lib/metanorma/standard_document/metadata/unitsml/plane_angle.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/prefix.rb +30 -0
- data/lib/metanorma/standard_document/metadata/unitsml/prefix_name.rb +21 -0
- data/lib/metanorma/standard_document/metadata/unitsml/prefix_set.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/prefix_symbol.rb +21 -0
- data/lib/metanorma/standard_document/metadata/unitsml/quantity.rb +28 -0
- data/lib/metanorma/standard_document/metadata/unitsml/quantity_name.rb +21 -0
- data/lib/metanorma/standard_document/metadata/unitsml/quantity_set.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/root_units.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/thermodynamic_temperature.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/time.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unit.rb +32 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unit_name.rb +21 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unit_set.rb +19 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unit_symbol.rb +36 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unit_system.rb +23 -0
- data/lib/metanorma/standard_document/metadata/unitsml/unitsml_root.rb +28 -0
- data/lib/metanorma/standard_document/metadata/unitsml.rb +39 -0
- data/lib/metanorma/standard_document/metadata.rb +4 -0
- data/lib/metanorma/standard_document/sections/misc_container.rb +8 -6
- data/lib/metanorma/standard_document/sections/sections.rb +7 -0
- data/lib/metanorma/un_document/blocks/un_admonition_block.rb +86 -0
- data/lib/metanorma/un_document/blocks.rb +9 -0
- data/lib/metanorma/un_document/root.rb +8 -0
- data/lib/metanorma/un_document/sections/un_abstract_section.rb +48 -0
- data/lib/metanorma/un_document/sections/un_preface.rb +19 -2
- data/lib/metanorma/un_document/sections.rb +1 -0
- data/lib/metanorma/un_document/un_text_element.rb +116 -0
- data/lib/metanorma/un_document.rb +2 -0
- data/script/benchmark_render.rb +35 -0
- data/tasks/roundtrip_samples.rake +2 -2
- metadata +65 -54
- data/.rubocop_todo.yml +0 -220
- data/TODO.finalize/01-split-multi-class-files.md +0 -8
- data/TODO.finalize/02-remove-data-dist-iso-document-frontend.md +0 -6
- data/TODO.finalize/03-align-frontend-iife-and-gha-build.md +0 -11
- data/TODO.finalize/04-theme-per-flavor-config-driven.md +0 -9
- data/TODO.finalize/05-migrate-all-html-to-liquid.md +0 -16
- data/TODO.finalize/06-integrate-pubid-library.md +0 -16
- data/TODO.finalize/07-replace-relaton-models-with-relaton-bib.md +0 -39
- data/TODO.finalize/08-refactor-renderer-architecture.md +0 -25
- data/TODO.finalize/09-eliminate-code-smells.md +0 -14
- data/TODO.finalize/10-comprehensive-spec-coverage.md +0 -24
- data/TODO.finalize/11-config-driven-flavor-metadata.md +0 -20
- data/TODO.finalize/12-add-frozen-string-literal.md +0 -6
- data/TODO.finalize/13-extract-composition-from-god-class.md +0 -96
- data/TODO.finalize/14-config-driven-section-ordering.md +0 -31
- data/TODO.finalize/15-theme-directories-per-flavor.md +0 -46
- data/TODO.finalize/16-theme-lutaml-model-schema.md +0 -44
- data/data/logos/oiml-logo-full-dark.svg +0 -1
- data/data/logos/oiml-logo-full-light.svg +0 -1
- data/data/logos/oiml-logo-icon-dark.svg +0 -1
- data/data/logos/oiml-logo-icon-light.svg +0 -1
- data/data/logos/oiml-logo.svg +0 -1
- data/data/themes/oiml.yaml +0 -56
- data/docs/html-renderer.adoc +0 -261
- data/lib/data/dist/iso_document/frontend/assets/index-mwzbzmnK.js +0 -22
- data/lib/data/dist/iso_document/frontend/assets/index-pGvKTNid.css +0 -1
- data/lib/data/dist/iso_document/frontend/assets/iso-red.svg +0 -53
- data/lib/data/dist/iso_document/frontend/index.html +0 -13
- data/lib/metanorma/document/relaton/bib_item_size_type.rb +0 -21
- data/lib/metanorma/document/relaton/bibliographic_date_type.rb +0 -22
- data/lib/metanorma/document/relaton/document_relation_type.rb +0 -31
- data/lib/metanorma/document/relaton/iso4217_code.rb +0 -17
- data/lib/metanorma/document/relaton/iso8601_date.rb +0 -17
- data/lib/metanorma/document/relaton/personal_identifier_type.rb +0 -21
- data/lib/metanorma/document/relaton/region_type.rb +0 -20
- data/lib/metanorma/document/relaton/series_type_type.rb +0 -21
- data/lib/metanorma/document/relaton/specific_locality_type.rb +0 -25
- data/lib/metanorma/document/relaton/title_type.rb +0 -21
- data/lib/metanorma/html/oiml_renderer.rb +0 -33
- data/lib/metanorma/mirror/output/html_renderer.rb +0 -95
- data/lib/metanorma/mirror/output/html_renderers/block_renderers.rb +0 -178
- data/lib/metanorma/mirror/output/html_renderers/inline_renderer.rb +0 -61
- data/lib/metanorma/mirror/output/html_renderers/list_renderers.rb +0 -96
- data/lib/metanorma/mirror/output/html_renderers/mark_renderers.rb +0 -41
- data/lib/metanorma/mirror/output/html_renderers/section_renderers.rb +0 -129
- data/lib/metanorma/mirror/output/html_renderers/structural_renderers.rb +0 -80
- data/lib/metanorma/mirror/output/html_renderers/table_renderers.rb +0 -87
- data/lib/metanorma/mirror/output/html_renderers.rb +0 -76
- data/lib/metanorma/oiml_document.rb +0 -9
- data/lib/metanorma/standard_document/annotation.rb +0 -37
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Html
|
|
5
|
+
module Concerns
|
|
6
|
+
# Plain-text extraction from model nodes, mixed into BaseRenderer.
|
|
7
|
+
# Used wherever rendered output needs a text-only form (titles,
|
|
8
|
+
# labels, captions, ToC entries). Walks `element_order` and typed
|
|
9
|
+
# attributes directly on the model — never strips tags from
|
|
10
|
+
# rendered HTML.
|
|
11
|
+
module TextExtraction
|
|
12
|
+
def extract_plain_text(node)
|
|
13
|
+
return node.to_s if node.is_a?(String)
|
|
14
|
+
return extract_text_value(node).to_s unless node.is_a?(Lutaml::Model::Serializable)
|
|
15
|
+
|
|
16
|
+
parts = []
|
|
17
|
+
xml_mapping = node.class.mappings_for(:xml, node.lutaml_register)
|
|
18
|
+
|
|
19
|
+
if node.element_order.is_a?(Array) && xml_mapping
|
|
20
|
+
element_to_attr =
|
|
21
|
+
Renderers::ElementOrderTraversal.element_to_attr_map(xml_mapping)
|
|
22
|
+
|
|
23
|
+
indices = Hash.new(0)
|
|
24
|
+
node.element_order.each do |el|
|
|
25
|
+
next unless el.is_a?(Lutaml::Xml::Element)
|
|
26
|
+
|
|
27
|
+
if el.text?
|
|
28
|
+
parts << el.text_content.to_s
|
|
29
|
+
elsif el.name == "tab"
|
|
30
|
+
parts << " "
|
|
31
|
+
# rubocop:disable Lint/DuplicateBranch
|
|
32
|
+
elsif el.name == "br"
|
|
33
|
+
parts << " "
|
|
34
|
+
# rubocop:enable Lint/DuplicateBranch
|
|
35
|
+
elsif el.element?
|
|
36
|
+
attr_name = element_to_attr[el.name]
|
|
37
|
+
if attr_name
|
|
38
|
+
coll = node.public_send(attr_name)
|
|
39
|
+
obj = if coll.is_a?(Array)
|
|
40
|
+
idx = indices[attr_name]
|
|
41
|
+
indices[attr_name] += 1
|
|
42
|
+
coll[idx]
|
|
43
|
+
else
|
|
44
|
+
coll
|
|
45
|
+
end
|
|
46
|
+
text = extract_plain_text(obj)
|
|
47
|
+
parts << (text.empty? ? " " : text)
|
|
48
|
+
elsif el.name == "span"
|
|
49
|
+
parts << " "
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if parts.join.strip.empty?
|
|
56
|
+
t = safe_attr(node, :text)
|
|
57
|
+
parts << (t.is_a?(Array) ? t.join : t.to_s) if t
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
parts.join.strip.gsub(" ", " ")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def extract_text_value(val)
|
|
64
|
+
return nil if val.nil?
|
|
65
|
+
return val if val.is_a?(String)
|
|
66
|
+
|
|
67
|
+
if val.is_a?(Array)
|
|
68
|
+
val.map { |v| extract_text_value(v) }.join
|
|
69
|
+
elsif val.is_a?(Lutaml::Model::Serializable)
|
|
70
|
+
c = safe_attr(val, :content)
|
|
71
|
+
if c && !c.equal?(val)
|
|
72
|
+
extract_text_value(c)
|
|
73
|
+
else
|
|
74
|
+
t = safe_attr(val, :text)
|
|
75
|
+
if t
|
|
76
|
+
extract_text_value(t)
|
|
77
|
+
else
|
|
78
|
+
v = safe_attr(val, :value)
|
|
79
|
+
if v
|
|
80
|
+
extract_text_value(v)
|
|
81
|
+
else
|
|
82
|
+
val.to_s
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
val.to_s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Html
|
|
5
|
+
module Concerns
|
|
6
|
+
# Table-of-contents entry collection and ToC rendering, mixed into
|
|
7
|
+
# BaseRenderer. Sub-renderers register section/figure/table entries
|
|
8
|
+
# as they walk the document; assemble_document renders the collected
|
|
9
|
+
# entries through the _toc.html.liquid template.
|
|
10
|
+
module TocRegistry
|
|
11
|
+
def toc_entries
|
|
12
|
+
@toc_entries
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def build_toc_html(entries)
|
|
16
|
+
entry_drops = entries.map { |e| Drops::TocEntryDrop.new(e) }
|
|
17
|
+
figure_drops = @figure_entries.map { |f| Drops::FigureListEntryDrop.new(f) }
|
|
18
|
+
table_drops = @table_entries.map { |t| Drops::FigureListEntryDrop.new(t) }
|
|
19
|
+
has_special_lists = !@figure_entries.empty? || !@table_entries.empty?
|
|
20
|
+
|
|
21
|
+
render_liquid("_toc.html.liquid", {
|
|
22
|
+
"entries" => entry_drops,
|
|
23
|
+
"figures" => figure_drops,
|
|
24
|
+
"tables" => table_drops,
|
|
25
|
+
"has_special_lists" => has_special_lists,
|
|
26
|
+
})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def register_toc_entry(id:, level:, text:)
|
|
30
|
+
@toc_entries << { id: id, level: level, text: text }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def register_figure_entry(id:, text:)
|
|
34
|
+
@figure_entries << { id: id, text: text }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def figure_entries
|
|
38
|
+
@figure_entries
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def register_table_entry(id:, text:)
|
|
42
|
+
@table_entries << { id: id, text: text }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -47,24 +47,47 @@ module Metanorma
|
|
|
47
47
|
end
|
|
48
48
|
sub_figures_html = sub_figures_parts.join
|
|
49
49
|
|
|
50
|
-
key_parts = []
|
|
51
|
-
renderer.safe_attr(figure, :note)&.each do |n|
|
|
52
|
-
key_parts << (renderer.render_note(n) || "")
|
|
53
|
-
end
|
|
54
|
-
renderer.safe_attr(figure, :dl)&.then do |dl|
|
|
55
|
-
key_parts << (renderer.render_definition_list(dl) || "")
|
|
56
|
-
end
|
|
57
|
-
key_html = key_parts.join
|
|
58
|
-
|
|
59
50
|
new(
|
|
60
51
|
id: id,
|
|
61
52
|
image_html: image_html,
|
|
62
53
|
caption_html: caption_html,
|
|
63
|
-
key_html:
|
|
54
|
+
key_html: build_key_html(figure, renderer),
|
|
64
55
|
sub_figures_html: sub_figures_html,
|
|
65
56
|
css_class: "figure",
|
|
66
57
|
)
|
|
67
58
|
end
|
|
59
|
+
|
|
60
|
+
class << self
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
# Notes, plain definition lists, and figure.key (e.g.
|
|
64
|
+
# <key class="formula_dl">) — symbol/footnote definitions
|
|
65
|
+
# belonging to the figure.
|
|
66
|
+
def build_key_html(figure, renderer)
|
|
67
|
+
parts = []
|
|
68
|
+
renderer.safe_attr(figure, :note)&.each do |n|
|
|
69
|
+
parts << (renderer.render_note(n) || "")
|
|
70
|
+
end
|
|
71
|
+
renderer.safe_attr(figure, :dl)&.then do |dl|
|
|
72
|
+
parts << (renderer.render_definition_list(dl) || "")
|
|
73
|
+
end
|
|
74
|
+
append_figure_key(parts, renderer.safe_attr(figure, :key), renderer)
|
|
75
|
+
parts.join
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def append_figure_key(parts, key, renderer)
|
|
79
|
+
return unless key
|
|
80
|
+
|
|
81
|
+
name = renderer.safe_attr(key, :name)
|
|
82
|
+
parts << (renderer.render_inline_element(name) || "") if name
|
|
83
|
+
if renderer.safe_attr(key, :dl)
|
|
84
|
+
parts << (renderer.render_definition_list(key.dl) || "")
|
|
85
|
+
end
|
|
86
|
+
renderer.safe_attr(key, :p)&.each do |para|
|
|
87
|
+
parts << (renderer.render_paragraph(para) || "")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
68
91
|
end
|
|
69
92
|
end
|
|
70
93
|
end
|
|
@@ -23,22 +23,19 @@ css_class: nil)
|
|
|
23
23
|
renderer.render_inline_element(sc.name)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
code_text = if sc.body
|
|
27
|
-
|
|
26
|
+
code_text = if sc.body
|
|
27
|
+
sc.body.decoded_content
|
|
28
28
|
elsif sc.content
|
|
29
29
|
Array(sc.content).join
|
|
30
30
|
else
|
|
31
31
|
""
|
|
32
32
|
end
|
|
33
|
-
raw_text = code_text.gsub("<", "<").gsub(">", ">").gsub("&", "&").gsub(
|
|
34
|
-
""", "\""
|
|
35
|
-
)
|
|
36
33
|
|
|
37
34
|
new(
|
|
38
35
|
id: id,
|
|
39
36
|
lang: lang,
|
|
40
37
|
name_html: name_html,
|
|
41
|
-
code_html: renderer.escape_html(
|
|
38
|
+
code_html: renderer.escape_html(code_text),
|
|
42
39
|
css_class: "sourcecode",
|
|
43
40
|
)
|
|
44
41
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "pubid"
|
|
4
|
+
|
|
3
5
|
module Metanorma
|
|
4
6
|
module Html
|
|
5
7
|
# A flavor ties together the four concepts that identify a Metanorma
|
|
@@ -38,7 +40,10 @@ module Metanorma
|
|
|
38
40
|
|
|
39
41
|
Object.const_get(pubid_module.to_s)
|
|
40
42
|
rescue NameError
|
|
41
|
-
|
|
43
|
+
raise ArgumentError,
|
|
44
|
+
"Flavor #{name.inspect}: pubid module #{pubid_module} could " \
|
|
45
|
+
"not be resolved — fix the registration in " \
|
|
46
|
+
"Html::Generator.build_flavor_registry"
|
|
42
47
|
end
|
|
43
48
|
end
|
|
44
49
|
end
|
|
@@ -87,6 +87,7 @@ module Metanorma
|
|
|
87
87
|
IsoRenderer
|
|
88
88
|
BipmRenderer
|
|
89
89
|
CcRenderer
|
|
90
|
+
CsaRenderer
|
|
90
91
|
IccRenderer
|
|
91
92
|
IecRenderer
|
|
92
93
|
IeeeRenderer
|
|
@@ -94,7 +95,6 @@ module Metanorma
|
|
|
94
95
|
IhoRenderer
|
|
95
96
|
ItuRenderer
|
|
96
97
|
OgcRenderer
|
|
97
|
-
OimlRenderer
|
|
98
98
|
PdfaRenderer
|
|
99
99
|
RiboseRenderer
|
|
100
100
|
|
|
@@ -136,6 +136,12 @@ module Metanorma
|
|
|
136
136
|
model_class: Metanorma::CcDocument::Root,
|
|
137
137
|
renderer_class: CcRenderer,
|
|
138
138
|
))
|
|
139
|
+
registry.register(Flavor.new(
|
|
140
|
+
name: :csa,
|
|
141
|
+
model_class: Metanorma::CsaDocument::Root,
|
|
142
|
+
renderer_class: CsaRenderer,
|
|
143
|
+
pubid_module: :"Pubid::Csa",
|
|
144
|
+
))
|
|
139
145
|
registry.register(Flavor.new(
|
|
140
146
|
name: :iec,
|
|
141
147
|
model_class: Metanorma::IecDocument::Root,
|
|
@@ -163,19 +169,13 @@ module Metanorma
|
|
|
163
169
|
name: :itu,
|
|
164
170
|
model_class: Metanorma::ItuDocument::Root,
|
|
165
171
|
renderer_class: ItuRenderer,
|
|
166
|
-
pubid_module: :"Pubid::
|
|
172
|
+
pubid_module: :"Pubid::Itu",
|
|
167
173
|
))
|
|
168
174
|
registry.register(Flavor.new(
|
|
169
175
|
name: :ogc,
|
|
170
176
|
model_class: Metanorma::OgcDocument::Root,
|
|
171
177
|
renderer_class: OgcRenderer,
|
|
172
178
|
))
|
|
173
|
-
registry.register(Flavor.new(
|
|
174
|
-
name: :oiml,
|
|
175
|
-
model_class: Metanorma::OimlDocument::Root,
|
|
176
|
-
renderer_class: OimlRenderer,
|
|
177
|
-
pubid_module: :"Pubid::Oiml",
|
|
178
|
-
))
|
|
179
179
|
registry.register(Flavor.new(
|
|
180
180
|
name: :pdfa,
|
|
181
181
|
model_class: Metanorma::RiboseDocument::Root,
|
|
@@ -330,148 +330,6 @@ module Metanorma
|
|
|
330
330
|
|
|
331
331
|
# --- ISO Term rendering ---
|
|
332
332
|
|
|
333
|
-
def render_term(term, **_opts)
|
|
334
|
-
term_name = extract_term_name(term)
|
|
335
|
-
term_def = extract_term_definition(term)
|
|
336
|
-
data_attrs = {}
|
|
337
|
-
if term_name && !term_name.empty?
|
|
338
|
-
data_attrs["data-term-name"] = term_name
|
|
339
|
-
end
|
|
340
|
-
if term_def && !term_def.empty?
|
|
341
|
-
data_attrs["data-term-definition"] = term_def
|
|
342
|
-
end
|
|
343
|
-
attrs = element_attrs(id: safe_attr(term, :id), **data_attrs)
|
|
344
|
-
fmt_name = safe_attr(term, :fmt_name)
|
|
345
|
-
fmt_preferred = safe_attr(term, :fmt_preferred)
|
|
346
|
-
fmt_admitted = safe_attr(term, :fmt_admitted)
|
|
347
|
-
fmt_deprecates = safe_attr(term, :fmt_deprecates)
|
|
348
|
-
fmt_definition = safe_attr(term, :fmt_definition)
|
|
349
|
-
fmt_termsource = safe_attr(term, :fmt_termsource)
|
|
350
|
-
term_number = safe_attr(term, :term_number)
|
|
351
|
-
term_p = safe_attr(term, :p)
|
|
352
|
-
term_note = safe_attr(term, :termnote) || Array(safe_attr(term, :note))
|
|
353
|
-
term_example = safe_attr(term,
|
|
354
|
-
:termexample) || Array(safe_attr(term,
|
|
355
|
-
:example))
|
|
356
|
-
term_termsource = safe_attr(term, :termsource)
|
|
357
|
-
term_admonition = safe_attr(term, :admonition)
|
|
358
|
-
term_nested = safe_attr(term, :term)
|
|
359
|
-
|
|
360
|
-
parts = []
|
|
361
|
-
if fmt_name
|
|
362
|
-
tn_content = render_inline_element(fmt_name)
|
|
363
|
-
parts << render_liquid("_term_number.html.liquid",
|
|
364
|
-
{ "content" => tn_content })
|
|
365
|
-
elsif term_number
|
|
366
|
-
tn_text = if term_number.is_a?(String)
|
|
367
|
-
term_number
|
|
368
|
-
else
|
|
369
|
-
extract_text_value(term_number)
|
|
370
|
-
end
|
|
371
|
-
parts << render_liquid("_term_number.html.liquid",
|
|
372
|
-
{ "content" => escape_html(tn_text) })
|
|
373
|
-
end
|
|
374
|
-
|
|
375
|
-
if fmt_preferred && !fmt_preferred.empty?
|
|
376
|
-
fmt_preferred.each do |fp|
|
|
377
|
-
fp.p&.each { |para| parts << (render_paragraph(para) || "") }
|
|
378
|
-
end
|
|
379
|
-
elsif term.preferred && !term.preferred.empty?
|
|
380
|
-
term.preferred&.each do |designation|
|
|
381
|
-
parts << (render_term_designation(designation, "preferred") || "")
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
if fmt_admitted && !fmt_admitted.empty?
|
|
386
|
-
fmt_admitted.each do |fa|
|
|
387
|
-
fa.p&.each { |para| parts << (render_paragraph(para) || "") }
|
|
388
|
-
end
|
|
389
|
-
elsif term.admitted && !term.admitted.empty?
|
|
390
|
-
term.admitted&.each do |designation|
|
|
391
|
-
parts << (render_term_designation(designation, "admitted") || "")
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
if fmt_deprecates
|
|
396
|
-
fmt_deprecates.p&.each do |para|
|
|
397
|
-
parts << (render_paragraph(para) || "")
|
|
398
|
-
end
|
|
399
|
-
elsif term.deprecates && !term.deprecates.empty?
|
|
400
|
-
term.deprecates&.each do |designation|
|
|
401
|
-
parts << (render_term_designation(designation, "deprecated") || "")
|
|
402
|
-
end
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
if term.domain && !fmt_definition
|
|
406
|
-
domain_text = safe_attr(term.domain, :text)
|
|
407
|
-
if domain_text
|
|
408
|
-
parts << render_liquid("_term_domain.html.liquid", {
|
|
409
|
-
"text" => escape_html(domain_text),
|
|
410
|
-
})
|
|
411
|
-
end
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
if fmt_definition
|
|
415
|
-
parts << (render_ordered_content(fmt_definition) || "")
|
|
416
|
-
else
|
|
417
|
-
term_p&.each { |para| parts << (render_paragraph(para) || "") }
|
|
418
|
-
term.definition&.each do |defn|
|
|
419
|
-
parts << (render_term_definition(defn) || "")
|
|
420
|
-
end
|
|
421
|
-
end
|
|
422
|
-
|
|
423
|
-
term_note&.each { |note| parts << (render_term_note(note) || "") }
|
|
424
|
-
term_example&.each { |ex| parts << (render_term_example(ex) || "") }
|
|
425
|
-
|
|
426
|
-
if fmt_termsource && !fmt_termsource.empty?
|
|
427
|
-
fmt_termsource.each do |fts|
|
|
428
|
-
src_content = render_mixed_inline(fts)
|
|
429
|
-
parts << render_liquid("_paragraph.html.liquid", {
|
|
430
|
-
"attrs" => " class=\"term-source\"",
|
|
431
|
-
"content" => src_content,
|
|
432
|
-
})
|
|
433
|
-
end
|
|
434
|
-
else
|
|
435
|
-
term.source&.each { |src| parts << (render_term_source(src) || "") }
|
|
436
|
-
term_termsource&.each do |src|
|
|
437
|
-
parts << (render_term_source_element(src) || "")
|
|
438
|
-
end
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
term_admonition&.each { |adm| parts << (render_admonition(adm) || "") }
|
|
442
|
-
term_nested&.each { |sub| parts << (render_term(sub) || "") }
|
|
443
|
-
|
|
444
|
-
render_liquid("_element.html.liquid", "tag" => "div",
|
|
445
|
-
"extra_attrs" => attrs, "content" => parts.join)
|
|
446
|
-
end
|
|
447
|
-
|
|
448
|
-
def extract_term_name(term)
|
|
449
|
-
fmt_pref = safe_attr(term, :fmt_preferred)
|
|
450
|
-
if fmt_pref && !fmt_pref.empty?
|
|
451
|
-
fp = fmt_pref.first
|
|
452
|
-
if fp.p && !fp.p.empty?
|
|
453
|
-
return extract_plain_text(fp.p.first)
|
|
454
|
-
end
|
|
455
|
-
end
|
|
456
|
-
if term.preferred && !term.preferred.empty?
|
|
457
|
-
return extract_designation_name(term.preferred.first).to_s
|
|
458
|
-
end
|
|
459
|
-
|
|
460
|
-
safe_attr(term, :id).to_s.delete_prefix("term-")
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
def extract_term_definition(term)
|
|
464
|
-
fmt_def = safe_attr(term, :fmt_definition)
|
|
465
|
-
return extract_plain_text(fmt_def) if fmt_def
|
|
466
|
-
|
|
467
|
-
term_p = safe_attr(term, :p)
|
|
468
|
-
if term_p && !term_p.empty?
|
|
469
|
-
text = term_p.map { |para| extract_plain_text(para) }.join(" ")
|
|
470
|
-
return text.strip unless text.strip.empty?
|
|
471
|
-
end
|
|
472
|
-
nil
|
|
473
|
-
end
|
|
474
|
-
|
|
475
333
|
def render_term_designation(designation, type)
|
|
476
334
|
css_class = type == "deprecated" ? "term-deprecated" : "term-name"
|
|
477
335
|
name = extract_designation_name(designation)
|
|
@@ -154,9 +154,11 @@ module Metanorma
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def render_unordered_list(ul, **_opts)
|
|
157
|
-
|
|
157
|
+
labeled = ul.listitem&.any? { |li| list_label(li) } || false
|
|
158
|
+
attrs = element_attrs(id: safe_attr(ul, :id),
|
|
159
|
+
class: labeled ? "mn-labeled-list" : nil)
|
|
158
160
|
items = ul.listitem&.filter_map do |li|
|
|
159
|
-
render_list_item_content(li)
|
|
161
|
+
render_list_item_content(li, labeled: labeled)
|
|
160
162
|
end || []
|
|
161
163
|
render_liquid("_list.html.liquid", {
|
|
162
164
|
"list_tag" => "ul",
|
|
@@ -182,10 +184,12 @@ module Metanorma
|
|
|
182
184
|
end
|
|
183
185
|
|
|
184
186
|
def render_ordered_list(ol, **_opts)
|
|
187
|
+
labeled = ol.listitem&.any? { |li| list_label(li) } || false
|
|
185
188
|
attrs = element_attrs(id: safe_attr(ol, :id),
|
|
189
|
+
class: labeled ? "mn-labeled-list" : nil,
|
|
186
190
|
start: safe_attr(ol, :start), type: safe_attr(ol, :type_attr))
|
|
187
191
|
items = ol.listitem&.filter_map do |li|
|
|
188
|
-
render_list_item_content(li)
|
|
192
|
+
render_list_item_content(li, labeled: labeled)
|
|
189
193
|
end || []
|
|
190
194
|
render_liquid("_list.html.liquid", {
|
|
191
195
|
"list_tag" => "ol",
|
|
@@ -194,14 +198,36 @@ module Metanorma
|
|
|
194
198
|
})
|
|
195
199
|
end
|
|
196
200
|
|
|
197
|
-
def render_list_item_content(li)
|
|
201
|
+
def render_list_item_content(li, labeled: false)
|
|
198
202
|
li_id = safe_attr(li, :id)
|
|
199
203
|
attrs = li_id ? %( id="#{escape_html(li_id)}") : ""
|
|
200
|
-
|
|
204
|
+
label = labeled ? list_label(li) : nil
|
|
205
|
+
inner = if label
|
|
206
|
+
coordinator.render_mixed_content_in_order(
|
|
207
|
+
li,
|
|
208
|
+
skip_classes: [Metanorma::Document::Components::Inline::FmtNameElement],
|
|
209
|
+
)
|
|
210
|
+
else
|
|
211
|
+
coordinator.render_mixed_content_in_order(li)
|
|
212
|
+
end
|
|
201
213
|
render_liquid("_list_item.html.liquid", "attrs" => attrs,
|
|
214
|
+
"label" => label && escape_html(label),
|
|
202
215
|
"content" => inner)
|
|
203
216
|
end
|
|
204
217
|
|
|
218
|
+
# Label glyph for a list item, taken from the presentation XML
|
|
219
|
+
# (the item's fmt-name/autonum). The presentation XML is
|
|
220
|
+
# authoritative for the bullet or number; when present it is
|
|
221
|
+
# rendered as the item marker and the browser's own list-style
|
|
222
|
+
# marker is suppressed (see components/lists.css).
|
|
223
|
+
def list_label(li)
|
|
224
|
+
fmt_name = coordinator.safe_attr(li, :fmt_name)
|
|
225
|
+
return nil unless fmt_name
|
|
226
|
+
|
|
227
|
+
label = coordinator.extract_plain_text(fmt_name).strip
|
|
228
|
+
label.empty? ? nil : label
|
|
229
|
+
end
|
|
230
|
+
|
|
205
231
|
def render_definition_list(dl, **_opts)
|
|
206
232
|
attrs = element_attrs(id: safe_attr(dl, :id))
|
|
207
233
|
terms = dl.dt&.each_with_index&.map do |dt, i|
|
|
@@ -271,6 +297,16 @@ module Metanorma
|
|
|
271
297
|
render_liquid("_example.html.liquid", { "block" => drop })
|
|
272
298
|
end
|
|
273
299
|
|
|
300
|
+
def render_form(form, **_opts)
|
|
301
|
+
attrs = element_attrs(id: safe_attr(form, :id), class: "form")
|
|
302
|
+
content = coordinator.render_ordered_content(form)
|
|
303
|
+
render_liquid("_element.html.liquid", {
|
|
304
|
+
"tag" => "div",
|
|
305
|
+
"extra_attrs" => attrs,
|
|
306
|
+
"content" => content,
|
|
307
|
+
})
|
|
308
|
+
end
|
|
309
|
+
|
|
274
310
|
def render_sourcecode(sc, **_opts)
|
|
275
311
|
drop = Drops::SourcecodeDrop.from_model(sc,
|
|
276
312
|
renderer: coordinator.renderer_context)
|
|
@@ -15,10 +15,24 @@ module Metanorma
|
|
|
15
15
|
module ElementOrderTraversal
|
|
16
16
|
module_function
|
|
17
17
|
|
|
18
|
+
# The map depends only on the model class's xml mapping, which is
|
|
19
|
+
# immutable after class definition — cache one map per mapping
|
|
20
|
+
# object instead of rebuilding it for every rendered node.
|
|
21
|
+
@cache = {}.compare_by_identity
|
|
22
|
+
|
|
23
|
+
def element_to_attr_map(xml_mapping)
|
|
24
|
+
@cache[xml_mapping] ||= build_map(xml_mapping)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Test/benchmark hook: drop all memoized maps.
|
|
28
|
+
def reset_cache!
|
|
29
|
+
@cache.clear
|
|
30
|
+
end
|
|
31
|
+
|
|
18
32
|
# Returns `{ xml_element_name => attr_name }` including both
|
|
19
33
|
# symbol and string keys for each mapped element, so callers
|
|
20
34
|
# can look up by either el.name form.
|
|
21
|
-
def
|
|
35
|
+
def build_map(xml_mapping)
|
|
22
36
|
{}.tap do |map|
|
|
23
37
|
xml_mapping.mapping_elements_hash.each_value do |rule_or_array|
|
|
24
38
|
Array(rule_or_array).each do |rule|
|