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.
- checksums.yaml +4 -4
- data/CLAUDE.md +3 -2
- data/README.adoc +1 -1
- data/Rakefile +30 -5
- 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/csa_document/root.rb +27 -0
- 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/semx_element.rb +7 -8
- 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 +1 -0
- data/lib/metanorma/html/base_renderer.rb +133 -307
- data/lib/metanorma/html/component/base.rb +2 -9
- 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 +50 -0
- data/lib/metanorma/html/flavor_registry.rb +49 -0
- data/lib/metanorma/html/generator.rb +113 -29
- data/lib/metanorma/html/iso_renderer.rb +0 -142
- data/lib/metanorma/html/renderer_delegation.rb +21 -0
- data/lib/metanorma/html/renderers/block_renderer.rb +10 -0
- data/lib/metanorma/html/renderers/element_order_traversal.rb +48 -0
- data/lib/metanorma/html/renderers/inline_renderer.rb +49 -124
- data/lib/metanorma/html/renderers/pubid_renderer.rb +4 -26
- data/lib/metanorma/html/renderers.rb +2 -0
- data/lib/metanorma/html/standard_renderer.rb +198 -36
- data/lib/metanorma/html.rb +4 -51
- 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 +52 -0
- data/lib/metanorma/mirror/handlers/inline/rich_html_renderer.rb +34 -35
- data/lib/metanorma/mirror/handlers/inline.rb +1 -0
- 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/mirror/transformer.rb +91 -3
- data/lib/metanorma/mirror.rb +0 -1
- data/lib/metanorma/registers/setup.rb +10 -0
- 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 +1 -1
- metadata +78 -50
- data/.rubocop_todo.yml +0 -327
- 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/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/mirror/metanorma_to_mirror.rb +0 -101
- 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 -64
- 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/standard_document/annotation.rb +0 -37
|
@@ -160,57 +160,217 @@ module Metanorma
|
|
|
160
160
|
|
|
161
161
|
# --- Term rendering ---
|
|
162
162
|
|
|
163
|
+
# Unified term entry renderer. Handles both semantic-only term models
|
|
164
|
+
# (StandardDocument::Terms::Term) and presentation-aware models with
|
|
165
|
+
# fmt-* attributes (IsoDocument::Terms::IsoTerm): safe_attr returns nil
|
|
166
|
+
# for attributes a model does not declare, so the fmt-* branches are
|
|
167
|
+
# skipped automatically on semantic-only models.
|
|
163
168
|
def render_term(term, **_opts)
|
|
164
|
-
attrs = element_attrs(id: safe_attr(term, :id))
|
|
169
|
+
attrs = element_attrs(id: safe_attr(term, :id), **term_data_attrs(term))
|
|
170
|
+
fmt_definition = safe_attr(term, :fmt_definition)
|
|
171
|
+
|
|
165
172
|
parts = []
|
|
166
|
-
term
|
|
167
|
-
|
|
173
|
+
parts << (render_term_number(term) || "")
|
|
174
|
+
parts << render_term_designations(term, :fmt_preferred, :preferred,
|
|
175
|
+
"preferred")
|
|
176
|
+
parts << render_term_designations(term, :fmt_admitted, :admitted,
|
|
177
|
+
"admitted")
|
|
178
|
+
parts << render_term_designations(term, :fmt_deprecates, :deprecates,
|
|
179
|
+
"deprecated")
|
|
180
|
+
parts << (render_term_domain(term, fmt_definition) || "")
|
|
181
|
+
parts << render_term_definitions(term, fmt_definition)
|
|
182
|
+
parts << render_term_note_parts(term)
|
|
183
|
+
parts << render_term_example_parts(term)
|
|
184
|
+
parts << render_term_source_parts(term)
|
|
185
|
+
safe_attr(term, :admonition)&.each do |admonition|
|
|
186
|
+
parts << (render_admonition(admonition) || "")
|
|
168
187
|
end
|
|
169
|
-
term
|
|
170
|
-
|
|
188
|
+
safe_attr(term, :term)&.each { |sub| parts << (render_term(sub) || "") }
|
|
189
|
+
render_liquid("_element.html.liquid", {
|
|
190
|
+
"tag" => "div",
|
|
191
|
+
"extra_attrs" => attrs,
|
|
192
|
+
"content" => parts.join,
|
|
193
|
+
})
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def term_data_attrs(term)
|
|
197
|
+
term_name = extract_term_name(term)
|
|
198
|
+
term_definition = extract_term_definition(term)
|
|
199
|
+
data_attrs = {}
|
|
200
|
+
if term_name && !term_name.empty?
|
|
201
|
+
data_attrs["data-term-name"] = term_name
|
|
171
202
|
end
|
|
172
|
-
|
|
173
|
-
|
|
203
|
+
if term_definition && !term_definition.empty?
|
|
204
|
+
data_attrs["data-term-definition"] = term_definition
|
|
174
205
|
end
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
206
|
+
data_attrs
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def render_term_number(term)
|
|
210
|
+
fmt_name = safe_attr(term, :fmt_name)
|
|
211
|
+
term_number = safe_attr(term, :term_number)
|
|
212
|
+
if fmt_name
|
|
213
|
+
render_liquid("_term_number.html.liquid", {
|
|
214
|
+
"content" => render_inline_element(fmt_name),
|
|
215
|
+
})
|
|
216
|
+
elsif term_number
|
|
217
|
+
number_text = if term_number.is_a?(String)
|
|
218
|
+
term_number
|
|
179
219
|
else
|
|
180
|
-
|
|
220
|
+
extract_text_value(term_number)
|
|
181
221
|
end
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
222
|
+
render_liquid("_term_number.html.liquid", {
|
|
223
|
+
"content" => escape_html(number_text),
|
|
224
|
+
})
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Designations (preferred/admitted/deprecated): fmt-* presentation
|
|
229
|
+
# elements win when present; otherwise render semantic designations.
|
|
230
|
+
def render_term_designations(term, fmt_attr, semantic_attr, type)
|
|
231
|
+
fmt = safe_attr(term, fmt_attr)
|
|
232
|
+
fmt_list = fmt.is_a?(Array) ? fmt : [fmt].compact
|
|
233
|
+
parts = []
|
|
234
|
+
if fmt_list.empty?
|
|
235
|
+
term.public_send(semantic_attr)&.each do |designation|
|
|
236
|
+
parts << (render_term_designation(designation, type) || "")
|
|
237
|
+
end
|
|
238
|
+
else
|
|
239
|
+
fmt_list.each do |element|
|
|
240
|
+
element.p&.each { |para| parts << (render_paragraph(para) || "") }
|
|
186
241
|
end
|
|
187
242
|
end
|
|
243
|
+
parts.join
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def render_term_domain(term, fmt_definition)
|
|
247
|
+
return nil if fmt_definition
|
|
248
|
+
|
|
249
|
+
domain = term.domain
|
|
250
|
+
return nil unless domain
|
|
251
|
+
|
|
252
|
+
domain_text = domain.is_a?(String) ? domain : safe_attr(domain, :text).to_s
|
|
253
|
+
return nil if domain_text.empty?
|
|
254
|
+
|
|
255
|
+
render_liquid("_term_domain.html.liquid", {
|
|
256
|
+
"text" => escape_html(domain_text),
|
|
257
|
+
}).to_s
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def render_term_definitions(term, fmt_definition)
|
|
261
|
+
return render_ordered_content(fmt_definition) || "" if fmt_definition
|
|
262
|
+
|
|
263
|
+
parts = []
|
|
264
|
+
safe_attr(term, :p)&.each do |para|
|
|
265
|
+
parts << (render_paragraph(para) || "")
|
|
266
|
+
end
|
|
267
|
+
term.definition&.each do |definition|
|
|
268
|
+
parts << (render_term_definition(definition) || "")
|
|
269
|
+
end
|
|
270
|
+
parts.join
|
|
271
|
+
end
|
|
188
272
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
273
|
+
def render_term_note_parts(term)
|
|
274
|
+
notes = safe_attr(term, :termnote) || Array(safe_attr(term, :note))
|
|
275
|
+
parts = []
|
|
276
|
+
notes.each_with_index do |note, i|
|
|
277
|
+
parts << (render_term_note_item(note, i) || "")
|
|
278
|
+
end
|
|
279
|
+
parts.join
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# A term note can be a raw String (rendered with a "Note N to entry"
|
|
283
|
+
# label), a termnote element (labelled wrapper), or a plain block
|
|
284
|
+
# (rendered as a generic note).
|
|
285
|
+
def render_term_note_item(note, index)
|
|
286
|
+
if note.is_a?(String)
|
|
287
|
+
render_liquid("_term_text_note.html.liquid", {
|
|
288
|
+
"label" => "Note #{index + 1} to entry: ",
|
|
289
|
+
"content" => escape_html(note),
|
|
290
|
+
}).to_s
|
|
291
|
+
elsif term_scoped_block?(note)
|
|
292
|
+
render_term_note(note)
|
|
293
|
+
else
|
|
294
|
+
render_note(note)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def render_term_example_parts(term)
|
|
299
|
+
examples = safe_attr(term, :termexample) ||
|
|
300
|
+
Array(safe_attr(term, :example))
|
|
301
|
+
examples.map do |example|
|
|
302
|
+
render_term_example_item(example) || ""
|
|
303
|
+
end.join
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# A term example can be a termexample element (labelled wrapper), a
|
|
307
|
+
# raw String, or a plain paragraph block (both rendered as paragraphs).
|
|
308
|
+
# render_paragraph cannot take a bare String (render_mixed_inline
|
|
309
|
+
# expects a model), so Strings go through the paragraph template
|
|
310
|
+
# directly — same markup render_paragraph would emit.
|
|
311
|
+
def render_term_example_item(example)
|
|
312
|
+
if example.is_a?(String)
|
|
313
|
+
return render_liquid("_paragraph.html.liquid", {
|
|
314
|
+
"attrs" => "",
|
|
315
|
+
"content" => escape_html(example),
|
|
316
|
+
})
|
|
317
|
+
end
|
|
318
|
+
return render_term_example(example) if term_scoped_block?(example)
|
|
319
|
+
|
|
320
|
+
render_paragraph(example)
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Termnote/termexample elements wrap block children (`p`, lists);
|
|
324
|
+
# plain paragraph blocks and Strings do not declare a `p` attribute.
|
|
325
|
+
def term_scoped_block?(node)
|
|
326
|
+
node.is_a?(Lutaml::Model::Serializable) &&
|
|
327
|
+
node.class.attributes.key?(:p)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def render_term_source_parts(term)
|
|
331
|
+
fmt_termsource = safe_attr(term, :fmt_termsource)
|
|
332
|
+
parts = []
|
|
333
|
+
if fmt_termsource && !fmt_termsource.empty?
|
|
334
|
+
fmt_termsource.each do |source|
|
|
335
|
+
parts << render_liquid("_paragraph.html.liquid", {
|
|
336
|
+
"attrs" => " class=\"term-source\"",
|
|
337
|
+
"content" => render_mixed_inline(source),
|
|
338
|
+
})
|
|
339
|
+
end
|
|
340
|
+
else
|
|
341
|
+
term.source&.each { |src| parts << (render_term_source(src) || "") }
|
|
342
|
+
safe_attr(term, :termsource)&.each do |source|
|
|
343
|
+
parts << (render_term_source_element(source) || "")
|
|
192
344
|
end
|
|
193
345
|
end
|
|
346
|
+
parts.join
|
|
347
|
+
end
|
|
194
348
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}).to_s
|
|
202
|
-
else
|
|
203
|
-
parts << (render_note(note) || "")
|
|
349
|
+
def extract_term_name(term)
|
|
350
|
+
fmt_pref = safe_attr(term, :fmt_preferred)
|
|
351
|
+
if fmt_pref && !fmt_pref.empty?
|
|
352
|
+
fp = fmt_pref.first
|
|
353
|
+
if fp.p && !fp.p.empty?
|
|
354
|
+
return extract_plain_text(fp.p.first)
|
|
204
355
|
end
|
|
205
356
|
end
|
|
357
|
+
if term.preferred && !term.preferred.empty?
|
|
358
|
+
return extract_designation_name(term.preferred.first).to_s
|
|
359
|
+
end
|
|
206
360
|
|
|
207
|
-
term.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
361
|
+
safe_attr(term, :id).to_s.delete_prefix("term-")
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def extract_term_definition(term)
|
|
365
|
+
fmt_def = safe_attr(term, :fmt_definition)
|
|
366
|
+
return extract_plain_text(fmt_def) if fmt_def
|
|
367
|
+
|
|
368
|
+
term_p = safe_attr(term, :p)
|
|
369
|
+
if term_p && !term_p.empty?
|
|
370
|
+
text = term_p.map { |para| extract_plain_text(para) }.join(" ")
|
|
371
|
+
return text.strip unless text.strip.empty?
|
|
372
|
+
end
|
|
373
|
+
nil
|
|
214
374
|
end
|
|
215
375
|
|
|
216
376
|
def render_term_designation(designation, _type)
|
|
@@ -454,11 +614,13 @@ module Metanorma
|
|
|
454
614
|
[prefix_text, rest.empty? ? nil : rest]
|
|
455
615
|
end
|
|
456
616
|
|
|
617
|
+
PREFERRED_LINK_TYPES = %w[src citation].freeze
|
|
618
|
+
|
|
457
619
|
def bibitem_url(item)
|
|
458
620
|
links = Array(item.link)
|
|
459
621
|
return nil if links.empty?
|
|
460
622
|
|
|
461
|
-
preferred = links.find { |l|
|
|
623
|
+
preferred = links.find { |l| PREFERRED_LINK_TYPES.include?(l.type) }
|
|
462
624
|
return preferred.content.to_s if preferred && !preferred.content.to_s.empty?
|
|
463
625
|
|
|
464
626
|
non_rss = links.find do |l|
|
data/lib/metanorma/html.rb
CHANGED
|
@@ -11,61 +11,13 @@ module Metanorma
|
|
|
11
11
|
Liquid::Environment.default.file_system = Liquid::LocalFileSystem.new(
|
|
12
12
|
TEMPLATES_ROOT, "_%s.html.liquid"
|
|
13
13
|
)
|
|
14
|
-
|
|
15
|
-
Moxml::Adapter::Nokogiri.class_eval do
|
|
16
|
-
class << self
|
|
17
|
-
alias_method :_original_children_patched, :children
|
|
18
|
-
remove_method :children
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.children(node)
|
|
22
|
-
node.children.to_a
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Patch missing Moxml module method used by lutaml-model XML serializer
|
|
28
|
-
::Moxml.class_eval do
|
|
29
|
-
def self.preprocess_entities(text)
|
|
30
|
-
if block_given?
|
|
31
|
-
yield text
|
|
32
|
-
else
|
|
33
|
-
text
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
module Html
|
|
39
|
-
Lutaml::Xml::XmlElement.class_eval do
|
|
40
|
-
remove_method :order
|
|
41
|
-
|
|
42
|
-
def order
|
|
43
|
-
return @order_cache if @order_cache
|
|
44
|
-
|
|
45
|
-
@order_cache = children.filter_map do |child|
|
|
46
|
-
if child.text?
|
|
47
|
-
Lutaml::Xml::Element.new("Text", "text",
|
|
48
|
-
text_content: child.text,
|
|
49
|
-
node_type: :text)
|
|
50
|
-
elsif child.cdata?
|
|
51
|
-
Lutaml::Xml::Element.new("Text", "#cdata-section",
|
|
52
|
-
text_content: child.text,
|
|
53
|
-
node_type: :cdata)
|
|
54
|
-
elsif child.comment?
|
|
55
|
-
nil
|
|
56
|
-
else
|
|
57
|
-
Lutaml::Xml::Element.new("Element", child.unprefixed_name,
|
|
58
|
-
node_type: :element,
|
|
59
|
-
namespace_uri: child.namespace_uri,
|
|
60
|
-
namespace_prefix: child.namespace_prefix)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
14
|
end
|
|
66
15
|
|
|
67
16
|
autoload :BaseRenderer, "metanorma/html/base_renderer"
|
|
17
|
+
autoload :Flavor, "metanorma/html/flavor"
|
|
18
|
+
autoload :FlavorRegistry, "metanorma/html/flavor_registry"
|
|
68
19
|
autoload :Generator, "metanorma/html/generator"
|
|
20
|
+
autoload :RendererDelegation, "metanorma/html/renderer_delegation"
|
|
69
21
|
autoload :Theme, "metanorma/html/theme"
|
|
70
22
|
autoload :AssetPipeline, "metanorma/html/asset_pipeline"
|
|
71
23
|
autoload :Component, "metanorma/html/component"
|
|
@@ -74,6 +26,7 @@ module Metanorma
|
|
|
74
26
|
autoload :IsoRenderer, "metanorma/html/iso_renderer"
|
|
75
27
|
autoload :BipmRenderer, "metanorma/html/bipm_renderer"
|
|
76
28
|
autoload :CcRenderer, "metanorma/html/cc_renderer"
|
|
29
|
+
autoload :CsaRenderer, "metanorma/html/csa_renderer"
|
|
77
30
|
autoload :IccRenderer, "metanorma/html/icc_renderer"
|
|
78
31
|
autoload :PdfaRenderer, "metanorma/html/pdfa_renderer"
|
|
79
32
|
autoload :IecRenderer, "metanorma/html/iec_renderer"
|
|
@@ -4,30 +4,44 @@ module Metanorma
|
|
|
4
4
|
module IsoDocument
|
|
5
5
|
module Sections
|
|
6
6
|
# Prefatory clauses in an ISO/IEC document.
|
|
7
|
-
#
|
|
8
|
-
# abstract
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
# Corresponds to isostandard.rng:
|
|
8
|
+
# preface = element preface { abstract?, foreword, introduction? }
|
|
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 and
|
|
13
|
+
# executivesummary mappings that the ISO grammar forbids. Attributes
|
|
14
|
+
# are composed directly instead.
|
|
15
|
+
#
|
|
16
|
+
# The `clause` mapping is a documented extension required by real ISO
|
|
17
|
+
# presentation output, which emits front-matter clauses such as
|
|
18
|
+
# `<clause type="toc">` ahead of the foreword. `content` mirrors
|
|
19
|
+
# `clause` for the generic preface-content consumers (e.g. the mirror
|
|
20
|
+
# renderer), matching the runtime behavior of the previous inherited
|
|
21
|
+
# dual mapping.
|
|
22
|
+
class IsoPreface < Lutaml::Model::Serializable
|
|
14
23
|
attribute :abstract, IsoAbstractSection
|
|
15
24
|
attribute :foreword, IsoForewordSection
|
|
16
25
|
attribute :introduction, IsoClauseSection
|
|
17
26
|
|
|
18
|
-
#
|
|
27
|
+
# Presentation front-matter clauses (e.g. table of contents placeholder)
|
|
19
28
|
attribute :clause, IsoClauseSection, collection: true
|
|
29
|
+
attribute :content, Metanorma::StandardDocument::Sections::ContentSection,
|
|
30
|
+
collection: true
|
|
20
31
|
|
|
21
|
-
#
|
|
22
|
-
attribute :
|
|
23
|
-
attribute :
|
|
32
|
+
# Presentation-specific attributes
|
|
33
|
+
attribute :semx_id, :string
|
|
34
|
+
attribute :displayorder, :integer
|
|
24
35
|
|
|
25
36
|
xml do
|
|
26
37
|
element "preface"
|
|
27
38
|
ordered
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
map_element "
|
|
40
|
+
map_element "abstract", to: :abstract
|
|
41
|
+
map_element "foreword", to: :foreword
|
|
42
|
+
map_element "introduction", to: :introduction
|
|
43
|
+
map_element "clause", to: :clause
|
|
44
|
+
map_element "clause", to: :content
|
|
31
45
|
|
|
32
46
|
Metanorma::StandardDocument::SectionXmlMapping.apply_preface_attributes(self)
|
|
33
47
|
end
|
|
@@ -153,6 +153,27 @@ module Metanorma
|
|
|
153
153
|
Handlers::Structural,
|
|
154
154
|
method_name: :preface,
|
|
155
155
|
)
|
|
156
|
+
# IsoPreface and UnPreface deliberately do not inherit
|
|
157
|
+
# StandardDocument::Preface (grammar-strict classes compose from
|
|
158
|
+
# mixins), so they need explicit registrations — the registry
|
|
159
|
+
# resolves handlers through class ancestry.
|
|
160
|
+
registry.register(
|
|
161
|
+
Metanorma::IsoDocument::Sections::IsoPreface,
|
|
162
|
+
Handlers::Structural,
|
|
163
|
+
method_name: :preface,
|
|
164
|
+
)
|
|
165
|
+
registry.register(
|
|
166
|
+
Metanorma::UnDocument::Sections::UnPreface,
|
|
167
|
+
Handlers::Structural,
|
|
168
|
+
method_name: :preface,
|
|
169
|
+
)
|
|
170
|
+
# UnAbstractSection likewise composes instead of inheriting
|
|
171
|
+
# ContentSection.
|
|
172
|
+
registry.register(
|
|
173
|
+
Metanorma::UnDocument::Sections::UnAbstractSection,
|
|
174
|
+
Handlers::Section,
|
|
175
|
+
method_name: :content_section,
|
|
176
|
+
)
|
|
156
177
|
registry.register(
|
|
157
178
|
Metanorma::StandardDocument::Sections::Sections,
|
|
158
179
|
Handlers::Structural,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
module Mirror
|
|
5
|
+
module Handlers
|
|
6
|
+
module Inline
|
|
7
|
+
# Shared declarative table of inline marks whose HTML rendering is
|
|
8
|
+
# a fixed tag with optional static attrs. It is consumed by
|
|
9
|
+
# RichHtmlRenderer, which renders Metanorma XML elements to HTML
|
|
10
|
+
# directly (the fallback / attribute-value path) during the
|
|
11
|
+
# forward transform into the mirror IR.
|
|
12
|
+
#
|
|
13
|
+
# Marks whose attrs vary per instance (link, xref, eref, span)
|
|
14
|
+
# carry data in mark.attrs and are not in this table; each
|
|
15
|
+
# consumer keeps custom handlers for those.
|
|
16
|
+
module Catalog
|
|
17
|
+
SIMPLE_WRAPS = {
|
|
18
|
+
"emphasis" => { tag: :em },
|
|
19
|
+
"strong" => { tag: :strong },
|
|
20
|
+
"subscript" => { tag: :sub },
|
|
21
|
+
"superscript" => { tag: :sup },
|
|
22
|
+
"code" => { tag: :code },
|
|
23
|
+
"underline" => { tag: :u },
|
|
24
|
+
"strike" => { tag: :s },
|
|
25
|
+
"smallcap" => { tag: :span, style: "font-variant: small-caps" },
|
|
26
|
+
"concept" => { tag: :span, class: "concept" },
|
|
27
|
+
"bcp14" => { tag: :span, class: "bcp14" },
|
|
28
|
+
"footnote" => { tag: :sup, class: "footnote-inline" },
|
|
29
|
+
"stem" => { tag: :span, class: "stem" },
|
|
30
|
+
}.freeze
|
|
31
|
+
|
|
32
|
+
# XML element classes that render via SIMPLE_WRAPS without
|
|
33
|
+
# per-instance attrs. Maps element class → mark type (catalog
|
|
34
|
+
# key). RichHtmlRenderer uses this to dispatch simple elements
|
|
35
|
+
# through the shared table.
|
|
36
|
+
SIMPLE_ELEMENTS = {
|
|
37
|
+
Metanorma::Document::Components::Inline::EmRawElement => "emphasis",
|
|
38
|
+
Metanorma::Document::Components::Inline::StrongRawElement => "strong",
|
|
39
|
+
Metanorma::Document::Components::Inline::SubElement => "subscript",
|
|
40
|
+
Metanorma::Document::Components::Inline::SupElement => "superscript",
|
|
41
|
+
Metanorma::Document::Components::Inline::TtElement => "code",
|
|
42
|
+
Metanorma::Document::Components::TextElements::UnderlineElement => "underline",
|
|
43
|
+
Metanorma::Document::Components::TextElements::StrikeElement => "strike",
|
|
44
|
+
Metanorma::Document::Components::Inline::SmallCapElement => "smallcap",
|
|
45
|
+
Metanorma::Document::Components::Inline::Bcp14Element => "bcp14",
|
|
46
|
+
Metanorma::Document::Components::Inline::ConceptElement => "concept",
|
|
47
|
+
}.freeze
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -10,35 +10,14 @@ module Metanorma
|
|
|
10
10
|
# representation of inline content is required (e.g., attribute values,
|
|
11
11
|
# fallback rendering). All HTML construction goes through
|
|
12
12
|
# Nokogiri::HTML5::Builder to guarantee well-formed, escaped output.
|
|
13
|
+
#
|
|
14
|
+
# Simple-wrap elements (em, strong, sub, sup, code, u, s, smallcap,
|
|
15
|
+
# bcp14, concept) take their tag-and-attrs mapping from the shared
|
|
16
|
+
# Inline::Catalog table.
|
|
13
17
|
module RichHtmlRenderer
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
},
|
|
18
|
-
Metanorma::Document::Components::Inline::StrongRawElement => ->(el) {
|
|
19
|
-
wrap { |d| d.strong { d << raw(extract(el)) } }
|
|
20
|
-
},
|
|
21
|
-
Metanorma::Document::Components::Inline::SubElement => ->(el) {
|
|
22
|
-
wrap { |d| d.sub { d << raw(extract(el)) } }
|
|
23
|
-
},
|
|
24
|
-
Metanorma::Document::Components::Inline::SupElement => ->(el) {
|
|
25
|
-
wrap { |d| d.sup { d << raw(extract(el)) } }
|
|
26
|
-
},
|
|
27
|
-
Metanorma::Document::Components::Inline::TtElement => ->(el) {
|
|
28
|
-
wrap { |d| d.code { d << raw(extract(el)) } }
|
|
29
|
-
},
|
|
30
|
-
Metanorma::Document::Components::TextElements::UnderlineElement => ->(el) {
|
|
31
|
-
wrap { |d| d.u { d << raw(extract(el)) } }
|
|
32
|
-
},
|
|
33
|
-
Metanorma::Document::Components::TextElements::StrikeElement => ->(el) {
|
|
34
|
-
wrap { |d| d.s { d << raw(extract(el)) } }
|
|
35
|
-
},
|
|
36
|
-
Metanorma::Document::Components::Inline::SmallCapElement => ->(el) {
|
|
37
|
-
wrap { |d| d.span { d << raw(extract(el)) } }
|
|
38
|
-
},
|
|
39
|
-
Metanorma::Document::Components::Inline::Bcp14Element => ->(el) {
|
|
40
|
-
wrap { |d| d.span { d << raw(extract(el)) } }
|
|
41
|
-
},
|
|
18
|
+
# Complex element handlers — these have per-instance attrs or
|
|
19
|
+
# multi-step rendering and bypass the shared Catalog.
|
|
20
|
+
COMPLEX_RENDERERS = {
|
|
42
21
|
Metanorma::Document::Components::Inline::StemInlineElement => ->(el) {
|
|
43
22
|
for_stem(el)
|
|
44
23
|
},
|
|
@@ -57,9 +36,6 @@ module Metanorma
|
|
|
57
36
|
Metanorma::Document::Components::Inline::FnElement => ->(el) {
|
|
58
37
|
for_fn(el)
|
|
59
38
|
},
|
|
60
|
-
Metanorma::Document::Components::Inline::ConceptElement => ->(el) {
|
|
61
|
-
wrap { |d| d.span(class: "concept") { d << raw(extract(el)) } }
|
|
62
|
-
},
|
|
63
39
|
Metanorma::Document::Components::Inline::SpanElement => ->(el) {
|
|
64
40
|
for_span(el)
|
|
65
41
|
},
|
|
@@ -93,8 +69,25 @@ module Metanorma
|
|
|
93
69
|
end
|
|
94
70
|
|
|
95
71
|
def self.render_element(element)
|
|
96
|
-
|
|
97
|
-
|
|
72
|
+
complex = COMPLEX_RENDERERS[element.class]
|
|
73
|
+
return complex.call(element) if complex
|
|
74
|
+
|
|
75
|
+
mark_type = Catalog::SIMPLE_ELEMENTS[element.class]
|
|
76
|
+
return render_simple(mark_type, element) if mark_type
|
|
77
|
+
|
|
78
|
+
extract(element)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.render_simple(mark_type, element)
|
|
82
|
+
spec = Catalog::SIMPLE_WRAPS[mark_type]
|
|
83
|
+
attrs = spec.except(:tag)
|
|
84
|
+
wrap do |d|
|
|
85
|
+
if attrs.empty?
|
|
86
|
+
d.public_send(spec[:tag]) { d << raw(extract(element)) }
|
|
87
|
+
else
|
|
88
|
+
d.public_send(spec[:tag], attrs) { d << raw(extract(element)) }
|
|
89
|
+
end
|
|
90
|
+
end
|
|
98
91
|
end
|
|
99
92
|
|
|
100
93
|
def self.for_stem(element)
|
|
@@ -105,7 +98,10 @@ module Metanorma
|
|
|
105
98
|
.sub(/\s*xmlns(:\w+)?="[^"]*"\s*/, " ")
|
|
106
99
|
.gsub(/\s+/, " ")
|
|
107
100
|
.strip
|
|
108
|
-
|
|
101
|
+
spec = Catalog::SIMPLE_WRAPS["stem"]
|
|
102
|
+
wrap do |d|
|
|
103
|
+
d.public_send(spec[:tag], spec.except(:tag)) { d << raw(mathml) }
|
|
104
|
+
end
|
|
109
105
|
end
|
|
110
106
|
|
|
111
107
|
def self.for_xref(element)
|
|
@@ -130,7 +126,10 @@ module Metanorma
|
|
|
130
126
|
|
|
131
127
|
def self.for_fn(element)
|
|
132
128
|
reference = SafeAttr.read(element, :reference) || ""
|
|
133
|
-
|
|
129
|
+
spec = Catalog::SIMPLE_WRAPS["footnote"]
|
|
130
|
+
wrap do |d|
|
|
131
|
+
d.public_send(spec[:tag], spec.except(:tag)) { d.text reference }
|
|
132
|
+
end
|
|
134
133
|
end
|
|
135
134
|
|
|
136
135
|
def self.for_span(element)
|
|
@@ -6,6 +6,7 @@ module Metanorma
|
|
|
6
6
|
module Inline
|
|
7
7
|
autoload :TextExtractor, "#{__dir__}/inline/text_extractor"
|
|
8
8
|
autoload :RichHtmlRenderer, "#{__dir__}/inline/rich_html_renderer"
|
|
9
|
+
autoload :Catalog, "#{__dir__}/inline/catalog"
|
|
9
10
|
|
|
10
11
|
MARK_BUILDERS = {
|
|
11
12
|
Metanorma::Document::Components::Inline::EmRawElement => ->(_el) {
|
|
@@ -4,12 +4,13 @@ module Metanorma
|
|
|
4
4
|
module Mirror
|
|
5
5
|
module Model
|
|
6
6
|
class Guide
|
|
7
|
-
attr_reader :content, :meta, :title
|
|
7
|
+
attr_reader :content, :meta, :title, :document
|
|
8
8
|
|
|
9
|
-
def initialize(content:, meta: {}, title: nil)
|
|
9
|
+
def initialize(content:, meta: {}, title: nil, document: nil)
|
|
10
10
|
@content = content
|
|
11
11
|
@meta = meta
|
|
12
12
|
@title = title
|
|
13
|
+
@document = document
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def to_h
|