metanorma-document 0.2.0 → 0.2.1

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.
@@ -67,32 +67,32 @@ module Metanorma
67
67
  end
68
68
  end
69
69
 
70
- def render(node, **opts)
70
+ def render(node, **)
71
71
  case node
72
72
  when Metanorma::IsoDocument::Root
73
- render_document(node, **opts)
73
+ render_document(node, **)
74
74
  when Metanorma::IsoDocument::Sections::IsoPreface
75
- render_preface(node, **opts)
75
+ render_preface(node, **)
76
76
  when Metanorma::IsoDocument::Sections::IsoSections
77
- render_sections(node, **opts)
77
+ render_sections(node, **)
78
78
  when Metanorma::IsoDocument::Sections::IsoClauseSection
79
- render_clause(node, **opts)
79
+ render_clause(node, **)
80
80
  when Metanorma::IsoDocument::Sections::IsoAnnexSection
81
- render_annex(node, **opts)
81
+ render_annex(node, **)
82
82
  when Metanorma::IsoDocument::Sections::IsoTermsSection
83
- render_terms_section(node, **opts)
83
+ render_terms_section(node, **)
84
84
  when Metanorma::IsoDocument::Sections::IsoForewordSection
85
- render_foreword(node, **opts)
85
+ render_foreword(node, **)
86
86
  when Metanorma::IsoDocument::Sections::IsoAbstractSection
87
- render_abstract(node, **opts)
87
+ render_abstract(node, **)
88
88
  when Metanorma::IsoDocument::Terms::IsoTerm
89
- render_term(node, **opts)
89
+ render_term(node, **)
90
90
  when Metanorma::IsoDocument::Terms::TermNote
91
- render_term_note(node, **opts)
91
+ render_term_note(node, **)
92
92
  when Metanorma::IsoDocument::Terms::TermExample
93
- render_term_example(node, **opts)
93
+ render_term_example(node, **)
94
94
  when Metanorma::IsoDocument::Boilerplate
95
- render_boilerplate(node, **opts)
95
+ render_boilerplate(node, **)
96
96
  else
97
97
  super
98
98
  end
@@ -147,33 +147,35 @@ module Metanorma
147
147
 
148
148
  # Extract English stage text, deduplicating duplicate language variants.
149
149
  def extract_stage(bibdata)
150
- return nil unless bibdata.status && bibdata.status.stage
150
+ return nil unless bibdata.status&.stage
151
151
 
152
152
  stages = Array(bibdata.status.stage)
153
153
  return nil if stages.empty?
154
154
 
155
155
  # Prefer English-language stage
156
- en_stage = stages.find { |s|
156
+ en_stage = stages.find do |s|
157
157
  lang = safe_attr(s, :language)
158
158
  lang == "en" if lang
159
- }
160
- return Array(en_stage.value).join.strip if en_stage && en_stage.value
159
+ end
160
+ return Array(en_stage.value).join.strip if en_stage&.value
161
161
 
162
162
  # Fallback: first non-empty, deduplicated
163
163
  seen = Set.new
164
- stage_text = stages.filter_map { |s|
164
+ stage_text = stages.filter_map do |s|
165
165
  val = Array(s.value).join.strip
166
166
  down = val.downcase
167
167
  next if seen.include?(down)
168
+
168
169
  seen << down
169
170
  val.empty? ? nil : val
170
- }.compact.join(" ")
171
+ end.compact.join(" ")
171
172
  stage_text.empty? ? nil : stage_text
172
173
  end
173
174
 
174
175
  # Extract document type from ext.doctype.
175
176
  def extract_doctype(bibdata)
176
177
  return nil unless bibdata.respond_to?(:ext)
178
+
177
179
  ext = bibdata.ext
178
180
  return nil unless ext
179
181
 
@@ -181,11 +183,11 @@ module Metanorma
181
183
  return nil unless doctypes && !doctypes.empty?
182
184
 
183
185
  # Prefer English-language doctype
184
- en_dt = doctypes.find { |d|
186
+ en_dt = doctypes.find do |d|
185
187
  lang = safe_attr(d, :language)
186
188
  lang == "en" if lang
187
- }
188
- return en_dt.value.to_s if en_dt && en_dt.value
189
+ end
190
+ return en_dt.value.to_s if en_dt&.value
189
191
 
