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.
- checksums.yaml +4 -4
- data/CLAUDE.md +3 -2
- 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/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 +86 -234
- 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 -1
- data/lib/metanorma/html/iso_renderer.rb +0 -142
- data/lib/metanorma/html/renderers/block_renderer.rb +10 -0
- data/lib/metanorma/html/renderers/element_order_traversal.rb +15 -1
- data/lib/metanorma/html/renderers/inline_renderer.rb +13 -75
- data/lib/metanorma/html/standard_renderer.rb +195 -35
- data/lib/metanorma/html.rb +1 -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 +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 +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 +63 -45
- 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/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/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/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
|
|
272
|
+
|
|
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
|
|
188
322
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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)
|
data/lib/metanorma/html.rb
CHANGED
|
@@ -11,57 +11,6 @@ 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"
|
|
@@ -77,6 +26,7 @@ module Metanorma
|
|
|
77
26
|
autoload :IsoRenderer, "metanorma/html/iso_renderer"
|
|
78
27
|
autoload :BipmRenderer, "metanorma/html/bipm_renderer"
|
|
79
28
|
autoload :CcRenderer, "metanorma/html/cc_renderer"
|
|
29
|
+
autoload :CsaRenderer, "metanorma/html/csa_renderer"
|
|
80
30
|
autoload :IccRenderer, "metanorma/html/icc_renderer"
|
|
81
31
|
autoload :PdfaRenderer, "metanorma/html/pdfa_renderer"
|
|
82
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,
|
|
@@ -5,19 +5,14 @@ module Metanorma
|
|
|
5
5
|
module Handlers
|
|
6
6
|
module Inline
|
|
7
7
|
# Shared declarative table of inline marks whose HTML rendering is
|
|
8
|
-
# a fixed tag with optional static attrs.
|
|
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.
|
|
9
12
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# to HTML (the primary SSR path).
|
|
14
|
-
#
|
|
15
|
-
# Both adapters must produce visually equivalent HTML for the same
|
|
16
|
-
# mark type — the table is the single source of truth for the
|
|
17
|
-
# mark-name to tag-and-attrs mapping. Marks whose attrs vary per
|
|
18
|
-
# instance (link, xref, eref, span) carry data in mark.attrs and
|
|
19
|
-
# are not in this table; each adapter keeps custom handlers for
|
|
20
|
-
# those.
|
|
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.
|
|
21
16
|
module Catalog
|
|
22
17
|
SIMPLE_WRAPS = {
|
|
23
18
|
"emphasis" => { tag: :em },
|
|
@@ -12,9 +12,8 @@ module Metanorma
|
|
|
12
12
|
# Nokogiri::HTML5::Builder to guarantee well-formed, escaped output.
|
|
13
13
|
#
|
|
14
14
|
# Simple-wrap elements (em, strong, sub, sup, code, u, s, smallcap,
|
|
15
|
-
# bcp14, concept)
|
|
16
|
-
#
|
|
17
|
-
# produce visually equivalent output for the same mark type.
|
|
15
|
+
# bcp14, concept) take their tag-and-attrs mapping from the shared
|
|
16
|
+
# Inline::Catalog table.
|
|
18
17
|
module RichHtmlRenderer
|
|
19
18
|
# Complex element handlers — these have per-instance attrs or
|
|
20
19
|
# multi-step rendering and bypass the shared Catalog.
|
|
@@ -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
|
|
@@ -8,12 +8,42 @@ module Metanorma
|
|
|
8
8
|
module Output
|
|
9
9
|
module Formats
|
|
10
10
|
class InlineFormat < BaseFormat
|
|
11
|
+
# Classic content styles inlined for the no-JS SSR body: reset +
|
|
12
|
+
# typography + block/inline component styles from the classic
|
|
13
|
+
# asset pipeline. Page chrome (layout, print, transitions, dark,
|
|
14
|
+
# cover, header, footer, toc, search, progress, shortcuts,
|
|
15
|
+
# glossary panel, flavor modules) is owned by the SPA and
|
|
16
|
+
# excluded.
|
|
17
|
+
CONTENT_CSS_MODULES = %w[
|
|
18
|
+
base/_reset
|
|
19
|
+
base/_typography
|
|
20
|
+
components/section
|
|
21
|
+
components/note
|
|
22
|
+
components/example
|
|
23
|
+
components/sourcecode
|
|
24
|
+
components/formula
|
|
25
|
+
components/admonition
|
|
26
|
+
components/table
|
|
27
|
+
components/footnote
|
|
28
|
+
components/figure
|
|
29
|
+
components/term
|
|
30
|
+
components/bibliography
|
|
31
|
+
components/inline
|
|
32
|
+
components/index
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
attr_accessor :missing_bundle_warned
|
|
37
|
+
end
|
|
38
|
+
|
|
11
39
|
def write(output_path, guide, title: "Metanorma")
|
|
12
40
|
FileUtils.mkdir_p(File.dirname(output_path))
|
|
13
41
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
42
|
+
warn_missing_bundle unless iife_bundle_exists?
|
|
43
|
+
|
|
44
|
+
data_script = "window.METANORMA_DATA = #{safe_json(guide.to_h)};"
|
|
45
|
+
ssr_body = render_ssr_body(guide)
|
|
46
|
+
head_parts = [build_style(classic_content_css)]
|
|
17
47
|
css_inline = read_css_inline
|
|
18
48
|
if css_inline && !css_inline.empty?
|
|
19
49
|
head_parts << build_style(css_inline)
|
|
@@ -42,6 +72,37 @@ module Metanorma
|
|
|
42
72
|
|
|
43
73
|
private
|
|
44
74
|
|
|
75
|
+
# SSR body is the classic renderer's document body: identical to
|
|
76
|
+
# the static HTML output, embedded as the no-JS / first-paint
|
|
77
|
+
# placeholder the SPA replaces on mount.
|
|
78
|
+
def render_ssr_body(guide)
|
|
79
|
+
document = guide.document
|
|
80
|
+
unless document
|
|
81
|
+
raise ArgumentError,
|
|
82
|
+
"InlineFormat requires a Guide carrying its source document"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
renderer = Metanorma::Html::Generator.renderer_for(document).new
|
|
86
|
+
renderer.generate_body(document)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def classic_content_css
|
|
90
|
+
css_dir = Metanorma::Html::AssetPipeline::CSS_DIR
|
|
91
|
+
CONTENT_CSS_MODULES.filter_map do |mod|
|
|
92
|
+
path = File.join(css_dir, "#{mod}.css")
|
|
93
|
+
File.read(path) if File.exist?(path)
|
|
94
|
+
end.join("\n")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def warn_missing_bundle
|
|
98
|
+
return if self.class.missing_bundle_warned
|
|
99
|
+
|
|
100
|
+
warn "metanorma-document: #{iife_bundle_path} not found — " \
|
|
101
|
+
"writing static HTML without the interactive SPA. " \
|
|
102
|
+
"Run `rake build_frontend` to build it."
|
|
103
|
+
self.class.missing_bundle_warned = true
|
|
104
|
+
end
|
|
105
|
+
|
|
45
106
|
def build_style(css)
|
|
46
107
|
Nokogiri::HTML5::Builder.new do |doc|
|
|
47
108
|
doc.style { doc.text css }
|
|
@@ -6,8 +6,6 @@ module Metanorma
|
|
|
6
6
|
autoload :Pipeline, "#{__dir__}/output/pipeline"
|
|
7
7
|
autoload :PipelineContext, "#{__dir__}/output/pipeline_context"
|
|
8
8
|
autoload :Builder, "#{__dir__}/output/builder"
|
|
9
|
-
autoload :HtmlRenderers, "#{__dir__}/output/html_renderers"
|
|
10
|
-
autoload :HtmlRenderer, "#{__dir__}/output/html_renderer"
|
|
11
9
|
autoload :Formats, "#{__dir__}/output/formats"
|
|
12
10
|
end
|
|
13
11
|
end
|
|
@@ -6,7 +6,9 @@ module Metanorma
|
|
|
6
6
|
# per-type customization. Despite living in the reverse-conversion
|
|
7
7
|
# namespace, this class produces a Model graph (not Metanorma XML) —
|
|
8
8
|
# the output is a fully model-driven representation that can be
|
|
9
|
-
# serialized via Model#to_h or
|
|
9
|
+
# serialized via Model#to_h or embedded into HTML output by
|
|
10
|
+
# Output::Formats::InlineFormat (which renders the source document
|
|
11
|
+
# through the classic Metanorma::Html renderer).
|
|
10
12
|
#
|
|
11
13
|
# Instance API:
|
|
12
14
|
# Rewriter.new(skip: Set.new(%w[review footnotes]))
|
|
@@ -44,6 +44,12 @@ module Metanorma
|
|
|
44
44
|
Lutaml::Model::GlobalRegister.register(reg)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def setup_csa_register
|
|
48
|
+
reg = Lutaml::Model::Register.new(:csa_document,
|
|
49
|
+
fallback: [:iso_document])
|
|
50
|
+
Lutaml::Model::GlobalRegister.register(reg)
|
|
51
|
+
end
|
|
52
|
+
|
|
47
53
|
def setup_bsi_register
|
|
48
54
|
iso = Metanorma::IsoDocument
|
|
49
55
|
reg = Lutaml::Model::Register.new(:bsi_document,
|
|
@@ -155,6 +161,10 @@ module Metanorma
|
|
|
155
161
|
from_type: sd::Sections::Preface,
|
|
156
162
|
to_type: Metanorma::UnDocument::Sections::UnPreface,
|
|
157
163
|
)
|
|
164
|
+
reg.register_global_type_substitution(
|
|
165
|
+
from_type: Metanorma::Document::Components::MultiParagraph::AdmonitionBlock,
|
|
166
|
+
to_type: Metanorma::UnDocument::Blocks::UnAdmonitionBlock,
|
|
167
|
+
)
|
|
158
168
|
end
|
|
159
169
|
end
|
|
160
170
|
end
|
|
@@ -10,6 +10,7 @@ module Metanorma
|
|
|
10
10
|
attribute :to, :string
|
|
11
11
|
attribute :type, :string
|
|
12
12
|
attribute :date, :string
|
|
13
|
+
attribute :semx_id, :string
|
|
13
14
|
attribute :paragraphs,
|
|
14
15
|
Metanorma::Document::Components::Paragraphs::ParagraphBlock,
|
|
15
16
|
collection: true
|
|
@@ -22,6 +23,7 @@ module Metanorma
|
|
|
22
23
|
map_attribute "to", to: :to
|
|
23
24
|
map_attribute "type", to: :type
|
|
24
25
|
map_attribute "date", to: :date
|
|
26
|
+
map_attribute "semx-id", to: :semx_id
|
|
25
27
|
map_element "p", to: :paragraphs
|
|
26
28
|
end
|
|
27
29
|
end
|