190
192
  # Fallback: first doctype
191
193
  dt = doctypes.first
@@ -216,7 +218,7 @@ module Metanorma
216
218
  all_items.each do |node|
217
219
  next if node.is_a?(String)
218
220
  next if is_title_element?(node, doc.sections)
219
- next if is_doc_title_paragraph?(node)
221
+
220
222
  render(node)
221
223
  end
222
224
 
@@ -254,13 +256,13 @@ module Metanorma
254
256
  stage_text = extract_stage(bibdata)
255
257
 
256
258
  @output << render_liquid("_iso_cover.html.liquid", {
257
- "publisher_logos" => logos,
258
- "doc_id" => doc_id,
259
- "pub_date" => pub_date,
260
- "doctype" => doctype,
261
- "title" => title_text,
262
- "stage" => stage_text,
263
- })
259
+ "publisher_logos" => logos,
260
+ "doc_id" => doc_id,
261
+ "pub_date" => pub_date,
262
+ "doctype" => doctype,
263
+ "title" => title_text,
264
+ "stage" => stage_text,
265
+ })
264
266
  end
265
267
 
266
268
  def render_doc_title(doc)
@@ -274,8 +276,8 @@ module Metanorma
274
276
  return unless en_title
275
277
 
276
278
  @output << render_liquid("_iso_doc_title.html.liquid", {
277
- "title" => en_title.to_s,
278
- })
279
+ "title" => en_title.to_s,
280
+ })
279
281
  end
280
282
 
281
283
  def render_boilerplate_section(doc)
@@ -303,7 +305,7 @@ module Metanorma
303
305
  fw_id = safe_attr(fw, :id)
304
306
  title_text = extract_plain_text(title)
305
307
  register_toc_entry(id: fw_id, level: level, text: title_text)
306
- @output << "<h1 class=\"ForewordTitle\">"
308
+ @output << "<h1 class=\"foreword-title\">"
307
309
  render_mixed_inline(title)
308
310
  @output << "</h1>"
309
311
  end
@@ -319,7 +321,7 @@ module Metanorma
319
321
  sec_id = safe_attr(section, :id)
320
322
  title_text = extract_plain_text(title)
321
323
  register_toc_entry(id: sec_id, level: level, text: title_text)
322
- @output << "<h1 class=\"IntroTitle\">"
324
+ @output << "<h1 class=\"intro-title\">"
323
325
  render_mixed_inline(title)
324
326
  @output << "</h1>"
325
327
  end
@@ -344,7 +346,7 @@ module Metanorma
344
346
  # --- Clause rendering ---
345
347
 
346
348
  def render_clause(clause, level: 1, **_opts)
347
- attrs = element_attrs(id: safe_attr(clause, :id), class: safe_attr(clause, :class_attr))
349
+ attrs = element_attrs(id: safe_attr(clause, :id))
348
350
  tag("div", attrs) do
349
351
  render_title(clause, level)
350
352
  render_ordered_content(clause, level)
@@ -354,7 +356,7 @@ module Metanorma
354
356
  # --- Annex rendering ---
355
357
 
356
358
  def render_annex(annex, level: 1, **_opts)
357
- attrs = element_attrs(id: safe_attr(annex, :id), class: "Section3")
359
+ attrs = element_attrs(id: safe_attr(annex, :id), class: "section-sub")
358
360
  tag("div", attrs) do
359
361
  render_annex_title(annex, level)
360
362
  render_ordered_content(annex, level)
@@ -370,7 +372,7 @@ module Metanorma
370
372
  register_toc_entry(id: annex_id, level: level, text: title_text)
371
373
 
372
374
  h = "h#{[[level, 6].min, 1].max}"
373
- @output << "<#{h} class=\"Annex\">"
375
+ @output << "<#{h} class=\"annex-title\">"
374
376
  render_mixed_inline(title_element)
375
377
  @output << "</#{h}>"
376
378
  end
@@ -398,7 +400,7 @@ module Metanorma
398
400
  # In presentation mode, use fmt_* elements
399
401
  if term.fmt_name
400
402
  # Render term number (e.g. "3.1")
401
- @output << "<p class=\"TermNum\">"
403
+ @output << "<p class=\"term-number\">"
402
404
  render_inline_element(term.fmt_name)
403
405
  @output << "</p>"
404
406
  elsif term.term_number
@@ -408,7 +410,7 @@ module Metanorma
408
410
  else
409
411
  extract_text_value(tn)
410
412
  end
411
- @output << "<p class=\"TermNum\">#{escape_html(tn_text)}</p>"
413
+ @output << "<p class=\"term-number\">#{escape_html(tn_text)}</p>"
412
414
  end
413
415
 
414
416
  # Preferred designations — use fmt-preferred if available
@@ -436,7 +438,7 @@ module Metanorma
436
438
  # (fmt-definition already includes domain text in its content)
437
439
  if term.domain && !term.fmt_definition
438
440
  domain_text = safe_attr(term.domain, :text)
439
- @output << "<p class=\"domain\">&lt;#{escape_html(domain_text)}&gt;</p>" if domain_text
441
+ @output << "<p class=\"term-domain\">&lt;#{escape_html(domain_text)}&gt;</p>" if domain_text
440
442
  end
441
443
 
442
444
  # Definition — use fmt-definition if available
@@ -458,7 +460,7 @@ module Metanorma
458
460
  # Source references — use fmt-termsource if available
459
461
  if term.fmt_termsource && !term.fmt_termsource.empty?
460
462
  term.fmt_termsource.each do |fts|
461
- @output << "<p class=\"source\">"
463
+ @output << "<p class=\"term-source\">"
462
464
  render_mixed_inline(fts)
463
465
  @output << "</p>"
464
466
  end
@@ -485,7 +487,8 @@ module Metanorma
485
487
  if term.preferred && !term.preferred.empty?
486
488
  return extract_designation_name(term.preferred.first).to_s
487
489
  end
488
- safe_attr(term, :id).to_s.sub(/\Aterm-/, "")
490
+
491
+ safe_attr(term, :id).to_s.delete_prefix("term-")
489
492
  end
490
493
 
491
494
  def extract_term_definition(term)
@@ -502,11 +505,11 @@ module Metanorma
502
505
 
503
506
  def strip_html(html)
504
507
  html.gsub(/<[^>]+>/, "").gsub("&lt;", "<").gsub("&gt;", ">")
505
- .gsub("&amp;", "&").gsub("&nbsp;", " ")
508
+ .gsub("&amp;", "&").gsub("&nbsp;", " ")
506
509
  end
507
510
 
508
511
  def render_term_designation(designation, type)
509
- css_class = type == "deprecated" ? "DeprecatedTerms" : "Terms"
512
+ css_class = type == "deprecated" ? "term-deprecated" : "term-name"
510
513
  @output << "<p class=\"#{css_class}\" style=\"text-align:left;\">"
511
514
  @output << "<del>" if type == "deprecated"
512
515
  @output << "<b><dfn>"
@@ -583,10 +586,10 @@ module Metanorma
583
586
  end
584
587
 
585
588
  def render_term_note(note)
586
- attrs = element_attrs(id: safe_attr(note, :id), class: "Note")
589
+ attrs = element_attrs(id: safe_attr(note, :id), class: "note-block")
587
590
  tag("div", attrs) do
588
591
  label = extract_termnote_label(note)
589
- @output << "<p><span class=\"termnote_label\">#{escape_html(label)}: </span>"
592
+ @output << "<p><span class=\"term-note-label\">#{escape_html(label)}: </span>"
590
593
  note.p&.each { |para| render_mixed_inline(para) }
591
594
  @output << "</p>"
592
595
  note.ul&.each { |ul| render_unordered_list(ul) }
@@ -599,7 +602,7 @@ module Metanorma
599
602
  attrs = element_attrs(id: safe_attr(example, :id), class: "example")
600
603
  tag("div", attrs) do
601
604
  label = extract_block_label(example, "EXAMPLE")
602
- @output << "<p><span class=\"example_label\">#{escape_html(label)}</span>&nbsp;"
605
+ @output << "<p><span class=\"example-label\">#{escape_html(label)}</span>&nbsp;"
603
606
  example.p&.each { |para| render_mixed_inline(para) }
604
607
  @output << "</p>"
605
608
  example.ul&.each { |ul| render_unordered_list(ul) }
@@ -627,7 +630,13 @@ module Metanorma
627
630
  .gsub(/<variant-title[^>]*>.*?<\/variant-title>/m, "")
628
631
  .gsub(/<\/?(?:copyright-statement|clause)[^>]*>/, "")
629
632
 
630
- @output << clean.strip
633
+ # Remap XML class names to HTML-specific class names
634
+ boilerplate_doc = Nokogiri::HTML::DocumentFragment.parse(clean)
635
+ boilerplate_doc.css("[class]").each do |el|
636
+ el["class"] = el["class"].split(/\s+/).map { |c| html_class_for_span(c) }.join(" ")
637
+ end
638
+
639
+ @output << boilerplate_doc.inner_html.strip
631
640
 
632
641
  @output << "</div>"
633
642
  end
@@ -641,19 +650,19 @@ module Metanorma
641
650
  next_sib = next_sib.next_sibling
642
651
  end
643
652
 
644
- display_text = if next_sib && next_sib.element? && next_sib.name == "semx"
645
- fmt_link = next_sib.at_css("fmt-link")
646
- if fmt_link
647
- fmt_target = fmt_link["target"] || fmt_link["href"] || target
648
- display_text = fmt_target.to_s.sub(/\Amailto:/, "")
649
- next_sib.remove
650
- display_text
651
- end
652
- end
653
-
654
- display_text ||= target.to_s.sub(/\Amailto:/, "")
653
+ display_text = if next_sib&.element? && next_sib.name == "semx"
654
+ fmt_link = next_sib.at_css("fmt-link")
655
+ if fmt_link
656
+ fmt_target = fmt_link["target"] || fmt_link["href"] || target
657
+ display_text = fmt_target.to_s.delete_prefix("mailto:")
658
+ next_sib.remove
659
+ display_text
660
+ end
661
+ end
662
+
663
+ display_text ||= target.to_s.delete_prefix("mailto:")
655
664
  a_tag = Nokogiri::HTML::DocumentFragment.parse(
656
- "<a href=\"#{CGI.escapeHTML(target.to_s)}\">#{CGI.escapeHTML(display_text)}</a>"
665
+ "<a href=\"#{CGI.escapeHTML(target.to_s)}\">#{CGI.escapeHTML(display_text)}</a>",
657
666
  )
658
667
  link.replace(a_tag)
659
668
  end
@@ -686,15 +695,20 @@ module Metanorma
686
695
  %i[terms definitions].each do |attr|
687
696
  val = safe_attr(section, attr)
688
697
  next if val.nil?
698
+
689
699
  Array(val).each do |v|
690
700
  children << v unless children.include?(v)
691
701
  end
692
702
  end
693
703
 
694
704
  # Sort by displayorder (non-nil first, then nil at end)
695
- children.reject!(&:nil?)
705
+ children.compact!
696
706
  children.sort_by do |node|
697
- order = node.displayorder rescue nil
707
+ order = begin
708
+ node.displayorder
709
+ rescue StandardError
710
+ nil
711
+ end
698
712
  order &&= order.to_i
699
713
  order || Float::INFINITY
700
714
  end
@@ -710,46 +724,49 @@ module Metanorma
710
724
  end
711
725
  end
712
726
 
713
- private
714
-
715
- # Filter document title paragraphs that are rendered by render_doc_title
716
- def is_doc_title_paragraph?(node)
717
- return false unless node.respond_to?(:class_attr)
718
- ["zzSTDTitle1", "zzSTDTitle2"].include?(node.class_attr)
719
- end
720
-
721
727
  # Collect all document-level children (sections, normative refs, annexes,
722
728
  # bibliography) sorted by displayorder for correct document order.
729
+ # Top-level paragraphs in sections (title paragraphs) are excluded —
730
+ # they are rendered separately by render_doc_title.
723
731
  def collect_document_children(doc)
724
732
  items = []
725
733
 
726
734
  # Main sections children (clauses, terms, etc.)
727
735
  if doc.sections
728
- items.concat(gather_element_order_children(doc.sections))
736
+ section_children = gather_element_order_children(doc.sections)
737
+ # Title paragraphs are ParagraphBlock objects at the top level of
738
+ # sections. They are rendered by render_doc_title, so skip them here.
739
+ section_children.reject! do |node|
740
+ node.is_a?(Metanorma::Document::Components::Paragraphs::ParagraphBlock)
741
+ end
742
+ items.concat(section_children)
729
743
  # Also add typed attributes that may not be in element_order
730
744
  %i[terms definitions].each do |attr|
731
745
  val = safe_attr(doc.sections, attr)
732
746
  next if val.nil?
747
+
733
748
  Array(val).each { |v| items << v unless items.include?(v) }
734
749
  end
735
750
  end
736
751
 
737
752
  # Normative references from bibliography (may have displayorder)
738
- if doc.bibliography && doc.bibliography.references
739
- doc.bibliography.references.each { |r| items << r }
740
- end
753
+ doc.bibliography&.references&.each { |r| items << r }
741
754
 
742
755
  # Annexes
743
756
  doc.annex&.each { |a| items << a }
744
757
 
745
758
  # Non-normative bibliography (no displayorder = goes at end)
746
- if doc.bibliography && doc.bibliography.references
759
+ if doc.bibliography&.references
747
760
  # Already included above; filter normative vs non-normative below
748
761
  end
749
762
 
750
763
  items.compact!
751
764
  items.sort_by do |node|
752
- order = node.displayorder rescue nil
765
+ order = begin
766
+ node.displayorder
767
+ rescue StandardError
768
+ nil
769
+ end
753
770
  order &&= order.to_i
754
771
  order || Float::INFINITY
755
772
  end
@@ -797,7 +814,7 @@ module Metanorma
797
814
  children
798
815
  end
799
816
 
800
- def publisher_logos_html(doc)
817
+ def publisher_logos_html(_doc)
801
818
  publishers = flavor_publishers(extract_primary_doc_id)
802
819
  logo_map = publisher_logo_map
803
820
  return [] if publishers.empty? && logo_map.empty?
@@ -811,8 +828,8 @@ module Metanorma
811
828
  next unless svg
812
829
 
813
830
  # White fill for dark cover background
814
- svg = svg.gsub(/fill:#00b1ff/, "fill:white") if pub == "OGC"
815
- svg = svg.gsub(/fill:#e3000f/, "fill:white") if pub == "ISO"
831
+ svg = svg.gsub("fill:#00b1ff", "fill:white") if pub == "OGC"
832
+ svg = svg.gsub("fill:#e3000f", "fill:white") if pub == "ISO"
816
833
  svg
817
834
  end
818
835
  end
@@ -46,7 +46,7 @@ module Metanorma
46
46
  t.example_bg = "#e8f4fa"
47
47
  t.example_color = "#004d73"
48
48
  t.admonition_border = "#e8812e"
49
- t.admonition_bg = "#fff5eb"
49
+ t.admonition_bg = "#fff5eb"
50
50
  t.admonition_color = "#c06a1a"
51
51
  t.footer_border_color = "#00b1ff"
52
52
  t.cover_separator_color = "rgba(0,177,255,0.25)"
@@ -69,13 +69,13 @@ module Metanorma
69
69
  preface_clauses = preface.clause&.reject { |cl| cl.type == "toc" } || []
70
70
 
71
71
  return if preface_clauses.empty? &&
72
- !preface.foreword && !preface.introduction &&
73
- !preface.abstract && !preface.acknowledgements &&
74
- !preface.executivesummary
72
+ !preface.foreword && !preface.introduction &&
73
+ !preface.abstract && !preface.acknowledgements &&
74
+ !preface.executivesummary
75
75
 
76
76
  @output << "<div id=\"preface\" class=\"preface-section\">"
77
77
  register_toc_entry(id: "preface", level: 1, text: "Preface")
78
- @output << "<h1 class=\"ForewordTitle\">Preface</h1>"
78
+ @output << "<h1 class=\"foreword-title\">Preface</h1>"
79
79
 
80
80
  preface_clauses.each { |cl| render(cl, level: 2) }
81
81
 
@@ -5,34 +5,34 @@ module Metanorma
5
5
  # Renders StandardDocument components to HTML.
6
6
  # Extends BaseRenderer with terms, bibliography, and standard sections.
7
7
  class StandardRenderer < BaseRenderer
8
- def render(node, **opts)
8
+ def render(node, **)
9
9
  case node
10
10
  when Metanorma::StandardDocument::Root
11
- render_standard_document(node, **opts)
11
+ render_standard_document(node, **)
12
12
  when Metanorma::StandardDocument::Terms::Term
13
- render_term(node, **opts)
13
+ render_term(node, **)
14
14
  when Metanorma::StandardDocument::Sections::TermsSection
15
- render_terms_section(node, **opts)
15
+ render_terms_section(node, **)
16
16
  when Metanorma::StandardDocument::Sections::StandardReferencesSection
17
- render_references_section(node, **opts)
17
+ render_references_section(node, **)
18
18
  when Metanorma::StandardDocument::Sections::BibliographySection
19
- render_bibliography(node, **opts)
19
+ render_bibliography(node, **)
20
20
  when Metanorma::StandardDocument::Sections::ClauseSection
21
- render_clause_section(node, **opts)
21
+ render_clause_section(node, **)
22
22
  when Metanorma::StandardDocument::Sections::AnnexSection
23
- render_annex_section(node, **opts)
23
+ render_annex_section(node, **)
24
24
  when Metanorma::StandardDocument::Sections::StandardSection
25
- render_standard_section(node, **opts)
25
+ render_standard_section(node, **)
26
26
  when Metanorma::StandardDocument::Sections::Abstract
27
- render_abstract_section(node, **opts)
27
+ render_abstract_section(node, **)
28
28
  when Metanorma::StandardDocument::Sections::Foreword
29
- render_foreword_section(node, **opts)
29
+ render_foreword_section(node, **)
30
30
  when Metanorma::StandardDocument::Sections::Introduction
31
- render_introduction_section(node, **opts)
31
+ render_introduction_section(node, **)
32
32
  when Metanorma::StandardDocument::Sections::FloatingTitle
33
- render_floating_title(node, **opts)
33
+ render_floating_title(node, **)
34
34
  when Metanorma::StandardDocument::Blocks::AmendBlock
35
- render_amend_block(node, **opts)
35
+ render_amend_block(node, **)
36
36
  else
37
37
  super
38
38
  end
@@ -86,8 +86,10 @@ module Metanorma
86
86
  cover_id = nil
87
87
  bibdata.doc_identifier&.each do |di|
88
88
  next unless safe_attr(di, :type) == "iso-reference"
89
+
89
90
  id = extract_text_value(di)
90
91
  next if id.to_s.empty?
92
+
91
93
  cover_id = id
92
94
  break
93
95
  end
@@ -105,9 +107,9 @@ module Metanorma
105
107
  end
106
108
 
107
109
  @output << render_liquid("_cover.html.liquid", {
108
- "doc_id" => cover_id,
109
- "title" => title_text,
110
- })
110
+ "doc_id" => cover_id,
111
+ "title" => title_text,
112
+ })
111
113
  end
112
114
 
113
115
  def render_doc_title(doc)
@@ -120,22 +122,24 @@ module Metanorma
120
122
  elsif bibdata.is_a?(Metanorma::Document::Components::BibData::BibData)
121
123
  titles = bibdata.title
122
124
  return unless titles && !titles.empty?
125
+
123
126
  en_title = titles.find { |t| t.language == "en" }
124
127
  return unless en_title
128
+
125
129
  en_title = extract_text_value(en_title)
126
130
  else
127
131
  return
128
132
  end
129
133
 
130
134
  @output << render_liquid("_doc_title.html.liquid", {
131
- "title" => en_title,
132
- })
135
+ "title" => en_title,
136
+ })
133
137
  end
134
138
 
135
139
  # --- Section rendering ---
136
140
 
137
141
  def render_clause_section(clause, level: 1, **_opts)
138
- attrs = element_attrs(id: safe_attr(clause, :id), class: safe_attr(clause, :class_attr))
142
+ attrs = element_attrs(id: safe_attr(clause, :id))
139
143
  tag("div", attrs) do
140
144
  render_standard_title(clause, level)
141
145
  render_standard_section_blocks(clause, level)
@@ -324,11 +328,11 @@ module Metanorma
324
328
  bibitemid = safe_attr(origin, :bibitemid)
325
329
 
326
330
  if citeas && !citeas.to_s.empty?
327
- if bibitemid && !bibitemid.to_s.empty?
328
- @output << "<a href=\"##{escape_html(bibitemid.to_s)}\" class=\"bibref\">#{escape_html(citeas.to_s)}</a>"
329
- else
330
- @output << escape_html(citeas.to_s)
331
- end
331
+ @output << if bibitemid && !bibitemid.to_s.empty?
332
+ "<a href=\"##{escape_html(bibitemid.to_s)}\" class=\"bibref\">#{escape_html(citeas.to_s)}</a>"
333
+ else
334
+ escape_html(citeas.to_s)
335
+ end
332
336
  else
333
337
  render_mixed_inline(origin)
334
338
  end
@@ -401,9 +405,11 @@ module Metanorma
401
405
  def bibitem_url(item)
402
406
  links = Array(item.link)
403
407
  return nil if links.empty?
408
+
404
409
  # Prefer src or citation type, skip RSS feeds
405
- preferred = links.find { |l| l.type == "src" || l.type == "citation" }
410
+ preferred = links.find { |l| ["src", "citation"].include?(l.type) }
406
411
  return preferred.content.to_s if preferred && !preferred.content.to_s.empty?
412
+
407
413
  # Fallback: first non-RSS link
408
414
  non_rss = links.find { |l| !l.content.to_s.include?(".rss") && !l.content.to_s.empty? }
409
415
  non_rss&.content&.to_s
@@ -421,10 +427,10 @@ module Metanorma
421
427
  docids = Array(item.docidentifier)
422
428
  # Skip bracket-number identifiers (e.g. "[1]") and iso-reference/URN variants;
423
429
  # render only the primary doc identifier
424
- primary = docids.find { |di|
430
+ primary = docids.find do |di|
425
431
  val = extract_text_value(di).to_s
426
432
  val.match?(/\A\[?\d+\]?\z/) ? false : !val.match?(/\A(?:iso-reference|URN)\s/)
427
- }
433
+ end
428
434
  if primary
429
435
  id_val = extract_text_value(primary)
430
436
  @output << "<span class=\"std-doc-number\">#{escape_html(id_val)}</span>" unless id_val.to_s.empty?
@@ -0,0 +1,4 @@
1
+ <div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ <p class="admonition-title">{{ block.label_html }}</p>
3
+ {{ block.content_html }}
4
+ </div>
@@ -1,3 +1,3 @@
1
1
  <p class="doc-title">
2
- <span class="bold-title">{{ title | escape }}</span>
2
+ <span class="title-text">{{ title | escape }}</span>
3
3
  </p>
@@ -0,0 +1,3 @@
1
+ <div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ <span class="example-label">{{ block.label_html }}</span>&nbsp;{{ block.content_html }}
3
+ </div>
@@ -0,0 +1,6 @@
1
+ <figure{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ {{ block.image_html }}
3
+ {{ block.sub_figures_html }}
4
+ {% if block.caption_html %}<figcaption>{{ block.caption_html }}</figcaption>{% endif %}
5
+ {{ block.key_html }}
6
+ </figure>
@@ -0,0 +1,6 @@
1
+ <div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ {{ block.stem_html }}
3
+ {% if block.where_html %}<p class="formula-where">where</p>{% endif %}
4
+ {{ block.where_html }}
5
+ {% if block.number_html %}<span class="formula-number">{{ block.number_html }}</span>{% endif %}
6
+ </div>
@@ -1,3 +1,3 @@
1
- <p class="zzSTDTitle1">
2
- <span class="boldtitle">{{ title | escape }}</span>
1
+ <p class="doc-title">
2
+ <span class="title-text">{{ title | escape }}</span>
3
3
  </p>
@@ -0,0 +1,3 @@
1
+ <div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ <span class="note-label">{{ block.label_html }}</span>&nbsp;{{ block.content_html }}
3
+ </div>
@@ -0,0 +1,4 @@
1
+ <div{% if block.id %} id="{{ block.id }}"{% endif %} class="{{ block.css_class }}">
2
+ {% if block.name_html %}<p class="code-name">{{ block.name_html }}</p>{% endif %}
3
+ <pre><code{% if block.lang %} lang="{{ block.lang }}"{% endif %}>{{ block.code_html }}</code></pre>
4
+ </div>