Class: IsoDoc::PresentationXMLConvert

Inherits:
Convert show all
Defined in:
lib/isodoc/presentation_xml_convert.rb,
lib/isodoc/presentation_function/ids.rb,
lib/isodoc/presentation_function/list.rb,
lib/isodoc/presentation_function/math.rb,
lib/isodoc/presentation_function/refs.rb,
lib/isodoc/presentation_function/reqt.rb,
lib/isodoc/presentation_function/annex.rb,
lib/isodoc/presentation_function/block.rb,
lib/isodoc/presentation_function/docid.rb,
lib/isodoc/presentation_function/erefs.rb,
lib/isodoc/presentation_function/image.rb,
lib/isodoc/presentation_function/index.rb,
lib/isodoc/presentation_function/terms.rb,
lib/isodoc/presentation_function/title.rb,
lib/isodoc/presentation_function/xrefs.rb,
lib/isodoc/presentation_function/inline.rb,
lib/isodoc/presentation_function/source.rb,
lib/isodoc/presentation_function/autonum.rb,
lib/isodoc/presentation_function/bibdata.rb,
lib/isodoc/presentation_function/cleanup.rb,
lib/isodoc/presentation_function/section.rb,
lib/isodoc/presentation_function/concepts.rb,
lib/isodoc/presentation_function/metadata.rb,
lib/isodoc/presentation_function/footnotes.rb,
lib/isodoc/presentation_function/sourcecode.rb,
lib/isodoc/presentation_function/designations.rb,
lib/isodoc/presentation_function/section_refs.rb,
lib/isodoc/presentation_function/list_to_table.rb,
lib/isodoc/presentation_function/erefs_locality.rb

Constant Summary collapse

MATHML =
{ "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
SERIAL_NUM_DOCID =

DOI, ISSN, ISBN cover term

<<~XPATH.strip.freeze
  @type = 'DOI' or @type = 'doi' or @type = 'ISSN' or @type = 'issn' or @type = 'ISBN' or @type = 'isbn' or starts-with(@type, 'ISSN.') or starts-with(@type, 'ISBN.') or starts-with(@type, 'issn.') or starts-with(@type, 'isbn.')
XPATH
REQS =
%w(requirement recommendation permission).freeze
XREF_CONNECTIVES =
%w(from to or and).freeze
SVG =
{ "m" => "http://www.w3.org/2000/svg" }.freeze
DESIGNATION_ELEMS =
%w(preferred admitted deprecates related definition source).freeze
AVOID_COMMENT_BOOKMARKS =

Do not insert a comment bookmark inside another comment bookmark Also avoid list labels, which are typically not rendered downstream as selectable text

<<~XPATH.freeze
  [not(ancestor::xmlns:fmt-annotation-start)][not(ancestor::xmlns:fmt-annotation-end)][not(ancestor::xmlns:fmt-name[parent::xmlns:li])]
XPATH

Constants inherited from Convert

Convert::AGENCIES

Constants included from Function::Utils

Function::Utils::CLAUSE_ANCESTOR, Function::Utils::COMMA_PLACEHOLDER, Function::Utils::DOCTYPE_HDR, Function::Utils::HUGESTRICT, Function::Utils::LABELLED_ANCESTOR_ELEMENTS, Function::Utils::NOTE_CONTAINER_ANCESTOR

Constants included from Function::ToWordHtml

Function::ToWordHtml::TOP_ELEMENTS

Constants included from Function::Table

Function::Table::SW

Constants included from Function::Section

Function::Section::TERM_CLAUSE

Constants included from Function::Lists

Function::Lists::OL_STYLE

Constants included from Function::Inline

Function::Inline::SPAN_UNWRAP_CLASSES

Constants included from Function::Cleanup

Function::Cleanup::TABLENOTE_CSS

Constants included from Function::Blocks

Function::Blocks::EXAMPLE_TBL_ATTR, Function::Blocks::EXAMPLE_TD_ATTR

Instance Attribute Summary

Attributes inherited from Convert

#bibrender, #doctype, #i18n, #localdir, #meta, #options, #reqt_models, #requirements_processor, #tempfile_cache, #wordcoverpage, #wordintropage, #xrefs

Instance Method Summary collapse

Methods inherited from Convert

#agency?, #bibrenderer, #compile_scss, #connectives_spans, #convert, #convert1_namespaces, #convert_i18n_init, #convert_i18n_init1, #convert_init, #convert_scss, #convert_xref_init, #default_file_locations, #default_fonts, #docid_all_parts, #docid_l10n, #docid_prefix, #doctype_init, #docxml_var_init, #fonts_options, #generate_css, #html_doc_path, #i18n_init, #init_arrangement, #init_covers, #init_fonts, #init_i18n, #init_locations, #init_processing, #init_rendering, #init_stylesheets, #init_toc, #l10n, #localpath, #log_messages, #metadata_init, #middle_clause, #omit_docid_prefix, #options_preprocess, #populate_css, #precompiled_style_or_original, #preprocess_css, #presentation_xml_converter, #scss_fontheader, #scss_load_paths, #swap_renderer, #target_pdf, #tmpfilesdir_suffix, #tmpimagedir_suffix, #toc_init, #write_css, #xref_init

Methods included from ClassUtils

#case_strict, #case_strict1, #case_with_markup, #date_range, #liquid, #nearest_block_parent, #ns, #start_of_sentence, #to_xml

Methods included from Function::Utils

#attr_code, #cleanup_entities, #comma_placeholder, #csv_attribute_extract, #date_range, #emf?, #empty2nil, #eps?, #external_path, #extract_delims, #from_xhtml, #get_clause_id, #get_note_container_id, #header_strip, #header_strip_elem?, #image_localfile, #imgfile_suffix, #insert_tab, #labelled_ancestor, #liquid, #noko, #ns, #numeric_escapes, #populate_template, #save_dataimage, #save_svg, #sentence_join, #start_of_sentence, #to_xhtml, #to_xhtml_fragment, #to_xhtml_prep, #to_xml, #unescape_amp_in_hrefs

Methods included from Function::ToWordHtml

#body_attr, #boilerplate, #content, #cross_align, #define_head, #info, #init_dir, #init_file, #make_body, #make_body1, #make_body2, #make_body3, #note?, #parse, #rel_tmpimagedir, #tmpimagedir, #top_element_render

Methods included from Function::Terms

#admitted_term_parse, #definition_parse, #deprecated_term_parse, #modification_parse, #related_parse, #semx_admitted_term_parse, #semx_deprecated_term_parse, #semx_related_parse, #semx_term_parse, #semx_termref_parse, #term_p_parse, #term_parse, #termdef_parse, #termdocsource_parse, #termdomain_parse, #termnote_p_class, #termnote_parse, #termnote_parse1, #termref_parse

Methods included from Function::Table

#bordered_table_style, #colgroup, #make_tr_attr, #make_tr_attr_style, #table_attrs, #table_attrs_style, #table_bordered?, #table_parse, #table_parse_core, #table_parse_tail, #table_title_parse, #tbody_parse, #tfoot_parse, #thead_parse, #tr_parse

Methods included from Function::Section

#abstract, #acknowledgements, #annex_attrs, #annex_name, #appendix_parse, #clause?, #clause_attrs, #clause_name, #clause_parse, #clause_parse_subtitle, #clause_parse_title, #clause_parse_title1, #clause_title_depth, #clausedelimspace, #colophon, #copyright_parse, #executivesummary, #feedback_parse, #footnotes, #foreword, #freestanding_title, #indexsect, #inline_header_title, #introduction, #legal_parse, #license_parse, #preface, #preface_attrs, #preface_block, #preface_normal, #scope, #sections_names, #single_term_clause?, #symbols_abbrevs, #symbols_parse, #table_of_contents, #terms_defs, #terms_parse, #variant_title

Methods included from Function::References

#bibitem_entry, #biblio_list, #bibliography, #bibliography_parse, #bibliography_xpath, #iso_bibitem_entry_attrs, #norm_ref, #norm_ref_xpath, #reference_format

Methods included from Function::Lists

#dl_attrs, #dl_parse, #dl_parse1, #dl_parse_notes, #dt_dd?, #dt_parse, #fmt_ul_parse, #li_checkbox, #li_parse, #list_title_parse, #ol_attrs, #ol_parse, #ol_style, #ul_attrs, #ul_parse

Methods included from Function::Footnotes

#fmt_annotation_body_parse, #footnote_parse, #get_table_ancestor_id, #make_table_footnote_link, #table_footnote?, #table_footnote_parse, #update_table_fn_body_ref

Methods included from Function::Inline

#add_parse, #amend_parse, #annotation_note_parse, #asciimath_parse, #author_parse, #bookmark_parse, #br_parse, #callout_parse, #children_parse, #concept_parse, #date_parse, #del_parse, #em_parse, #eref_parse, #erefstack_parse, #error_parse, #floating_title_parse, #fmt_annotation_end_parse, #fmt_annotation_start_parse, #fmt_concept_parse, #fmt_date_parse, #fmt_fn_label_parse, #fmt_footnote_container_parse, #fmt_identifier_parse, #fmt_name_parse, #hr_parse, #identifier_parse, #image_attrs, #image_body_parse, #image_parse, #index_parse, #index_xref_parse, #keyword_parse, #latexmath_parse, #link_parse, #link_parse_url, #location_parse, #mathml_parse, #name_parse, #no_locality_parse, #origin_parse, #page_break, #pagebreak_parse, #rb_parse, #rt_parse, #ruby_parse, #section_break, #select_altsource, #select_altsource?, #semx_definition_parse, #semx_eref_parse, #semx_link_parse, #semx_origin_parse, #semx_parse, #semx_source_parse, #semx_sourcecode_parse, #semx_stem_parse, #semx_xref_parse, #smallcap_parse, #span_parse, #stem_parse, #stem_parse1, #strike_parse, #strong_parse, #sub_parse, #sup_parse, #svgmap_parse, #termrefelem_parse, #text_parse, #tt_parse, #underline_parse, #xref_label_parse, #xref_parse

Methods included from Function::Form

#form_parse, #input_parse, #label_parse, #option_parse, #select_parse, #text_input, #textarea_parse

Methods included from Function::Cleanup

#admonition_cleanup, #empty_tags, #example_cleanup, #figure_cleanup, #inline_header_cleanup, #merge_fnref_into_fn_text, #new_fullcolspan_row, #passthrough_cleanup, #remove_bottom_border, #symbols_cleanup, #table_cleanup, #table_footnote_cleanup, #table_footnote_cleanup_propagate, #table_get_or_make_tfoot, #table_note_cleanup, #textcleanup

Methods included from Function::Blocks

#admonition_attrs, #admonition_class, #admonition_name, #admonition_name_in_first_para, #admonition_name_para_delim, #admonition_name_parse, #admonition_p_parse, #admonition_parse, #admonition_parse1, #admonition_subclass, #annotation_parse, #attribution_parse, #block_body_first_elem, #columnbreak_parse, #cross_align_parse, #div_parse, #example_div_attr, #example_div_parse, #example_label, #example_parse, #example_table_attr, #example_table_parse, #figure_attrs, #figure_name_parse, #figure_parse, #figure_parse1, #fmt_fn_body_parse, #formula_attrs, #formula_parse, #formula_parse1, #keep_style, #key_name_parse, #key_parse, #note_attrs, #note_p_class, #note_p_parse, #note_parse, #note_parse1, #para_attrs, #para_class, #para_parse, #para_prefix, #passthrough_parse, #permission_parse, #pre_parse, #pseudocode_attrs, #pseudocode_parse, #pseudocode_tag, #quote_attrs, #quote_parse, #recommendation_name, #recommendation_parse, #recommendation_parse1, #reqt_attrs, #requirement_parse, #source_parse, #sourcecode_attrs, #sourcecode_name_parse, #sourcecode_parse, #sourcecode_parse1, #starts_with_para?, #svg_parse, #toc_parse

Constructor Details

#initialize(options) ⇒ PresentationXMLConvert

Returns a new instance of PresentationXMLConvert.



28
29
30
31
32
33
# File 'lib/isodoc/presentation_xml_convert.rb', line 28

def initialize(options)
  @format = :presentation
  @suffix = "presentation.xml"
  @new_ids = {} # guids assigned within Presentation XML
  super
end

Instance Method Details

#add_fnbody?(fnote, seen) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/isodoc/presentation_function/footnotes.rb', line 36

def add_fnbody?(fnote, seen)
  !seen[fnote["reference"]]
end

#add_id(elem) ⇒ Object



9
10
11
12
13
14
# File 'lib/isodoc/presentation_function/ids.rb', line 9

def add_id(elem)
  elem["id"] and return
  id = "_#{UUIDTools::UUID.random_create}"
  elem["id"] = id
  @new_ids[id] = nil
end

#add_id_textObject



3
4
5
6
7
# File 'lib/isodoc/presentation_function/ids.rb', line 3

def add_id_text
  id = "_#{UUIDTools::UUID.random_create}"
  @new_ids[id] = nil
  %(id="#{id}")
end

#add_id_to_display_bib_notes(bib) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/isodoc/presentation_function/refs.rb', line 34

def add_id_to_display_bib_notes(bib)
  bib.xpath(ns("./note")).each do |n|
    t = n["type"] or next
    t.split(",").map(&:strip).include?("display") or next
    add_id(n)
  end
end

#add_missing_id(docxml) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/isodoc/presentation_function/ids.rb', line 97

def add_missing_id(docxml)
  docxml.xpath(ns("//source | //modification | //erefstack | //fn | " \
    "//annotation | //floating-title | //li | //executivesummary | " \
    "//preface/abstract | //foreword | //introduction | //annex | " \
    "//acknowledgements | //clause | //references | //terms | " \
    "//preferred | //deprecates | //admitted | //related | " \
    "//expression/name | //letter-symbol/name | //graphical-symbol"))
    .each do |s|
    add_id(s)
  end
end

#add_missing_presxml_id(docxml) ⇒ Object



24
25
26
27
28
29
# File 'lib/isodoc/presentation_function/ids.rb', line 24

def add_missing_presxml_id(docxml)
  docxml.xpath(ns("//fmt-name | //fmt-title | //fmt-definition | " \
    "//fmt-sourcecode | //fmt-provision")).each do |x|
    add_id(x)
  end
end

#add_new_contenthash_id(docxml, ids) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/isodoc/presentation_function/ids.rb', line 120

def add_new_contenthash_id(docxml, ids)
  suffix = "" # for disambiguation in Metanorma Collections
  docxml["document_suffix"] and suffix = "_#{docxml['document_suffix']}"
  %w(original-id id).each do |k|
    docxml.xpath("//*[@#{k}]").each do |x|
      ids.has_key?(x[k]) or next
      new_id = Metanorma::Utils::contenthash(x) + suffix
      ids[x[k]] = new_id
      x[k] = new_id
    end
  end
end

#address_precompose(bib) ⇒ Object



13
14
15
16
17
18
19
20
# File 'lib/isodoc/presentation_function/bibdata.rb', line 13

def address_precompose(bib)
  bib.xpath(ns("//bibdata//address")).each do |b|
    next if b.at(ns("./formattedAddress"))

    x = address_precompose1(b)
    b.children = "<formattedAddress>#{x}</formattedAddress>"
  end
end

#address_precompose1(addr) ⇒ Object



22
23
24
25
26
27
28
29
30
# File 'lib/isodoc/presentation_function/bibdata.rb', line 22

def address_precompose1(addr)
  ret = []
  addr.xpath(ns("./street")).each { |s| ret << to_xml(s.children) }
  a = addr.at(ns("./city")) and ret << to_xml(a.children)
  addr.xpath(ns("./state")).each { |s| ret << to_xml(s.children) }
  a = addr.at(ns("./country")) and ret << to_xml(a.children)
  a = addr.at(ns("./postcode")) and ret[-1] += " #{to_xml a.children}"
  ret.join("<br/>")
end

#admits(elem) ⇒ Object



54
# File 'lib/isodoc/presentation_function/designations.rb', line 54

def admits(elem); end

#admonition(docxml) ⇒ Object



72
73
74
# File 'lib/isodoc/presentation_function/block.rb', line 72

def admonition(docxml)
  docxml.xpath(ns("//admonition")).each { |f| admonition1(f) }
end

#admonition1(elem) ⇒ Object



76
77
78
79
80
81
82
83
84
85
# File 'lib/isodoc/presentation_function/block.rb', line 76

def admonition1(elem)
  if elem["type"] == "box"
    admonition_numbered1(elem)
  elsif elem["notag"] == "true" || elem.at(ns("./name"))
    prefix_name(elem, { label: admonition_delim(elem) }, nil, "name")
  else
    label = admonition_label(elem, nil)
    prefix_name(elem, { label: admonition_delim(elem) }, label, "name")
  end
end

#admonition_delim(_elem) ⇒ Object



101
102
103
# File 'lib/isodoc/presentation_function/block.rb', line 101

def admonition_delim(_elem)
  ""
end

#admonition_label(elem, num) ⇒ Object



94
95
96
97
98
99
# File 'lib/isodoc/presentation_function/block.rb', line 94

def admonition_label(elem, num)
  lbl = if elem["type"] == "box" then @i18n.box
        else @i18n.admonition[elem["type"]]&.upcase
        end
  labelled_autonum(lbl, elem["id"] || elem["original-id"], num)
end

#admonition_numbered1(elem) ⇒ Object



87
88
89
90
91
92
# File 'lib/isodoc/presentation_function/block.rb', line 87

def admonition_numbered1(elem)
  label = admonition_label(elem,
                           @xrefs.anchor(elem["id"] || elem["original-id"],
                                         :label, false))
  prefix_name(elem, { caption: block_delim }, label, "name")
end

#also_lblObject



111
112
113
# File 'lib/isodoc/presentation_function/index.rb', line 111

def also_lbl
  @lang == "en" ? @i18n.see_also : "<em>#{@i18n.see_also}</em>"
end

#amend(docxml) ⇒ Object



151
152
153
# File 'lib/isodoc/presentation_function/block.rb', line 151

def amend(docxml)
  docxml.xpath(ns("//amend")).each { |f| amend1(f) }
end

#amend1(elem) ⇒ Object



155
156
157
158
159
160
161
162
163
# File 'lib/isodoc/presentation_function/block.rb', line 155

def amend1(elem)
  ret = semx_fmt_dup(elem)
  ret.xpath(ns("./locality | ./localityStack | .//autonumber | " \
               "./classification | ./contributor | ./fmt-name | " \
               "./fmt-xref-label")).each(&:remove)
  amend_newcontent(ret)
  ret.xpath(ns("./description")).each { |a| a.replace(a.children) }
  elem.next = ret
end

#amend_newcontent(elem) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/isodoc/presentation_function/block.rb', line 165

def amend_newcontent(elem)
  elem.xpath(ns(".//newcontent")).each do |a|
    a.name = "quote"
    a["type"] = "newcontent"
    a.xpath(ns("./clause")).reverse_each do |c|
      amend_subclause(c, 1)
      a.next = c
    end
  end
  elem.xpath(ns("./quote[not(node())]")).each(&:remove)
end

#amend_subclause(clause, depth) ⇒ Object



177
178
179
180
181
182
# File 'lib/isodoc/presentation_function/block.rb', line 177

def amend_subclause(clause, depth)
  amend_subclause_title(clause, depth)
  clause.name = depth == 1 ? "quote" : "quote" # "div"
  clause["type"] = "newcontent"
  clause.xpath(ns("./clause")).each { |c| amend_subclause(c, depth + 1) }
end

#amend_subclause_title(clause, _depth) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/isodoc/presentation_function/block.rb', line 184

def amend_subclause_title(clause, _depth)
  if clause["type"] == "annex"
    annex1(clause)
  else
    clause1(clause) # insert title prefix
  end
  clause.xpath(ns("./title | ./variant-title")).each(&:remove)
  t = clause.at(ns("./fmt-title")) or return
  t.name = "p"
  t["type"] = "floating-title"
  # t["depth"] ||= depth || "1"
end

#anchor_id_postproc(node) ⇒ Object



50
51
52
# File 'lib/isodoc/presentation_function/xrefs.rb', line 50

def anchor_id_postproc(node)
  node["target"]
end

#anchor_id_postprocess(node) ⇒ Object



39
# File 'lib/isodoc/presentation_function/inline.rb', line 39

def anchor_id_postprocess(node); end

#anchor_linkend(node, linkend) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/isodoc/presentation_function/xrefs.rb', line 33

def anchor_linkend(node, linkend)
  node["style"] == "id" and
    return anchor_id_postproc(node)
  node["style"] && x = @ref_renderings&.dig(node["bibitemid"], :citation,
                                            node["style"].to_sym) and
    return x.strip
  node["citeas"].nil? && node["bibitemid"] and
    return citeas_cleanup(@xrefs.anchor(node["bibitemid"], :xref)) || "???"
  node.at(ns("./location")) and
    return combine_xref_locations(node) || "???"
  node["target"] && node["droploc"] and
    return anchor_value(node["target"]) || "???"
  node["target"] && !/.#./.match(node["target"]) and
    return anchor_linkend1(node) || "???"
  linkend || "???"
end

#anchor_linkend1(node) ⇒ Object



54
55
56
57
58
59
# File 'lib/isodoc/presentation_function/xrefs.rb', line 54

def anchor_linkend1(node)
  linkend = anchor_xref(node, node["target"])
  container = @xrefs.anchor(node["target"], :container, false)
  linkend = prefix_container(container, linkend, node, node["target"])
  capitalise_xref(node, linkend, anchor_value(node["target"]))
end

#anchor_sanitise(docxml) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/isodoc/presentation_function/ids.rb', line 82

def anchor_sanitise(docxml)
  Metanorma::Utils::anchor_attributes.each do |a|
    docxml.xpath("//xmlns:#{a[0]}").each do |x|
      x[a[1]] &&= to_ncname(x[a[1]])
    end
  end
end

#anchor_value(id) ⇒ Object



28
29
30
31
# File 'lib/isodoc/presentation_function/xrefs.rb', line 28

def anchor_value(id)
  @xrefs.anchor(id, :bare_xref) || @xrefs.anchor(id, :value) ||
    @xrefs.anchor(id, :label) || @xrefs.anchor(id, :xref)
end

#anchor_xref(node, target, container: false) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/isodoc/presentation_function/xrefs.rb', line 61

def anchor_xref(node, target, container: false)
  x = anchor_xref_short(node, target, container)
  t = @xrefs.anchor(target, :title)
  ret = case node["style"]
        when "basic" then t
        when "full" then anchor_xref_full(x, t)
        when "short", nil then x
        else @xrefs.anchor(target, node[:style].to_sym)
        end
  ret || x
end

#anchor_xref_full(num, title) ⇒ Object



81
82
83
84
# File 'lib/isodoc/presentation_function/xrefs.rb', line 81

def anchor_xref_full(num, title)
  (!title.nil? && !title.empty?) or return nil
  l10n("#{num}<span class='fmt-comma'>,</span> #{title}")
end

#anchor_xref_short(node, target, container) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/isodoc/presentation_function/xrefs.rb', line 73

def anchor_xref_short(node, target, container)
  if (l = node["label"]) && !container
    v = anchor_value(target)
    @i18n.l10n(%[<span class="fmt-element-name">#{l}</span> #{esc v}])
  else @xrefs.anchor(target, :xref)
  end
end

#annex(docxml) ⇒ Object



3
4
5
6
7
8
9
10
# File 'lib/isodoc/presentation_function/annex.rb', line 3

def annex(docxml)
  docxml.xpath(ns("//annex")).each do |f|
    @xrefs.klass.single_term_clause?(f) and single_term_clause_retitle(f)
    annex1(f)
    @xrefs.klass.single_term_clause?(f) and single_term_clause_unnest(f)
  end
  @xrefs.parse_inclusions(clauses: true).parse(docxml)
end

#annex1(elem) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/isodoc/presentation_function/annex.rb', line 12

def annex1(elem)
  lbl = @xrefs.anchor(elem["id"], :label, false)
  orig_title = annex1_title_fmt(elem)
  %w(title variant-title).each do |k|
    k == "variant-title" && (t = elem.at(ns("./variant-title"))) &&
      t["type"] != "_toc_temp" and next
    # we only prefix variant-title we have just copied from title
    annex1_title_prefix(elem, lbl, k)
  end
  annex1_title_postprocess(elem, orig_title)
end

#annex1_title_fmt(elem) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/isodoc/presentation_function/annex.rb', line 24

def annex1_title_fmt(elem)
  t = elem.at(ns("./title")) or return nil
  unless elem.at(ns("./variant-title[@type='toc']"))
    t.next = to_xml(t)
    v = t.next
    v.name = "variant-title"
    v["type"] = "_toc_temp"
  end
  orig_title = to_xml(t.children)
  t.children = annex1_title_fmt_inline(t)
  orig_title
end

#annex1_title_fmt_inline(title) ⇒ Object



37
38
39
# File 'lib/isodoc/presentation_function/annex.rb', line 37

def annex1_title_fmt_inline(title)
  "<strong>#{to_xml(title.children)}</strong>"
end

#annex1_title_postprocess(elem, orig_title) ⇒ Object

only accept variant-title we have just copied from title and prefixed into fmt-variant-title: that replaces the variant-title we have inserted



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/isodoc/presentation_function/annex.rb', line 66

def annex1_title_postprocess(elem, orig_title)
  v, t, v1 = annex1_variant_title_postprocess_prep(elem)
  t&.children = orig_title
  v1&.name == "fmt-variant-title" or return
  v&.remove
  v1.name = "variant-title"
  v1["type"] = "toc"
  s = v1.at(ns(".//semx[@element = 'variant-title']")) or return
  s["element"] = "title"
  t and s["source"] = t["id"]
end

#annex1_title_prefix(elem, lbl, tag) ⇒ Object



41
42
43
44
45
46
47
48
49
# File 'lib/isodoc/presentation_function/annex.rb', line 41

def annex1_title_prefix(elem, lbl, tag)
  delim, lbl = annex1_title_prefix_prep(elem, lbl, tag)
  if unnumbered_clause?(elem)
    prefix_name(elem, {}, nil, tag)
  else
    prefix_name(elem, { caption: delim }, lbl, tag,
                fmt_xref_label: tag == "title")
  end
end

#annex1_title_prefix_prep(elem, lbl, tag) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/isodoc/presentation_function/annex.rb', line 51

def annex1_title_prefix_prep(elem, lbl, tag)
  delim = annex_delim_override(elem)
  if tag == "variant-title" # strip obligation, boldface
    lbl &&= lbl.gsub("<strong>", "").gsub("</strong>", "")
      # Use (?:<br/>)* (non-capturing) and [^<]* instead of .+? so the
      # obligation-span content is matched without polynomial backtracking.
      # fmt-obligation spans contain plain text, so [^<]* is equivalent.
      .sub(%r{(?:<br/>)*<span class=.fmt-obligation.>[^<]*</span>}, "")
    delim = "<tab/>"
  end
  [delim, lbl]
end

#annex1_variant_title_postprocess_prep(elem) ⇒ Object



78
79
80
81
82
83
84
85
86
# File 'lib/isodoc/presentation_function/annex.rb', line 78

def annex1_variant_title_postprocess_prep(elem)
  v = elem.at(ns("./variant-title[@type='_toc_temp']"))
  t = elem.at(ns("./title"))
  # fmt-variant-title generated from variant-title
  v1 = v&.next_element ||
    #  fmt-variant-title generated only from lbl
    elem.at(ns("./fmt-variant-title"))
  [v, t, v1]
end

#annex_delim(_elem) ⇒ Object



93
94
95
# File 'lib/isodoc/presentation_function/annex.rb', line 93

def annex_delim(_elem)
  "<br/><br/>"
end

#annex_delim_override(elem) ⇒ Object



88
89
90
91
# File 'lib/isodoc/presentation_function/annex.rb', line 88

def annex_delim_override(elem)
  m = elem.document.root.at(ns("//presentation-metadata/annex-delim"))
  m ? to_xml(m.children) : annex_delim(elem)
end

#annotations(elem, fmt_elem) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 70

def annotations(elem, fmt_elem)
  elem.at(ns("./callout-annotation")) or return
  ret = ""
  elem.xpath(ns("./callout-annotation")).each do |a|
    id = a["original-id"]
    dd = semx_fmt_dup(a)
    dd["source"] = a["id"]
    ret += <<~OUT
      <dt id='#{id}'><span class='c'>#{@callouts[id]}</span></dt>
      <dd>#{to_xml dd}</dd>
    OUT
  end
  fmt_elem.xpath(ns("./callout-annotation")).each(&:remove)
  fmt_elem << "<dl><name>#{@i18n.key}</name>#{ret}</dl>"
end

#asciimath_dup(node) ⇒ Object



181
182
183
184
185
186
187
188
189
190
# File 'lib/isodoc/presentation_function/math.rb', line 181

def asciimath_dup(node)
  @suppressasciimathdup || node.parent.at(ns("./asciimath")) and return
  math = node.to_xml.gsub(/ xmlns=["'][^"']*["']/, "")
    .gsub(%r{<[^:/>]*:}, "<").gsub(%r{</[^:/>]*:}, "</")
    .gsub(%r{ data-metanorma-numberformat="[^"]*"}, "")
  ret = Plurimath::Math.parse(math, "mathml").to_asciimath
  node.next = "<asciimath>#{@c.encode(ret, :basic)}</asciimath>"
rescue StandardError => e
  warn "Failure to convert MathML to AsciiMath\n#{node.parent.to_xml}\n#{e}"
end

#attachments_extract(docxml) ⇒ Object



61
62
63
64
65
66
67
68
69
# File 'lib/isodoc/presentation_function/metadata.rb', line 61

def attachments_extract(docxml)
  docxml.at(ns("//metanorma-extension/attachment")) or return
  dir = File.join(@output_dir, "_#{@outputfile}_attachments")
  FileUtils.rm_rf(dir)
  FileUtils.mkdir_p(dir)
  docxml.xpath(ns("//metanorma-extension/attachment")).each do |a|
    save_attachment(a, dir)
  end
end

#autonum(id, num) ⇒ Object



88
89
90
91
# File 'lib/isodoc/presentation_function/autonum.rb', line 88

def autonum(id, num)
  num.include?("<semx") and return num # already contains markup
  "<semx element='autonum' source='#{id}'>#{num}</semx>"
end

#bibdata(docxml) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/isodoc/presentation_function/bibdata.rb', line 5

def bibdata(docxml)
  a = bibdata_current(docxml) or return
  address_precompose(a)
  bibdata_i18n(a)
  @xrefs.klass.localdir ||= @localdir
  @xrefs.klass.info docxml, nil
end

#bibdata_current(docxml) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/isodoc/presentation_function/bibdata.rb', line 32

def bibdata_current(docxml)
  a = docxml.at(ns("//bibdata")) or return
  { language: @lang, script: @script, locale: @locale }.each do |k, v|
    a.xpath(ns("./#{k}")).each do |l|
      l.text == v and l["current"] = "true"
    end
  end
  a
end

#bibdata_i18n(bib) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/isodoc/presentation_function/bibdata.rb', line 42

def bibdata_i18n(bib)
  hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype",
                 "//presentation-metadata/doctype-alias", @lang)
  hash_translate(bib, @i18n.get["stage_dict"], "./status/stage",
                 "//presentation-metadata/stage-alias", @lang)
  hash_translate(bib, @i18n.get["substage_dict"], "./status/substage", nil,
                 @lang)
  edition_translate(bib)
end

#bibitem(bib, renderings) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/isodoc/presentation_function/refs.rb', line 19

def bibitem(bib, renderings)
  implicit_reference(bib) and bib["hidden"] = "true"
  notes_inside_bibitem(bib)
  bibrender_item(bib, renderings)
  add_id_to_display_bib_notes(bib)
  @xrefs.bibitem_note_names(bib)
end

#bibitem_lookup(docxml) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/isodoc/presentation_xml_convert.rb', line 62

def bibitem_lookup(docxml)
  @bibitem_lookup ||= docxml.xpath(ns("//references/bibitem"))
    .each_with_object({}) do |b, m|
    m[b["id"]] = b
    m[b["anchor"]] = b
  end
end

#bibitem_notes(bib) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/isodoc/presentation_function/refs.rb', line 64

def bibitem_notes(bib)
  f = bib.at(ns("./formattedref")) or return
  bibnote_extract(bib, "display").each do |n|
    f << <<~XML
      <note type='display'>#{to_xml(semx_fmt_dup(n))}</note>
    XML
    transfer_id(n, f.elements.last)
  end
end

#bibitem_ref_code(bib) ⇒ Object

returns [metanorma, non-metanorma, DOI/ISSN/ISBN] identifiers



30
31
32
33
34
35
36
# File 'lib/isodoc/presentation_function/docid.rb', line 30

def bibitem_ref_code(bib)
  ret = bibitem_ref_code_prep(bib)
  ret.all?(&:nil?) or return ret
  bib["suppress_identifier"] == "true" and return [nil, nil, nil, nil, nil]
  # [nil, no_identifier(bib), nil, nil]
  [nil, nil, nil, nil, nil]
end

#bibitem_ref_code_prep(bib) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/isodoc/presentation_function/docid.rb', line 38

def bibitem_ref_code_prep(bib)
  id = bib.at(ns("./docidentifier[@type = 'metanorma']"))
  id1 = pref_ref_code(bib)
  id2 = bib.at(ns("./docidentifier[#{SERIAL_NUM_DOCID}]"))
  id3 = bib.at(ns("./docidentifier[@type = 'metanorma-ordinal']"))
  id4 = bib.at(ns("./docidentifier[@type = 'title']")) ||
    bib.at(ns("./docidentifier[@type = 'author-date']"))
  [id, id1, id2, id3, id4]
end

#biblio_ref_entry_code(ordinal, ids, _standard, datefn, _bib) ⇒ Object

if ids is just a number, only use that ([1] Non-Standard) else, use both ordinal, as prefix, and ids



163
164
165
166
167
168
169
170
171
172
173
# File 'lib/isodoc/presentation_function/refs.rb', line 163

def biblio_ref_entry_code(ordinal, ids, _standard, datefn, _bib)
  ret = esc(ids[:ordinal]) || esc(ids[:content]) || esc(ids[:metanorma]) ||
    "[#{esc ordinal.to_s}]"
  if ids[:sdo] && !ids[:sdo].empty?
    ret = prefix_bracketed_ref(ret)
    ret += "#{esc ids[:sdo]}#{datefn}, "
  else
    ret = prefix_bracketed_ref("#{ret}#{datefn}")
  end
  ret
end

#bibliography_bibitem_number(docxml) ⇒ Object



82
83
84
85
86
87
88
89
90
91
# File 'lib/isodoc/presentation_function/refs.rb', line 82

def bibliography_bibitem_number(docxml)
  i = 0
  docxml.xpath(ns("//references")).each do |r|
    r.xpath(ns("./bibitem")).each do |b|
      i = bibliography_bibitem_number1(b, i, r["normative"] == "true")
    end
  end
  reference_names docxml
  bibliography_bibitem_tag(docxml)
end

#bibliography_bibitem_number1(bibitem, idx, normative) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/isodoc/presentation_function/refs.rb', line 93

def bibliography_bibitem_number1(bibitem, idx, normative)
  ins = bibliography_bibitem_number_insert_pt(bibitem)
  mn = bibitem.at(ns(".//docidentifier[@type = 'metanorma']")) and
    /^\[?\d+\]?$/.match?(mn.text) and mn.remove # ignore numbers already inserted
  if !bibliography_bibitem_number_skip(bibitem) && (!normative || mn)
    # respect numeric ids in normative only if already inserted
    idx += 1
    ins.next =
      "<docidentifier type='metanorma-ordinal'>[#{idx}]</docidentifier>"
  end
  idx
end

#bibliography_bibitem_number_insert_pt(bibitem) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/isodoc/presentation_function/refs.rb', line 106

def bibliography_bibitem_number_insert_pt(bibitem)
  bibitem.children.empty? and bibitem.add_child(" ")
  unless d = bibitem.at(ns(".//docidentifier"))
    d = bibitem.children.first
    d.previous = " " and return d.previous
  end
  unless ins = d.previous_element
    d.previous = " "
    ins = d.previous
  end
  ins
end

#bibliography_bibitem_number_skip(bibitem) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/isodoc/presentation_function/refs.rb', line 74

def bibliography_bibitem_number_skip(bibitem)
  implicit_reference(bibitem) ||
    bibitem.at(ns(".//docidentifier[@type = 'metanorma']")) ||
    bibitem.at(ns(".//docidentifier[@type = 'metanorma-ordinal']")) ||
    bibitem["suppress_identifier"] == "true" ||
    bibitem["hidden"] == "true" || bibitem.parent["hidden"] == "true"
end

#bibliography_bibitem_tag(docxml) ⇒ Object



119
120
121
122
123
124
125
126
# File 'lib/isodoc/presentation_function/refs.rb', line 119

def bibliography_bibitem_tag(docxml)
  [true, false].each do |norm|
    i = 0
    docxml.xpath(ns("//references[@normative = '#{norm}']")).each do |r|
      i = bibliography_bibitem_tag1(r, i, norm)
    end
  end
end

#bibliography_bibitem_tag1(ref, idx, norm) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/isodoc/presentation_function/refs.rb', line 128

def bibliography_bibitem_tag1(ref, idx, norm)
  ref.xpath(ns("./bibitem")).each do |b|
    implicit_reference(b) and next
    b["suppress_identifier"] == "true" and next
    idx += 1 unless b["hidden"]
    insert_biblio_tag(b, idx, !norm, standard?(b))
  end
  idx
end

#bibnote_extract(bib, type) ⇒ Object



179
180
181
182
183
184
# File 'lib/isodoc/presentation_function/refs.rb', line 179

def bibnote_extract(bib, type)
  bib.xpath(ns("./note")).each_with_object([]) do |n, m|
    n["type"] or next
    n["type"].split(",").map(&:strip).include?(type) and m << n
  end
end

#bibrender_formattedref(formattedref, bib) ⇒ Object



50
# File 'lib/isodoc/presentation_function/refs.rb', line 50

def bibrender_formattedref(formattedref, bib); end

#bibrender_item(bib, renderings) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/isodoc/presentation_function/refs.rb', line 42

def bibrender_item(bib, renderings)
  if (f = bib.at(ns("./formattedref"))) && bib.at(ns("./title")).nil?
    bibrender_formattedref(f, bib)
  else bibrender_relaton(bib, renderings)
  end
  bibitem_notes(bib)
end

#bibrender_relaton(bib, renderings) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/isodoc/presentation_function/refs.rb', line 52

def bibrender_relaton(bib, renderings)
  f = renderings[bib["id"]][:formattedref] or return
  f &&= "<formattedref>#{f}</formattedref>"
  if x = bib.at(ns("./formattedref"))
    x.replace(f)
  elsif bib.children.empty?
    bib << f
  else
    bib.children.first.previous = f
  end
end

#blank?(elem) ⇒ Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/isodoc/presentation_function/metadata.rb', line 166

def blank?(elem)
  elem.nil? || (elem.respond_to?(:empty?) && elem.empty?)
end

#block(docxml) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/isodoc/presentation_xml_convert.rb', line 101

def block(docxml)
  amend docxml # feeds all other blocks
  table docxml
  figure docxml
  sourcecode docxml
  formula docxml
  example docxml
  note docxml
  admonition docxml
  source docxml
  ul docxml # feeds list_to_table
  ol docxml # feeds list_to_table
  list_to_table docxml
  dl docxml
  quote docxml
  permission docxml
  requirement docxml
  recommendation docxml
  requirement_render docxml
end

#block?(node) ⇒ Boolean

Returns:

  • (Boolean)


221
222
223
224
225
# File 'lib/isodoc/presentation_function/autonum.rb', line 221

def block?(node)
  %w(figure table note example termnote termexample formula sourcecode
     admonition ul ol dl quote permission requirement recommendation)
    .include?(node.name)
end

#block_delimObject



18
19
20
# File 'lib/isodoc/presentation_function/block.rb', line 18

def block_delim
  "&#xa0;&#x2014; "
end

#bracket(num) ⇒ Object



68
69
70
71
72
# File 'lib/isodoc/presentation_function/docid.rb', line 68

def bracket(num)
  num.nil? and return nil
  num = xml_to_string_skip_fn(num).sub(/^\[/, "").sub(/\]$/, "")
  "[#{num}]"
end

#bracket_if_num(num) ⇒ Object



61
62
63
64
65
66
# File 'lib/isodoc/presentation_function/docid.rb', line 61

def bracket_if_num(num)
  num.nil? and return nil
  num = xml_to_string_skip_fn(num).sub(/^\[/, "").sub(/\]$/, "")
  /^\d+$/.match?(num) and return "[#{num}]"
  num
end

#callouts(elem) ⇒ Object



35
36
37
38
39
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 35

def callouts(elem)
  elem.xpath(ns(".//callout")).each do |c|
    @callouts[c["target"]] = to_xml(c.children)
  end
end

#can_conflate_eref_rendering?(refs) ⇒ Boolean

Returns:

  • (Boolean)


23
24
25
26
27
28
29
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 23

def can_conflate_eref_rendering?(refs)
  (refs.size > 1 &&
    refs.all? { |r| r.name == "localityStack" } &&
    refs.all? { |r| r.xpath(ns("./locality")).size == 1 }) or return false
  first = refs.first.at(ns("./locality/@type")).text
  refs.all? { |r| r.at(ns("./locality/@type")).text == first }
end

#can_conflate_xref_rendering?(locs) ⇒ Boolean

Returns:

  • (Boolean)


189
190
191
192
193
194
# File 'lib/isodoc/presentation_function/xrefs.rb', line 189

def can_conflate_xref_rendering?(locs)
  @i18n.get["no_conflate_xref_locations"] == true and return false
  (locs.all? { |l| l[:container].nil? } ||
   locs.all? { |l| l[:container] == locs.first[:container] }) &&
    locs.all? { |l| l[:type] == locs[0][:type] }
end

#capitalise_xref(node, linkend, label) ⇒ Object



196
197
198
199
200
201
202
203
# File 'lib/isodoc/presentation_function/xrefs.rb', line 196

def capitalise_xref(node, linkend, label)
  linktext = linkend.gsub(/<[^<>]*>/, "")
  (label && !label.empty? && /^#{Regexp.escape(label)}/.match?(linktext)) ||
    linktext[0, 1].match?(/\p{Upper}/) and return linkend
  node["case"] and
    return Common::case_with_markup(linkend, node["case"], @script)
  capitalise_xref1(node, linkend)
end

#capitalise_xref1(node, linkend) ⇒ Object



205
206
207
208
209
210
# File 'lib/isodoc/presentation_function/xrefs.rb', line 205

def capitalise_xref1(node, linkend)
  if start_of_sentence(node)
    Common::case_with_markup(linkend, "capital", @script)
  else linkend
  end
end

#change_case(span, value, seen_space) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/isodoc/presentation_function/inline.rb', line 142

def change_case(span, value, seen_space)
  span.traverse do |s|
    s.text? or next
    case value
    when "uppercase" then s.replace s.text.upcase
    when "lowercase" then s.replace s.text.downcase
    when "capitalize"
      s.replace conditional_capitalize(s.text, seen_space)
    end
    seen_space = /\s$/.match?(s.text)
  end
end

#citeas(xmldoc) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
# File 'lib/isodoc/presentation_function/erefs.rb', line 6

def citeas(xmldoc)
  xmldoc.xpath(ns("//fmt-eref | //fmt-origin | //fmt-link"))
    .each do |e|
    sem_xml_descendant?(e) and next
    (e["bibitemid"] && e["citeas"]) or next
    a = @xrefs.anchor(e["bibitemid"], :xref, false) or next
    e["citeas"] = citeas_cleanup(a)
    # link generated in collection postprocessing from eref
    e.name == "fmt-link" && e.text.empty? and e.children = e["citeas"]
  end
end

#citeas_cleanup(ref) ⇒ Object



18
19
20
21
22
23
24
25
26
# File 'lib/isodoc/presentation_function/erefs.rb', line 18

def citeas_cleanup(ref)
  ref.nil? and return nil
  if ref.include?("<")
    xml = Nokogiri::XML("<root>#{ref}</root>")
    xml.xpath("//semx").each { |x| x.replace(x.children) }
    ref = to_xml(xml.at("//root").children)
  end
  ref
end

#cjk_extended_title(doc) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/isodoc/presentation_function/title.rb', line 75

def cjk_extended_title(doc)
  l = cjk_search
  doc.xpath(ns("//bibdata/title[#{l}] | //floating-title[#{l}] | " \
               "//fmt-title[@depth = '1' or not(@depth)][#{l}]"))
    .each do |t|
    t.text.size < 4 or next
    t.traverse do |n|
      n.text? or next
      n.replace(@i18n.cjk_extend(n.text))
    end
  end
end

#cjk_searchObject



68
69
70
71
72
73
# File 'lib/isodoc/presentation_function/title.rb', line 68

def cjk_search
  lang = %w(zh ja ko).map { |x| "@language = '#{x}'" }.join(" or ")
  %(Hans Hant Jpan Hang Kore).include?(@script) and
    lang += " or not(@language)"
  lang
end

#clause(docxml) ⇒ Object



3
4
5
6
7
8
9
10
11
12
# File 'lib/isodoc/presentation_function/section.rb', line 3

def clause(docxml)
  docxml.xpath(ns("//clause | //terms | //definitions | //references | " \
                  "//introduction | //foreword | //preface/abstract | " \
                  "//acknowledgements | //colophon | //indexsect | " \
                  "//executivesummary | //appendix")).each do |f|
    f.parent.name == "annex" &&
      @xrefs.klass.single_term_clause?(f.parent) and next
    clause1(f)
  end
end

#clause1(elem) ⇒ Object



40
41
42
43
44
45
46
47
48
49
# File 'lib/isodoc/presentation_function/section.rb', line 40

def clause1(elem)
  level, is_unnumbered, lbl = clause1_prep(elem)
  if is_unnumbered || !lbl
    prefix_name(elem, {}, nil, "title")
  else
    prefix_name(elem, { caption: "<tab/>" }, "#{lbl}#{clausedelim}",
                "title")
  end
  t = elem.at(ns("./fmt-title")) and t["depth"] = level
end

#clause1_prep(elem) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/isodoc/presentation_function/section.rb', line 51

def clause1_prep(elem)
  level = @xrefs.anchor(elem["id"], :level, false) ||
    (elem.ancestors("clause, annex").size + 1)
  is_unnumbered = unnumbered_clause?(elem)
  lbl = @xrefs.anchor(elem["id"], :label, false)
  [level, is_unnumbered, lbl]
end

#clausedelimObject



34
35
36
37
38
# File 'lib/isodoc/presentation_function/section.rb', line 34

def clausedelim
  ret = super
  (ret && !ret.empty?) or return ret
  "<span class='fmt-autonum-delim'>#{ret}</span>"
end

#clausetitle(docxml) ⇒ Object



64
65
66
# File 'lib/isodoc/presentation_function/title.rb', line 64

def clausetitle(docxml)
  cjk_extended_title(docxml)
end

#cleanup(docxml) ⇒ Object



3
4
5
6
# File 'lib/isodoc/presentation_function/cleanup.rb', line 3

def cleanup(docxml)
  docxml["type"] = "presentation"
  empty_elements_remove(docxml)
end

#combine_conflated_xref_locations(locs) ⇒ Object

Note % to entry and Note % to entry: cannot conflate as Note % to entry 1 and 2 So Notes 1 and 3, but Note 1 to entry and Note 3 to entry



110
111
112
113
114
115
116
117
# File 'lib/isodoc/presentation_function/xrefs.rb', line 110

def combine_conflated_xref_locations(locs)
  out = if locs.any? { |l| l[:elem]&.include?("%") }
          locs.each { |l| l[:label] = @xrefs.anchor(l[:target], :xref) }
        else
          conflate_xref_locations(locs)
        end
  combine_conflated_xref_locations_container(locs, l10n(combine_conn(out)))
end

#combine_conflated_xref_locations_container(locs, ret) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/isodoc/presentation_function/xrefs.rb', line 126

def combine_conflated_xref_locations_container(locs, ret)
  container = @xrefs.anchor(locs.first[:node]["target"], :container,
                            false)
  prefix_container?(container, locs.first[:node]) and
    ret = prefix_container(container, ret, locs.first[:node],
                           locs.first[:node]["target"])
  ret
end

#combine_conn(list) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/isodoc/presentation_function/xrefs.rb', line 156

def combine_conn(list)
  list.size == 1 and list.first[:label]
  if list[1..].all? { |l| l[:conn] == "and" }
    connectives_spans(@i18n.boolean_conj(list.map do |l|
      loc2xref(l)
    end, "and"))
  elsif list[1..].all? { |l| l[:conn] == "or" }
    connectives_spans(@i18n.boolean_conj(list.map do |l|
      loc2xref(l)
    end, "or"))
  else
    ret = loc2xref(list[0])
    list[1..].each { |l| ret = i18n_chain_boolean(ret, l) }
    if list[0][:conn] == "from" && list[0][:custom]
      # TODO: languages with mandatory from, include from in chain_to
      ret = connectives_spans("<conn>#{list[0][:custom]}</conn> ") + ret
    end
    ret
  end
end

#combine_xref_locations(node) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/isodoc/presentation_function/xrefs.rb', line 94

def combine_xref_locations(node)
  locs = gather_xref_locations(node)
  linkend = if can_conflate_xref_rendering?(locs)
              combine_conflated_xref_locations(locs)
            else
              out = locs.each do |l|
                l[:label] = esc(anchor_linkend1(l[:node]))
              end
              l10n(combine_conn(out))
            end
  capitalise_xref(node, linkend, anchor_value(node["target"]))
end

#comment_body(elem) ⇒ Object



178
179
180
181
182
183
# File 'lib/isodoc/presentation_function/footnotes.rb', line 178

def comment_body(elem)
  c1 = elem.after("<fmt-annotation-body/>").next
  elem.attributes.each_key { |k| k == "id" or c1[k] = elem[k] }
  add_id(c1)
  c1 << semx_fmt_dup(elem)
end

#comment_bookmark_end(to, elem) ⇒ Object



225
226
227
228
229
230
231
232
# File 'lib/isodoc/presentation_function/footnotes.rb', line 225

def comment_bookmark_end(to, elem)
  ret = to.after("<fmt-annotation-end/>").next
  add_id(ret)
  ret["source"] = elem["to"]
  comment_to_bookmark_attrs(elem, ret, start: false)
  ret << comment_bookmark_end_label(elem)
  ret
end

#comment_bookmark_end_label(_elem) ⇒ Object



238
239
240
# File 'lib/isodoc/presentation_function/footnotes.rb', line 238

def comment_bookmark_end_label(_elem)
  ""
end

#comment_bookmark_start(from, elem) ⇒ Object



216
217
218
219
220
221
222
223
# File 'lib/isodoc/presentation_function/footnotes.rb', line 216

def comment_bookmark_start(from, elem)
  ret = from.before("<fmt-annotation-start/>").previous
  add_id(ret)
  ret["source"] = elem["from"]
  comment_to_bookmark_attrs(elem, ret, start: true)
  ret << comment_bookmark_start_label(elem)
  ret
end

#comment_bookmark_start_label(_elem) ⇒ Object



234
235
236
# File 'lib/isodoc/presentation_function/footnotes.rb', line 234

def comment_bookmark_start_label(_elem)
  ""
end

#comment_bookmarks(elem) ⇒ Object



185
186
187
188
189
190
191
# File 'lib/isodoc/presentation_function/footnotes.rb', line 185

def comment_bookmarks(elem)
  from, to = comment_bookmarks_locate(elem)
  new_from = comment_bookmark_start(from, elem)
  new_to = comment_bookmark_end(to, elem)
  elem["from"] = new_from["id"]
  elem["to"] = new_to["id"]
end

#comment_bookmarks_locate(elem) ⇒ Object



200
201
202
203
204
205
206
# File 'lib/isodoc/presentation_function/footnotes.rb', line 200

def comment_bookmarks_locate(elem)
  from = elem.document.at("//*[@id = '#{elem['from']}']")
  f = from.at(".//text()#{AVOID_COMMENT_BOOKMARKS}") and from = f
  to = elem.document.at("//*[@id = '#{elem['to']}']") || from
  f = to.at(".//text()[last()]#{AVOID_COMMENT_BOOKMARKS}") and to = f
  [from, to]
end

#comment_to_bookmark_attrs(elem, bookmark, start: true) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/isodoc/presentation_function/footnotes.rb', line 208

def comment_to_bookmark_attrs(elem, bookmark, start: true)
  bookmark["target"] = elem["id"]
  if start then bookmark["end"] = elem["to"]
  else bookmark["start"] = elem["from"]
  end
  %w(author date).each { |k| bookmark[k] = elem[k] }
end

#comments(docxml) ⇒ Object



163
164
165
166
167
168
169
170
# File 'lib/isodoc/presentation_function/footnotes.rb', line 163

def comments(docxml)
  global_display = display_comments_global?(docxml)
  docxml.xpath(ns("//annotation")).each do |c|
    global_display || display_comment_override?(c) or next
    c1 = comment_body(c)
    comment_bookmarks(c1)
  end
end

#concept(docxml) ⇒ Object



3
4
5
6
7
# File 'lib/isodoc/presentation_function/concepts.rb', line 3

def concept(docxml)
  @definition_ids = docxml.xpath(ns("//definitions//dt"))
    .each_with_object({}) { |x, m| m[x["id"]] = true }
  docxml.xpath(ns("//concept")).each { |f| concept1(f) }
end

#concept1(node) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/isodoc/presentation_function/concepts.rb', line 9

def concept1(node)
  node.ancestors("definition, source, related").empty? or return
  xref = node&.at(ns("./semx/fmt-xref/@target"))&.text or
    return concept_render(node, ital: "true", ref: "true", bold: "false",
                                linkref: "true", linkmention: "false")
  if @definition_ids[xref]
    concept_render(node, ital: "false", ref: "false", bold: "false",
                         linkref: "true", linkmention: "false")
  else concept_render(node, ital: "true", ref: "true", bold: "false",
                            linkref: "true", linkmention: "false")
  end
end

#concept1_linkmention(ref, renderterm, opts) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/isodoc/presentation_function/concepts.rb', line 74

def concept1_linkmention(ref, renderterm, opts)
  (opts[:linkmention] == "true" && !renderterm.nil? && !ref.nil?) or return
  ref2 = ref.clone
  r2 = renderterm.clone
  ref2.children = r2
  if ref.parent.name == "semx"
    renderterm.replace(<<~SEMX)
      <semx element='#{ref.parent['element']}' source='#{ref.parent['source']}'>#{to_xml(ref2)}</semx>
    SEMX
  else
    renderterm.replace(ref2)
  end
end

#concept1_ref(_node, ref, opts) ⇒ Object



88
89
90
91
92
93
94
95
# File 'lib/isodoc/presentation_function/concepts.rb', line 88

def concept1_ref(_node, ref, opts)
  ref.nil? and return
  opts[:ref] == "false" and return ref.remove
  concept1_ref_content(ref)
  %w(fmt-xref fmt-eref).include? ref.name and get_linkend(ref)
  opts[:linkref] == "false" && %w(fmt-xref fmt-eref).include?(ref.name) and
    ref.replace(ref.children)
end

#concept1_ref_content(ref) ⇒ Object



97
98
99
100
101
102
103
104
105
106
# File 'lib/isodoc/presentation_function/concepts.rb', line 97

def concept1_ref_content(ref)
  prev = "["
  foll = "]"
  non_locality_elems(ref).select do |c|
    !c.text? || /\S/.match(c)
  end.empty? or
    (prev, foll = @i18n.term_defined_in.split("%"))
  ref.previous = prev
  ref.next = foll
end

#concept1_style(node, opts) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/isodoc/presentation_function/concepts.rb', line 53

def concept1_style(node, opts)
  r = node.at(ns(".//renderterm")) or return
  opts[:ital] == "true" and r.children = "<em>#{to_xml(r.children)}</em>"
  opts[:bold] == "true" and
    r.children = "<strong>#{to_xml(r.children)}</strong>"
  r.replace(r.children)
end

#concept_dup(node, ret) ⇒ Object



32
33
34
35
36
37
38
39
40
41
# File 'lib/isodoc/presentation_function/concepts.rb', line 32

def concept_dup(node, ret)
  concept_dup_cleanup_orig(node)
  ret.xpath(ns(".//xref | .//eref | .//origin | .//link")).each(&:remove)
  ret.xpath(ns(".//semx")).each do |s|
    s.children.empty? and s.remove
  end
  f = Nokogiri::XML::Node.new("fmt-concept", node.document)
  f << ret
  node.next = f
end

#concept_dup_cleanup_orig(node) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/isodoc/presentation_function/concepts.rb', line 43

def concept_dup_cleanup_orig(node)
  node.xpath(".//xmlns:semx[xmlns:fmt-xref | xmlns:fmt-eref | " \
             "xmlns:fmt-origin | xmlns:fmt-link]").each(&:remove)
  node.xpath(ns(".//xref | .//eref | .//origin | .//link")).each do |x|
    x["original-id"] or next
    x["id"] = x["original-id"]
    x.delete("original-id")
  end
end

#concept_render(node, defaults) ⇒ Object



22
23
24
25
26
27
28
29
30
# File 'lib/isodoc/presentation_function/concepts.rb', line 22

def concept_render(node, defaults)
  opts, render, ref, ret = concept_render_init(node, defaults)
  ret&.at(ns("./refterm"))&.remove
  ref && opts[:ref] != "false" and render&.next = " "
  concept1_linkmention(ref, render, opts)
  concept1_ref(ret, ref, opts)
  concept1_style(ret, opts)
  concept_dup(node, ret)
end

#concept_render_init(node, defaults) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/isodoc/presentation_function/concepts.rb', line 61

def concept_render_init(node, defaults)
  opts = concept_render_opts(node, defaults)
  ret = semx_fmt_dup(node)
  ret.children.each { |x| x.text? and x.remove }
  [opts, ret.at(ns("./renderterm")),
   ret.at(ns("./semx/fmt-xref | ./semx/fmt-eref | ./termref")), ret]
end

#concept_render_opts(node, defaults) ⇒ Object



69
70
71
72
# File 'lib/isodoc/presentation_function/concepts.rb', line 69

def concept_render_opts(node, defaults)
  %i(bold ital ref linkref linkmention)
    .each_with_object({}) { |x, m| m[x] = node[x.to_s] || defaults[x] }
end

#conditional_capitalize(text, seen_space) ⇒ Object



155
156
157
158
159
160
161
# File 'lib/isodoc/presentation_function/inline.rb', line 155

def conditional_capitalize(text, seen_space)
  m = text.split(/(?<=\s)/)
  ((seen_space ? 0 : 1)...m.size).each do |i|
    m[i] = m[i].capitalize
  end
  m.join
end

#conflate_xref_locations(locs) ⇒ Object



119
120
121
122
123
124
# File 'lib/isodoc/presentation_function/xrefs.rb', line 119

def conflate_xref_locations(locs)
  out = locs.each { |l| l[:label] = anchor_value(l[:target]) }
  label = @i18n.inflect(locs.first[:elem], number: "pl")
  out[0][:label] = l10n("#{label} #{esc out[0][:label]}").strip
  out
end

#conn_sub(str, conn) ⇒ Object



177
178
179
# File 'lib/isodoc/presentation_function/xrefs.rb', line 177

def conn_sub(str, conn)
  str.sub(%r{<conn>[^<]+</conn>}, "<conn>#{conn}</conn>")
end

#contenthash_id_cleanup(docxml) ⇒ Object



115
116
117
118
# File 'lib/isodoc/presentation_function/ids.rb', line 115

def contenthash_id_cleanup(docxml)
  add_new_contenthash_id(docxml, @new_ids)
  xref_new_contenthash_id(docxml, @new_ids)
end

#conversions(docxml) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/isodoc/presentation_xml_convert.rb', line 70

def conversions(docxml)
   docxml
  bibdata docxml
  @xrefs.parse docxml
  section docxml
  block docxml
  terms docxml
  inline docxml
end

#convert1(docxml, filename, dir) ⇒ Object



35
36
37
38
39
40
41
# File 'lib/isodoc/presentation_xml_convert.rb', line 35

def convert1(docxml, filename, dir)
  presxml_convert_init(docxml, filename, dir)
  conversions(docxml)
  cleanup(docxml.root)
  validate(docxml.root)
  docxml.to_xml.gsub("&lt;", "&#x3c;").gsub("&gt;", "&#x3e;")
end

#copy_baselevel_termsource(docxml) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/isodoc/presentation_function/terms.rb', line 126

def copy_baselevel_termsource(docxml)
  docxml.xpath(ns("//term[source]")).each do |x|
    s = x.xpath(ns("./source"))
    s1 = x.at(ns("./fmt-termsource"))
    s.each do |ss|
      dup = ss.clone
      modification_dup_align(ss, dup)
      s1 << dup
    end
    strip_duplicate_ids(nil, s, s1)
    %w(status type).each { |a| s[0][a] and s1[a] = s[0][a] }
  end
end

#counter_initObject



43
44
45
# File 'lib/isodoc/presentation_xml_convert.rb', line 43

def counter_init
  @counter = IsoDoc::XrefGen::Counter.new(0, {})
end

#custom_charset(docxml) ⇒ Object



163
164
165
166
167
168
169
# File 'lib/isodoc/presentation_function/inline.rb', line 163

def custom_charset(docxml)
  charsets = extract_custom_charsets(docxml)
  docxml.xpath(ns("//span[@custom-charset]")).each do |s|
    s["style"] ||= ""
    s["style"] += ";font-family:#{charsets[s['custom-charset']]}"
  end
end

#custom_css(docxml) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 11

def custom_css(docxml)
  ret = ""
  @sourcehighlighter and ret += rouge_css_location
  a = docxml.at(ns("//metanorma-extension/" \
                   "clause[title = 'user-css']/sourcecode/body")) and
    ret += "\n#{to_xml(a.children)}"
  ret
end

#date(docxml) ⇒ Object



107
108
109
110
111
112
# File 'lib/isodoc/presentation_function/inline.rb', line 107

def date(docxml)
  (docxml.xpath(ns("//date")) -
   docxml.xpath(ns("//bibdata/date | //bibitem//date"))).each do |d|
     date1(d)
   end
end

#date1(elem) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/isodoc/presentation_function/inline.rb', line 114

def date1(elem)
  elem["value"] && elem["format"] or return
  val = @i18n.date(elem["value"], elem["format"].strip)
  d = semx_fmt_dup(elem)
  d << val
  elem.next = "<fmt-date>#{to_xml(d)}</fmt-date>"
end

#date_note_process(bib) ⇒ Object

strip any fns in docidentifier before they are extracted for rendering



187
188
189
190
191
192
193
194
195
196
# File 'lib/isodoc/presentation_function/refs.rb', line 187

def date_note_process(bib)
  ret = ident_fn(bib)
  date_note = bibnote_extract(bib, "Unpublished-Status")
  date_note.empty? and return ret
  id = "_#{UUIDTools::UUID.random_create}"
  @new_ids[id] = nil
  <<~XML
    #{ret}<fn id='#{id}' reference='#{id}'><p>#{date_note.first.content}</p></fn>
  XML
end

#deprecates(elem) ⇒ Object



48
49
50
51
52
# File 'lib/isodoc/presentation_function/designations.rb', line 48

def deprecates(elem)
  elem.xpath(ns(".//semx[@element = 'deprecates']")).each do |t|
    t.previous = @i18n.l10n("#{@i18n.deprecated}: ")
  end
end

#designation(docxml) ⇒ Object



38
39
40
41
42
43
44
45
46
# File 'lib/isodoc/presentation_function/designations.rb', line 38

def designation(docxml)
  docxml.xpath(ns("//related")).each { |p| related_designation1(p) }
  docxml.xpath(ns("//preferred | //admitted | //deprecates"))
    .each { |p| designation1(p) }
  docxml.xpath(ns("//fmt-preferred | //fmt-admitted | //fmt-deprecates"))
    .each { |t| merge_second_preferred(t) }
  docxml.xpath(ns("//fmt-deprecates")).each { |d| deprecates(d) }
  docxml.xpath(ns("//fmt-admitted")).each { |d| admits(d) }
end

#designation1(desgn) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/isodoc/presentation_function/designations.rb', line 93

def designation1(desgn)
  desgn.parent.name == "related" and return
  out = desgn.parent.at(ns("./fmt-#{desgn.name}"))
  d1 = semx_fmt_dup(desgn)
  s = d1.at(ns("./source"))
  modification_dup_align(desgn.at(ns("./source")), s)
  name = d1.at(ns("./expression/name | ./letter-symbol/name | " \
                     "./graphical-symbol")) or return
  designation_annotate(d1, name, desgn)
  out << d1
  s and out << s.wrap("<fmt-termsource></fmt-termsource>").parent
end

#designation_annotate(desgn, name, orig) ⇒ Object



106
107
108
109
110
111
112
113
114
115
# File 'lib/isodoc/presentation_function/designations.rb', line 106

def designation_annotate(desgn, name, orig)
  # designation_boldface(desgn)
  designation_expression(desgn, name, orig)
  designation_field(desgn, name, orig)
  designation_grammar(desgn, name)
  designation_localization(desgn, name, orig)
  designation_pronunciation(desgn, name)
  designation_bookmarks(desgn, name)
  desgn.children = name.children
end

#designation_boldfacex(desgn) ⇒ Object

KILL



118
119
120
121
122
# File 'lib/isodoc/presentation_function/designations.rb', line 118

def designation_boldfacex(desgn)
  desgn["element"] == "preferred" or return
  name = desgn.at(ns("./expression/name | ./letter-symbol/name")) or return
  name.children = "<strong>#{name.children}</strong>"
end

#designation_bookmarks(desgn, name) ⇒ Object



175
176
177
# File 'lib/isodoc/presentation_function/designations.rb', line 175

def designation_bookmarks(desgn, name)
  desgn.xpath(ns(".//bookmark")).each { |b| name << b.remove }
end

#designation_expression(desgn, name, orig) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/isodoc/presentation_function/designations.rb', line 124

def designation_expression(desgn, name, orig)
  if origname = orig.at(ns("./expression/name"))
    element = "expression/name"
  elsif origname = orig.at(ns("./letter-symbol/name"))
    element = "letter-symbol/name"
  elsif origname = orig.at(ns("./graphical-symbol"))
    element = "graphical-symbol"
  end
  name.children = <<~XML.strip
    <semx element='#{element}' source='#{origname['id'] || origname['original-id']}'>#{to_xml(name.children).strip}</semx>
  XML
  designation_expression_boldface(desgn, name)
end

#designation_expression_boldface(desgn, name) ⇒ Object



138
139
140
141
# File 'lib/isodoc/presentation_function/designations.rb', line 138

def designation_expression_boldface(desgn, name)
  name.name == "name" && desgn["element"] == "preferred" and
    name.children = "<strong>#{to_xml(name.children)}</strong>"
end

#designation_field(_desgn, name, orig) ⇒ Object



143
144
145
146
147
148
# File 'lib/isodoc/presentation_function/designations.rb', line 143

def designation_field(_desgn, name, orig)
  f = orig.xpath(ns("./field-of-application | ./usage-info"))
    &.map { |u| to_xml(semx_fmt_dup(u)) }&.join(", ")
  f&.empty? and return nil
  name << "<span class='fmt-designation-field'>, &#x3c;#{f}&#x3e;</span>"
end

#designation_grammar(desgn, name) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
# File 'lib/isodoc/presentation_function/designations.rb', line 150

def designation_grammar(desgn, name)
  g = desgn.at(ns("./expression/grammar")) or return
  ret = g.xpath(ns("./gender | ./number")).each_with_object([]) do |x, m|
    m << @i18n.grammar_abbrevs[x.text]
  end
  %w(isPreposition isParticiple isAdjective isVerb isAdverb isNoun)
    .each do |x|
    g.at(ns("./#{x}[text() = 'true']")) and ret << @i18n.grammar_abbrevs[x]
  end
  name << ", #{ret.join(', ')}"
end

#designation_localization(desgn, name, orig_desgn) ⇒ Object



162
163
164
165
166
167
168
# File 'lib/isodoc/presentation_function/designations.rb', line 162

def designation_localization(desgn, name, orig_desgn)
  loc = [desgn.at(ns("./expression/@language"))&.text,
         desgn.at(ns("./expression/@script"))&.text,
         orig_desgn.at("./@geographic-area")&.text].compact
  loc.empty? and return
  name << ", #{loc.join(' ')}"
end

#designation_pronunciation(desgn, name) ⇒ Object



170
171
172
173
# File 'lib/isodoc/presentation_function/designations.rb', line 170

def designation_pronunciation(desgn, name)
  f = desgn.at(ns("./expression/pronunciation")) or return
  name << ", /#{to_xml(f.children)}/"
end

#display_comment_override?(_comment) ⇒ Boolean

if false, then decision on displaying comment is only dependent on display_comments_global? . display_comment_override? overrides that

Returns:

  • (Boolean)


174
175
176
# File 'lib/isodoc/presentation_function/footnotes.rb', line 174

def display_comment_override?(_comment)
  false
end

#display_comments_global?(docxml) ⇒ Boolean

Returns:

  • (Boolean)


242
243
244
245
246
# File 'lib/isodoc/presentation_function/footnotes.rb', line 242

def display_comments_global?(docxml)
  m = docxml.at(ns("//presentation-metadata/render-document-annotations"))
  m&.text and return m.text != "false"
  @meta.get[:unpublished]
end

#display_order(docxml) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/isodoc/presentation_function/section.rb', line 99

def display_order(docxml)
  i = 0
  d = @xrefs.clause_order(docxml)
  %i(preface main annex back).each do |s|
    d[s].each do |a|
      i = if a[:multi]
            display_order_xpath(docxml, a[:path], i)
          else display_order_at(docxml, a[:path], i)
          end
    end
  end
end

#display_order_at(docxml, xpath, idx) ⇒ Object



80
81
82
83
84
85
86
87
# File 'lib/isodoc/presentation_function/section.rb', line 80

def display_order_at(docxml, xpath, idx)
  c = docxml.at(ns(xpath)) or return idx
  skip_display_order?(c) and return idx
  idx += 1
  idx = preceding_floating_titles(c, idx)
  c["displayorder"] = idx
  idx
end

#display_order_xpath(docxml, xpath, idx) ⇒ Object



89
90
91
92
93
94
95
96
97
# File 'lib/isodoc/presentation_function/section.rb', line 89

def display_order_xpath(docxml, xpath, idx)
  docxml.xpath(ns(xpath)).each do |c|
    skip_display_order?(c) and next
    idx += 1
    idx = preceding_floating_titles(c, idx)
    c["displayorder"] = idx
  end
  idx
end

#dl(docxml) ⇒ Object



3
4
5
# File 'lib/isodoc/presentation_function/list.rb', line 3

def dl(docxml)
  docxml.xpath(ns("//dl")).each { |f| dl1(f) }
end

#dl1(elem) ⇒ Object



7
8
9
10
# File 'lib/isodoc/presentation_function/list.rb', line 7

def dl1(elem)
  elem.at(ns("./name")) and
    prefix_name(elem, {}, "", "name") # copy name to fmt-name
end

#docid_prefixes(docxml) ⇒ Object



3
4
5
6
7
# File 'lib/isodoc/presentation_function/docid.rb', line 3

def docid_prefixes(docxml)
  docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
    i.children = docid_prefix(i["type"], to_xml(i.children))
  end
end

#document_footnotes(docxml) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/isodoc/presentation_function/footnotes.rb', line 70

def document_footnotes(docxml)
  sects = sort_footnote_sections(docxml)
  excl = non_document_footnotes(docxml)
  fns = filter_document_footnotes(sects, excl)
  fns = renumber_document_footnotes(fns, 1)
  ret = footnote_collect(fns)
  f = footnote_container(fns, ret) and docxml.root << f
end

#edition_integer?(bibdata) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
80
81
# File 'lib/isodoc/presentation_function/bibdata.rb', line 76

def edition_integer?(bibdata)
  x = bibdata.at(ns("./edition[not(@language) or @language = '']"))
  x or return
  /^\d+$/.match?(x.text) or return
  x.text.to_i
end

#edition_translate(bibdata) ⇒ Object

does not allow %Spellout and %Ordinal in the ordinal expression to be mixed



65
66
67
68
69
70
71
72
73
74
# File 'lib/isodoc/presentation_function/bibdata.rb', line 65

def edition_translate(bibdata)
  x = bibdata.at(ns("./edition")) or return
  if @i18n.edition_ordinal && num = edition_integer?(bibdata)
    tag_translate(x, @lang, @i18n
      .populate("edition_ordinal", { "var1" => num }))
  elsif @i18n.edition_cardinal
    tag_translate(x, @lang, @i18n
      .populate("edition_cardinal", { "var1" => x.text }))
  end
end

#emf_encode(img) ⇒ Object



123
124
125
126
127
128
# File 'lib/isodoc/presentation_function/image.rb', line 123

def emf_encode(img)
  svg_prep(img)
  img.children = "<emf src='#{img['src']}'/>"
  img["src"] = ""
  img
end

#emf_to_svg(img) ⇒ Object



136
137
138
139
140
141
142
# File 'lib/isodoc/presentation_function/image.rb', line 136

def emf_to_svg(img)
  datauri_src = img.at(ns("./emf/@src")).text
  Vectory::Emf.from_datauri(datauri_src)
    .to_svg
    .content
    .sub(/<\?[^>]+>/, "")
end

#empty_elements_remove(docxml) ⇒ Object

allow fmt-link to be empty



9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/isodoc/presentation_function/cleanup.rb', line 9

def empty_elements_remove(docxml)
  %w(fmt-name fmt-xref-label fmt-source fmt-xref fmt-eref fmt-origin
     fmt-concept fmt-related fmt-preferred fmt-deprecates
     fmt-admitted fmt-termsource fmt-definition fmt-footnote-container
     fmt-fn-body fmt-fn-label fmt-annotation-body fmt-provision
     fmt-identifier fmt-date).each do |e|
       docxml.xpath(ns("//#{e}")).each do |n|
         n.text.strip.empty? or next
         n.elements.empty? or next
         n.remove
       end
     end
end

#empty_xml?(str) ⇒ Boolean

detect whether string which may contain XML markup is empty

Returns:

  • (Boolean)


137
138
139
140
141
# File 'lib/isodoc/presentation_function/autonum.rb', line 137

def empty_xml?(str)
  str.blank? and return true
  x = Nokogiri::XML::DocumentFragment.parse(str)
  x.to_str.strip.empty?
end

#eps2svg(img) ⇒ Object



101
102
103
104
105
106
107
108
109
# File 'lib/isodoc/presentation_function/image.rb', line 101

def eps2svg(img)
  return unless eps?(img["mimetype"])

  img["mimetype"] = "image/svg+xml"
  if src = eps_to_svg(img)
    img["src"] = src
    img.children = ""
  end
end

#eps_to_svg(node) ⇒ Object



144
145
146
147
148
149
150
151
152
153
# File 'lib/isodoc/presentation_function/image.rb', line 144

def eps_to_svg(node)
  if !node.text.strip.empty? || %r{^data:}.match?(node["src"])
    return eps_to_svg_from_node(node)
  end

  target_path = imgfile_suffix(node["src"], "svg")
  return target_path if File.exist?(target_path)

  eps_to_svg_from_node(node, target_path)
end

#eps_to_svg_from_node(node, target_path = nil) ⇒ Object



155
156
157
158
159
160
# File 'lib/isodoc/presentation_function/image.rb', line 155

def eps_to_svg_from_node(node, target_path = nil)
  svg = Vectory::Eps.from_node(node).to_svg
  return svg.write(target_path).path if target_path

  svg.write.path
end

#eref(docxml) ⇒ Object



49
50
51
52
53
54
55
56
# File 'lib/isodoc/presentation_function/inline.rb', line 49

def eref(docxml)
  docxml.xpath(ns("//eref[@deleteme]")).each { |f| redundant_eref(f) }
  docxml.xpath(ns("//fmt-eref")).each { |f| xref1(f) }
  docxml.xpath(ns("//fmt-eref//fmt-xref")).each do |f|
    f.replace(f.children)
  end
  docxml.xpath(ns("//erefstack")).each { |f| erefstack1(f) }
end


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/isodoc/presentation_function/erefs.rb', line 127

def eref2link(docxml)
  docxml.xpath(ns("//display-text")).each { |f| f.replace(f.children) }
  docxml.xpath(ns("//fmt-eref | //fmt-origin[not(.//termref)]"))
    .each do |e|
    sem_xml_descendant?(e) and next
    href = eref_target(e) or next
    e.xpath(ns("./locality | ./localityStack")).each(&:remove)
    if %w(short).include?(e["style"])
      eref2linkshort(e, href)
    elsif href[:type] == :anchor || %w(full).include?(e["style"])
      eref2xref(e)
    else eref2link1(e, href)
    end
  end
end

#eref2link1(node, href) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/isodoc/presentation_function/erefs.rb', line 151

def eref2link1(node, href)
  url = href[:link]
  att = href[:type] == :attachment ? "attachment='true'" : ""
  repl = "<fmt-link #{att} target='#{url}'>#{to_xml(node.children)}</link>"
  node["type"] == "footnote" and repl = "<sup>#{repl}</sup>"
  node.replace(repl)
end

#eref2linkshort(node, _href) ⇒ Object



159
160
161
162
163
164
165
# File 'lib/isodoc/presentation_function/erefs.rb', line 159

def eref2linkshort(node, _href)
  node.at(ns("./span[@class = 'fmt-first-biblio-delim']")) or
    return eref2xref(node)
  node.children = <<~XML
    <fmt-xref target='#{node['bibitemid']}'>#{to_xml(node.children).sub('<span class="fmt-first-biblio-delim"/>', '</fmt-xref>')}
  XML
end

#eref2xref(node) ⇒ Object



143
144
145
146
147
148
149
# File 'lib/isodoc/presentation_function/erefs.rb', line 143

def eref2xref(node)
  node.name = "fmt-xref"
  node["target"] = node["bibitemid"]
  node.delete("bibitemid")
  node.delete("citeas")
  node["type"] == "footnote" and node.wrap("<sup></sup>")
end

#eref_localities(refs, target, node) ⇒ Object



3
4
5
6
7
8
9
10
11
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 3

def eref_localities(refs, target, node)
  if can_conflate_eref_rendering?(refs)
    l10n(", #{esc(eref_localities_conflated(refs, target, node))}"
      .gsub(/\s+/, " "), @lang, @script, { prev: target })
  else
    ret = resolve_eref_connectives(eref_locality_stacks(refs, target, node))
    l10n(ret.join.gsub(/\s+/, " "), @lang, @script, { prev: target })
  end
end

#eref_localities0(ref, _idx, target, node) ⇒ Object



79
80
81
82
83
84
85
86
87
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 79

def eref_localities0(ref, _idx, target, node)
  if ref["type"] == "whole" then @i18n.wholeoftext
  else
    eref_localities1({ target:, type: ref["type"], number: "sg",
                       from: ref.at(ns("./referenceFrom"))&.text,
                       upto: ref.at(ns("./referenceTo"))&.text, node:,
                       lang: @lang })
  end
end

#eref_localities1(opt) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 99

def eref_localities1(opt)
  opt[:type] == "anchor" and return nil
  # %(zh ja ko).include?(opt[:lang]) and
  # return l10n(eref_localities1_zh(opt))
  ret = eref_locality_populate(opt[:type], opt[:node], opt[:number])
  ret += " <esc>#{opt[:from]}</esc>" if opt[:from]
  ret += "&#x2013;<esc>#{opt[:upto]}</esc>" if opt[:upto]
  l10n(ret)
end

#eref_localities1_zh(opt) ⇒ Object

Suspended, this is an ordinal that GB asked for, not applicable for non-integers, and not desired for JIS



91
92
93
94
95
96
97
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 91

def eref_localities1_zh(opt)
  ret = "#{esc opt[:from]}" if opt[:from]
  ret += "&#x2013;#{esc opt[:upto]}" if opt[:upto]
  loc = eref_locality_populate(opt[:type], opt[:node], "sg")
  ret += " #{loc}" unless opt[:node]["droploc"] == "true"
  ret
end

#eref_localities_conflated(refs, target, node) ⇒ Object



13
14
15
16
17
18
19
20
21
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 13

def eref_localities_conflated(refs, target, node)
  droploc = node["droploc"]
  node["droploc"] = true
  ret = resolve_eref_connectives(eref_locality_stacks(refs, target, node))
  node.delete("droploc") unless droploc
  eref_localities1({ target:, number: "pl",
                     type: refs.first.at(ns("./locality/@type")).text,
                     from: l10n(ret[1..].join), node:, lang: @lang })
end

#eref_locality_delimiter(ref) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 43

def eref_locality_delimiter(ref)
  if ref&.next_element&.name == "localityStack"
    { conn: ref.next_element["connective"],
      custom: ref.next_element["custom-connective"] }
  else locality_delimiter(ref)
  end
end

#eref_locality_populate(type, node, number) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 109

def eref_locality_populate(type, node, number)
  node["droploc"] == "true" and return ""
  loc = type.sub(/^locality:/, "")
  ret = @i18n.locality[loc] || loc
  number == "pl" and ret = @i18n.inflect(ret, number: "pl")
  ret = case node["case"]
        when "lowercase" then ret.downcase
        else Metanorma::Utils.strict_capitalize_first(ret)
        end
  " #{ret}"
end

#eref_locality_stack(ref, idx, target, node) ⇒ Object



51
52
53
54
55
56
57
58
59
60
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 51

def eref_locality_stack(ref, idx, target, node)
  ret = []
  if ref.name == "localityStack"
    ret = eref_locality_stack1(ref, target, node, ret)
  else
    l = eref_localities0(ref, idx, target, node) and ret << { ref: l }
  end
  ret[-1] && ret[-1][:conn] == ", " and ret.pop
  ret
end

#eref_locality_stack1(ref, target, node, ret) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 62

def eref_locality_stack1(ref, target, node, ret)
  if ref["connective"] == "from" && ref["custom-connective"]
    # TODO deal better with languages with mandatory from connective
    ret << { conn: "from", custom: ref["custom-connective"] }
  end
  ref.elements.each_with_index do |rr, j|
    l = eref_localities0(rr, j, target, node) or next
    ret << { ref: l }
    ret << locality_delimiter(rr) unless j == ref.elements.size - 1
  end
  ret
end

#eref_locality_stacks(refs, target, node) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 31

def eref_locality_stacks(refs, target, node)
  ret = refs.each_with_index.with_object([]) do |(r, i), m|
    added = eref_locality_stack(r, i, target, node)
    added.empty? and next
    added.each { |a| m << a }
    i == refs.size - 1 and next
    m << eref_locality_delimiter(r)
  end
  ret[-1] && ret[-1][:conn] == ", " and ret.pop
  ret.empty? ? ret : [{ conn: ", " }] + ret
end

#eref_target(node) ⇒ Object



173
174
175
176
177
178
179
# File 'lib/isodoc/presentation_function/erefs.rb', line 173

def eref_target(node)
  u = eref_url(node["bibitemid"]) or return nil
  url = suffix_url(u[:link])
  anchor = node.at(ns(".//locality[@type = 'anchor']"))
  /^#/.match?(url) || !anchor and return { link: url, type: u[:type] }
  { link: "#{url}##{anchor.text.strip}", type: u[:type] }
end

#eref_url(id) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/isodoc/presentation_function/erefs.rb', line 186

def eref_url(id)
  b = eref_url_prep(id) or return nil
  %i(attachment citation).each do |x|
    u = b.at(ns("./uri[@type = '#{x}'][@language = '#{@lang}']")) ||
      b.at(ns("./uri[@type = '#{x}']")) and return { link: u.text, type: x }
  end
  if b["hidden"] == "true"
    u = b.at(ns("./uri")) or return nil
    { link: u.text, type: :citation }
  else { link: "##{id}", type: :anchor }
  end
end

#eref_url_prep(id) ⇒ Object



181
182
183
184
# File 'lib/isodoc/presentation_function/erefs.rb', line 181

def eref_url_prep(id)
  @bibitem_lookup.nil? and return nil
  @bibitem_lookup[id]
end

#erefstack1(elem) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/isodoc/presentation_function/erefs.rb', line 33

def erefstack1(elem)
  locs = elem.xpath(ns("./semx/fmt-eref")).map do |e|
    [{ conn: e["connective"], custom: e["custom-connective"] },
     { ref: to_xml(e.parent.remove) }]
  end.flatten
  ret = resolve_eref_connectives(locs)
  elem.next = <<~XML
    <semx element='erefstack' source='#{elem['id']}'>#{l10n ret[1]}</semx>
  XML
end

#esc(text) ⇒ Object



170
171
172
173
# File 'lib/isodoc/presentation_function/autonum.rb', line 170

def esc(text)
  text.nil? || text.empty? and return text
  "<esc>#{text}</esc>"
end

#esc_origin(element) ⇒ Object



151
152
153
154
155
# File 'lib/isodoc/presentation_function/terms.rb', line 151

def esc_origin(element)
  element.xpath(ns(".//origin")).each do |origin|
    origin.wrap("<esc></esc>")
  end
end

#escape_l10n(locs) ⇒ Object



78
79
80
81
82
# File 'lib/isodoc/presentation_function/erefs.rb', line 78

def escape_l10n(locs)
  locs.map do |x|
    x[:conn] ? x : { ref: esc(x[:ref]) }
  end
end

#example(docxml) ⇒ Object



41
42
43
# File 'lib/isodoc/presentation_function/block.rb', line 41

def example(docxml)
  docxml.xpath(ns("//example")).each { |f| example1(f) }
end

#example1(elem) ⇒ Object



45
46
47
48
49
50
# File 'lib/isodoc/presentation_function/block.rb', line 45

def example1(elem)
  n = @xrefs.get[elem["id"]] || @xrefs.get[elem["original-id"]]
  lbl = labelled_autonum(@i18n.example, elem["id"] || elem["original-id"],
                         n&.dig(:label))
  prefix_name(elem, { caption: block_delim }, lbl, "name")
end

#expand_citeas(text) ⇒ Object



28
29
30
31
# File 'lib/isodoc/presentation_function/erefs.rb', line 28

def expand_citeas(text)
  text.nil? and return text
  HTMLEntities.new.decode(text.gsub("&amp;#x", "&#"))
end

#explicit_number_formatter(num, locale, options) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/isodoc/presentation_function/math.rb', line 68

def explicit_number_formatter(num, locale, options)
  ret = numberformat_type(csv_attribute_extract(options))
  l = ret[:locale] || locale
  precision, symbols, significant = explicit_number_formatter_cfg(num, ret)
  n = normalise_number(num.text)
  Plurimath::NumberFormatter.new(l)
    .localized_number(n, precision:,
                         format: symbols.merge(significant:))
end

#explicit_number_formatter_cfg(num, fmt) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/isodoc/presentation_function/math.rb', line 78

def explicit_number_formatter_cfg(num, fmt)
  symbols = twitter_cldr_localiser_symbols.dup.transform_values do |v|
    v.is_a?(String) ? HTMLEntities.new.decode(v) : v
  end.merge(fmt)
  symbols = large_notation_fmt(symbols, num.text)
  significant = explicit_number_formatter_signif(num, symbols)
  precision = symbols[:precision] || num_precision(num.text) ||
    num_precision_from_significant(num.text, significant,
                                   (symbols[:base] || 10).to_i)
  [precision, symbols, significant]
end

#explicit_number_formatter_signif(num, symbols) ⇒ Object



90
91
92
93
94
95
# File 'lib/isodoc/presentation_function/math.rb', line 90

def explicit_number_formatter_signif(num, symbols)
  signif = symbols[:significant]
  (symbols.keys & %i(precision digit_count)).empty? and
    signif ||= num_totaldigits(num.text, (symbols[:base] || 10).to_i)
  signif
end

#extension_insert(xml, path = []) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/isodoc/presentation_function/metadata.rb', line 77

def extension_insert(xml, path = [])
  ins = extension_insert_pt(xml)
  path.each do |n|
    ins = ins.at(ns("./#{n}")) || ins.add_child("<#{n}/>").first
  end
  ins
end

#extension_insert_pt(xml) ⇒ Object



85
86
87
88
89
90
91
92
93
# File 'lib/isodoc/presentation_function/metadata.rb', line 85

def extension_insert_pt(xml)
  xml.at(ns("//metanorma-extension")) ||
    xml.at(ns("//bibdata"))
      &.after("<metanorma-extension> </metanorma-extension>")
      &.next_element ||
    xml.root.elements.first
      .before("<metanorma-extension> </metanorma-extension>")
      .previous_element
end

#extract_custom_charsets(docxml) ⇒ Object



186
187
188
189
190
191
192
193
194
# File 'lib/isodoc/presentation_function/inline.rb', line 186

def extract_custom_charsets(docxml)
  docxml.xpath(ns("//presentation-metadata/custom-charset-font"))
    .each_with_object({}) do |line, m|
    line.text.split(",").map(&:strip).each do |x|
      kv = x.split(":", 2)
      m[kv[0]] = kv[1]
    end
  end
end

#extract_indexsee(val, terms, label) ⇒ Object



125
126
127
128
129
130
131
132
# File 'lib/isodoc/presentation_function/index.rb', line 125

def extract_indexsee(val, terms, label)
  terms.each_with_object(val) do |t, v|
    term, term2, term3 = extract_indexterms_init(t)
    term_hash_init(v, term, term2, term3, label)
    v[term][term2][term3][label] << to_xml(t.at(ns("./target"))&.children)
    t.remove
  end
end

#extract_indexterms(terms) ⇒ Object

attributes are decoded into UTF-8, elements in extract_indexsee are still in entities



143
144
145
146
147
148
149
150
151
152
# File 'lib/isodoc/presentation_function/index.rb', line 143

def extract_indexterms(terms)
  terms.each_with_object({}) do |t, v|
    term, term2, term3 = extract_indexterms_init(t)
    to = t["to"] ? "to='#{t['to']}' " : ""
    index2bookmark(t)
    term_hash_init(v, term, term2, term3, :xref)
    v[term][term2][term3][:xref] << "<xref target='#{t['id']}' " \
                                    "#{to}pagenumber='true'/>"
  end
end

#extract_indexterms_init(term) ⇒ Object



154
155
156
157
158
# File 'lib/isodoc/presentation_function/index.rb', line 154

def extract_indexterms_init(term)
  %w(primary secondary tertiary).each_with_object([]) do |x, m|
    m << to_xml(term.at(ns("./#{x}"))&.children)
  end
end

#figure(docxml) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/isodoc/presentation_function/image.rb', line 7

def figure(docxml)
  docxml.xpath("//m:svg", SVG).each { |f| svg_wrap(f) }
  docxml.xpath(ns("//image")).each { |f| svg_extract(f) }
  docxml.xpath(ns("//figure")).each { |f| figure1(f) }
  docxml.xpath(ns("//svgmap")).each { |s| svgmap_extract(s) }
  imageconvert(docxml)
  docxml.xpath("//m:svg", SVG).each { |f| svg_scale(f) }
end

#figure1(elem) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/isodoc/presentation_function/image.rb', line 69

def figure1(elem)
  elem["class"] == "pseudocode" || elem["type"] == "pseudocode" and
    return sourcecode1(elem)
  figure_fn(elem)
  figure_key(elem.at(ns("./key")))
  lbl = @xrefs.anchor(elem["id"] || elem["original-id"], :label, false)
  lbl and a = autonum(elem["id"] || elem["original-id"], lbl)
  figname = figure_name(elem)
  elem.at("./ancestor::xmlns:figure") && a and
    a += subfigure_delim
  lbl && figure_label?(elem) and s = "#{figname}#{a}"
  prefix_name(elem, { caption: figure_delim(elem) }, l10n(s&.strip), "name")
end

#figure_delim(_elem) ⇒ Object



61
62
63
# File 'lib/isodoc/presentation_function/image.rb', line 61

def figure_delim(_elem)
  block_delim
end

#figure_fn(elem) ⇒ Object

move footnotes into key



139
140
141
142
143
144
145
146
147
148
# File 'lib/isodoc/presentation_function/footnotes.rb', line 139

def figure_fn(elem)
  fn = elem.xpath(ns(".//fn")) - elem.xpath(ns("./name//fn")) -
    elem.xpath(ns("./fmt-name//fn"))
  fn.empty? and return
  dl = figure_key_insert_pt(elem)
  footnote_collect(fn).each do |f|
    label, fbody = figure_fn_to_dt_dd(f)
    dl.previous = "<dt><p>#{to_xml(label)}</p></dt><dd>#{to_xml(fbody)}</dd>"
  end
end

#figure_fn_to_dt_dd(fnote) ⇒ Object



150
151
152
153
154
# File 'lib/isodoc/presentation_function/footnotes.rb', line 150

def figure_fn_to_dt_dd(fnote)
  label = fnote.at(ns(".//fmt-fn-label")).remove
  label.at(ns(".//span[@class = 'fmt-caption-delim']"))&.remove
  [label, fnote]
end

#figure_footnotes(docxml) ⇒ Object



100
101
102
103
104
# File 'lib/isodoc/presentation_function/footnotes.rb', line 100

def figure_footnotes(docxml)
  docxml.xpath(ns("//figure//fn")) -
    docxml.xpath(ns("//figure/name//fn")) -
    docxml.xpath(ns("//figure/fmt-name//fn"))
end

#figure_key(dlist) ⇒ Object



94
95
96
97
98
99
# File 'lib/isodoc/presentation_function/image.rb', line 94

def figure_key(dlist)
  dlist or return
  dlist["class"] = "formula_dl"
  dlist.at(ns("./name")) and return
  dlist.children.first.previous = "<name>#{@i18n.key}</name>"
end

#figure_key_insert_pt(elem) ⇒ Object



156
157
158
159
160
161
# File 'lib/isodoc/presentation_function/footnotes.rb', line 156

def figure_key_insert_pt(elem)
  elem.at(ns(".//dl/name"))&.next ||
    elem.at(ns(".//dl"))&.children&.first ||
    elem.add_child("<key><dl> </dl></key>")
      .first.elements.first.children.first
end

#figure_label(elem) ⇒ Object



88
89
90
91
92
# File 'lib/isodoc/presentation_function/image.rb', line 88

def figure_label(elem)
  klass = elem["class"] || "figure"
  klasslbl = @i18n.get[klass] || klass
  lower2cap klasslbl
end

#figure_label?(elem) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
86
# File 'lib/isodoc/presentation_function/image.rb', line 83

def figure_label?(elem)
  elem.at(ns("./figure")) && !elem.at(ns("./name")) and return false
  true
end

#figure_name(elem) ⇒ Object



65
66
67
# File 'lib/isodoc/presentation_function/image.rb', line 65

def figure_name(elem)
  "<span class='fmt-element-name'>#{figure_label(elem)}</span> "
end

#figuresource(elem) ⇒ Object



34
35
36
# File 'lib/isodoc/presentation_function/source.rb', line 34

def figuresource(elem)
  source1(elem, :figure)
end

#filter_document_footnotes(sects, excl) ⇒ Object



106
107
108
109
110
111
# File 'lib/isodoc/presentation_function/footnotes.rb', line 106

def filter_document_footnotes(sects, excl)
  sects.each_with_object([]) do |s, m|
    docfns = s.xpath(ns(".//fn")) - excl
    m << docfns
  end
end

#floattitle(docxml) ⇒ Object



35
36
37
# File 'lib/isodoc/presentation_function/title.rb', line 35

def floattitle(docxml)
  docxml.xpath(ns(".//floating-title")).each { |f| floattitle1(f) }
end

#floattitle1(elem) ⇒ Object

TODO not currently doing anything with the @depth attribute of floating-title



40
41
42
43
44
45
46
47
48
# File 'lib/isodoc/presentation_function/title.rb', line 40

def floattitle1(elem)
  p = elem.dup
  p.children = "<semx element='floating-title' source='#{elem['id']}'>" \
    "#{to_xml(p.children)}</semx>"
  elem.next = p
  p.name = "p"
  p["type"] = "floating-title"
  transfer_id(elem, p)
end

#fmt_caption(label, elem, name, ids, delims) ⇒ Object

Remove “.blank?” tests if want empty delim placeholders for manipulation



144
145
146
147
148
149
150
151
# File 'lib/isodoc/presentation_function/autonum.rb', line 144

def fmt_caption(label, elem, name, ids, delims)
  label = fmt_caption_label_wrap(label)
  c = fmt_caption2(label, elem, name, ids, delims)
  empty_xml?(c) and return
  !delims[:label].blank? and
    f = "<span class='fmt-label-delim'>#{delims[:label]}</span>"
  "<fmt-#{elem}>#{c}#{f}</fmt-#{elem}>"
end

#fmt_caption2(label, elem, name, ids, delims) ⇒ Object



160
161
162
163
164
165
166
167
168
# File 'lib/isodoc/presentation_function/autonum.rb', line 160

def fmt_caption2(label, elem, name, ids, delims)
  if name && !name.children.empty?
    empty_xml?(label) or
      d = "<span class='fmt-caption-delim'>#{delims[:caption]}</span>"
    attr = " element='#{elem}' source='#{ids[:name]}'"
    "#{label}#{d}<semx #{attr}>#{to_xml(name.children)}</semx>"
  elsif label then label
  end
end

#fmt_caption_label_wrap(label) ⇒ Object



153
154
155
156
157
158
# File 'lib/isodoc/presentation_function/autonum.rb', line 153

def fmt_caption_label_wrap(label)
  empty_xml?(label) ||
    %r{<span class=['"]fmt-caption-label['"]}.match?(label) or
    label = "<span class='fmt-caption-label'>#{label}</span>"
  label
end

#fmt_ref(docxml) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
# File 'lib/isodoc/presentation_function/xrefs.rb', line 3

def fmt_ref(docxml)
  docxml.xpath(ns("//xref | //eref | //origin | //link")).each do |x|
    sem_xml_descendant?(x) and next
    tag = x.name
    y = Nokogiri::XML::Node.new("fmt-#{tag}", x.document)
    x.attributes.keys.reject { |a| a == "id" }.each { |a| y[a] = x[a] }
    n = semx_fmt_dup(x) # semx/fmt-xref for ease of processing
    n.children.each { |c| y << c }
    n << y
    x.next = n
  end
end

#fmt_source(docxml) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'lib/isodoc/presentation_function/source.rb', line 20

def fmt_source(docxml)
  n = docxml.xpath(ns("//source")) - docxml.xpath(ns("//term//source")) -
    docxml.xpath(ns("//quote/source"))
  n.each do |s|
    dup = s.clone
    modification_dup_align(s, dup)
    s.next = "<fmt-source>#{to_xml(dup)}</fmt-source>"
  end
end

#fmt_sourcecode(elem, ret1) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 62

def fmt_sourcecode(elem, ret1)
  ret = Nokogiri::XML::Node.new("fmt-#{elem.name}", elem.document)
  elem.attributes.each_key { |x| x != "id" and ret[x] = elem[x] }
  ret1.xpath(ns("./name")).each(&:remove)
  ret << ret1.children
  elem << ret
end

#fmt_xref_label(label, _number, ids) ⇒ Object



104
105
106
107
108
109
110
111
112
113
# File 'lib/isodoc/presentation_function/autonum.rb', line 104

def fmt_xref_label(label, _number, ids)
  label or return ""
  x = @xrefs.anchor(ids[:elem], :xref, false) or return ""
  ret = "<fmt-xref-label>#{x}</fmt-xref-label>"
  container = @xrefs.anchor(ids[:elem], :container, false)
  y = prefix_container_fmt_xref_label(container, x)
  y != x and
    ret += "<fmt-xref-label container='#{container}'>#{y}</fmt-xref-label>"
  ret
end

#fn_body_label(fnote) ⇒ Object



53
54
55
# File 'lib/isodoc/presentation_function/footnotes.rb', line 53

def fn_body_label(fnote)
  "<sup>#{fn_label(fnote)}</sup>"
end

#fn_label(fnote) ⇒ Object



57
58
59
60
61
# File 'lib/isodoc/presentation_function/footnotes.rb', line 57

def fn_label(fnote)
  <<~FNOTE.strip
    <semx element="autonum" source="#{fnote['id']}">#{fnote['reference']}</semx>
  FNOTE
end

#fn_ref_label(fnote) ⇒ Object



49
50
51
# File 'lib/isodoc/presentation_function/footnotes.rb', line 49

def fn_ref_label(fnote)
  "<sup>#{fn_label(fnote)}</sup>"
end

#fnbody(fnote, seen) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/isodoc/presentation_function/footnotes.rb', line 24

def fnbody(fnote, seen)
  add_fnbody?(fnote, seen) or return nil
  body = Nokogiri::XML::Node.new("fmt-fn-body", fnote.document)
  add_id(body)
  body["target"] = fnote["id"]
  body["reference"] = fnote["reference"]
  body << semx_fmt_dup(fnote)
  insert_fn_body_ref(fnote, body)
  seen[fnote["reference"]] = body["id"]
  body
end

#fonts_metadata(xmldoc) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/isodoc/presentation_function/metadata.rb', line 107

def (xmldoc)
  @fontlicenseagreement || @fontist_fonts or return
  ins = presmeta_insert_pt(xmldoc)
  @fontlicenseagreement and
    ins.add_child(presmeta("font-license-agreement", @fontlicenseagreement))
  @fontist_fonts and CSV.parse_line(@fontist_fonts, col_sep: ";").compact
    .map(&:strip).reject(&:empty?).each do |f|
    ins.add_child(presmeta("fonts", f))
  end
end

#footnote_collect(fnotes) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
14
# File 'lib/isodoc/presentation_function/footnotes.rb', line 3

def footnote_collect(fnotes)
  seen = {}
  fnotes.each_with_object([]) do |x, m|
    x["reference"] or next # ignore semx-only footnotes
    b = fnbody(x, seen) and m << b
    x["target"] = seen[x["reference"]]
    ref = x["hiddenref"] == "true" ? "" : fn_ref_label(x)
    x << <<~FNOTE.strip
      <fmt-fn-label><span class='fmt-caption-label'>#{ref}</span</fmt-fn-label>
    FNOTE
  end
end

#footnote_container(fnotes, fnbodies) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/isodoc/presentation_function/footnotes.rb', line 16

def footnote_container(fnotes, fnbodies)
  fnbodies.empty? and return
  ctr = Nokogiri::XML::Node.new("fmt-footnote-container",
                                fnotes.first.document)
  fnbodies.each { |x| ctr << x }
  ctr
end

#formula(docxml) ⇒ Object



22
23
24
# File 'lib/isodoc/presentation_function/block.rb', line 22

def formula(docxml)
  docxml.xpath(ns("//formula")).each { |f| formula1(f) }
end

#formula1(elem) ⇒ Object



26
27
28
29
30
31
32
# File 'lib/isodoc/presentation_function/block.rb', line 26

def formula1(elem)
  dl = elem.at(ns("./dl")) and dl.replace("<key>#{to_xml(dl)}</key>")
  formula_where(elem.at(ns("./key")))
  lbl = @xrefs.anchor(elem["id"], :label, false) ||
    @xrefs.anchor(elem["original-id"], :label, false)
  lbl.nil? || lbl.empty? or prefix_name(elem, {}, lbl, "name")
end

#formula_where(dlist) ⇒ Object



34
35
36
37
38
39
# File 'lib/isodoc/presentation_function/block.rb', line 34

def formula_where(dlist)
  dlist or return
  dlist["class"] = "formula_dl"
  where = dlist.xpath(ns(".//dt")).size > 1 ? @i18n.where : @i18n.where_one
  dlist.previous = "<p keep-with-next='true'>#{where}</p>"
end

#gather_all_ids(elem) ⇒ Object



62
63
64
65
66
# File 'lib/isodoc/presentation_function/autonum.rb', line 62

def gather_all_ids(elem)
  elem.xpath(".//*[@id]").each_with_object([]) do |i, m|
    m << i["id"]
  end
end

#gather_xref_locations(node) ⇒ Object



135
136
137
138
139
140
141
142
143
144
# File 'lib/isodoc/presentation_function/xrefs.rb', line 135

def gather_xref_locations(node)
  node.xpath(ns("./location")).each_with_object([]) do |l, m|
    type = @xrefs.anchor(l["target"], :type)
    m << { conn: l["connective"], custom: l["custom-connective"],
           target: l["target"],
           type:, node: l, elem: @xrefs.anchor(l["target"], :elem),
           container: @xrefs.anchor(l["target"], :container, false) ||
             %w(termnote).include?(type) }
  end
end

#get_linkend(node) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/isodoc/presentation_function/inline.rb', line 12

def get_linkend(node)
  node["style"] == "id" and anchor_id_postprocess(node)
  xref_empty?(node) or return
  target = docid_l10n(node["target"]) ||
    docid_l10n(expand_citeas(node["citeas"]))
  link = anchor_linkend(node, target)
  link += eref_localities(node.xpath(ns("./locality | ./localityStack")),
                          link, node)
  non_locality_elems(node).each(&:remove)
  node.add_child(cleanup_entities(link))
  unnest_linkend(node)
end

#hash_translate(bibdata, hash, dest_xpath, alt_source_xpath, lang) ⇒ Object

translate dest_xpath in bibdata using lookup in hash source text is dest_xpath by default, can be alt_source_xpath if given



54
55
56
57
58
59
60
61
# File 'lib/isodoc/presentation_function/bibdata.rb', line 54

def hash_translate(bibdata, hash, dest_xpath, alt_source_xpath, lang)
  hash.is_a? Hash or return
  x = bibdata.xpath(ns(dest_xpath))
  alt_source_xpath and alt_x = bibdata.at(ns(alt_source_xpath))&.text
  x.each do |d|
    v = hash[alt_x || d.text] and tag_translate(d, lang, v)
  end
end

#hidden_items(docxml) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/isodoc/presentation_function/section_refs.rb', line 45

def hidden_items(docxml)
  docxml.xpath(ns("//references[bibitem/@hidden = 'true']")).each do |x|
    x.at(ns("./bibitem[not(@hidden = 'true')]")) and next
    x.elements.map(&:name).any? do |n|
      !%w(title bibitem).include?(n)
    end and next
    x["hidden"] = "true"
  end
end

#i18n_chain_boolean(value, entry) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/isodoc/presentation_function/xrefs.rb', line 181

def i18n_chain_boolean(value, entry)
  ret = @i18n.send("chain_#{entry[:conn]}")
    .sub("%1", value)
    .sub("%2", loc2xref(entry))
  c = entry[:custom] and ret = conn_sub(ret, c)
  connectives_spans(ret)
end

#i18n_name(hash, pref, lang) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/isodoc/presentation_function/metadata.rb', line 138

def i18n_name(hash, pref, lang)
  case hash
  when Hash then i18n_name1(hash, pref, lang)
  when Array
    hash.reject { |a| blank?(a) }.each_with_object([])
      .with_index do |(v1, g), i|
        i18n_name(v1, "#{i18n_safe(k)}.#{i}", lang).each { |x| g << x }
      end
  else [i18n_tag(pref, hash, lang)]
  end
end

#i18n_name1(hash, pref, lang) ⇒ Object



150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/isodoc/presentation_function/metadata.rb', line 150

def i18n_name1(hash, pref, lang)
  hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
    case v
    when Hash then i18n_name(v, i18n_safe(k), lang).each { |x| g << x }
    when Array
      v.reject { |a| blank?(a) }.each_with_index do |v1, i|
        i18n_name(v1, "#{i18n_safe(k)}.#{i}", lang).each { |x| g << x }
      end
    else
      g << i18n_tag("#{pref}#{pref.empty? ? '' : '.'}#{i18n_safe(k)}", v,
                    lang)
    end
  end
end

#i18n_safe(key) ⇒ Object



134
135
136
# File 'lib/isodoc/presentation_function/metadata.rb', line 134

def i18n_safe(key)
  key.to_s.gsub(/\s|\./, "_")
end

#i18n_tag(key, value, lang) ⇒ Object



129
130
131
132
# File 'lib/isodoc/presentation_function/metadata.rb', line 129

def i18n_tag(key, value, lang)
  "<localized-string key='#{key}' language='#{lang}'>#{value}" \
    "</localized-string>"
end

#id_validate(docxml) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/isodoc/presentation_function/ids.rb', line 16

def id_validate(docxml)
  add_missing_presxml_id(docxml)
  repeat_id_validate(docxml) # feeds orig_id_cleanup
  orig_id_cleanup(docxml)
  idref_validate(docxml)
  contenthash_id_cleanup(docxml)
end

#ident_fn(bib) ⇒ Object



198
199
200
201
# File 'lib/isodoc/presentation_function/refs.rb', line 198

def ident_fn(bib)
  ret = bib.at(ns("./docidentifier//fn")) or return ""
  to_xml(ret.remove)
end

#identifier(docxml) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/isodoc/presentation_function/inline.rb', line 98

def identifier(docxml)
  docxml.xpath(ns("//identifier")).each do |n|
    %w(bibdata bibitem requirement recommendation permission)
      .include?(n.parent.name) and next
    s = semx_fmt_dup(n)
    n.next = "<fmt-identifier><tt>#{to_xml(s)}</tt></fmt-identifier>"
  end
end

#idref_validate(doc) ⇒ Object



60
61
62
63
64
65
66
67
# File 'lib/isodoc/presentation_function/ids.rb', line 60

def idref_validate(doc)
  @log or return
  Metanorma::Utils::anchor_attributes(presxml: true).each do |e|
    doc.xpath("//xmlns:#{e[0]}[@#{e[1]}]").each do |x|
      idref_validate1(x, e[1])
    end
  end
end

#idref_validate1(node, attr) ⇒ Object



69
70
71
72
73
74
# File 'lib/isodoc/presentation_function/ids.rb', line 69

def idref_validate1(node, attr)
  node[attr].strip.empty? and return
  @doc_ids[node[attr]] and return
  @doc_orig_ids[node[attr]] and return
  @log.add("ISODOC_1", node, params: [node[attr], node.name])
end

#imageconvert(docxml) ⇒ Object



38
39
40
41
42
43
# File 'lib/isodoc/presentation_function/image.rb', line 38

def imageconvert(docxml)
  docxml.xpath(ns("//image")).each do |f|
    eps2svg(f)
    svg_emf_double(f)
  end
end

#implicit_number_formatter(num, locale) ⇒ Object



44
45
46
47
48
49
50
51
# File 'lib/isodoc/presentation_function/math.rb', line 44

def implicit_number_formatter(num, locale)
  num.ancestors("formula").empty? or return
  ## by default, no formatting in formulas
  fmt = { significant: num_totaldigits(num.text, 10) }.compact
  n = normalise_number(num.text)
  @numfmt.localized_number(n, locale:, format: fmt,
                              precision: num_precision(num.text))
end

#implicit_reference(bib) ⇒ Object

reference not to be rendered because it is deemed implicit in the standards environment



205
206
207
# File 'lib/isodoc/presentation_function/refs.rb', line 205

def implicit_reference(bib)
  bib["hidden"] == "true"
end

#index(xml) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/isodoc/presentation_function/index.rb', line 7

def index(xml)
  if xml.at(ns("//index"))
    i = xml.at(ns("//indexsect")) ||
      xml.root.add_child(
        "<indexsect #{add_id_text}>" \
         "<fmt-title #{add_id_text}>#{@i18n.index}</fmt-title></indexsect>",
      ).first
    index = sort_indexterms(xml.xpath(ns("//index")),
                            xml.xpath(ns("//index-xref[@also = 'false']")),
                            xml.xpath(ns("//index-xref[@also = 'true']")))
    index1(xml, i, index)
  else strip_index(xml)
  end
end

#index1(docxml, indexsect, index) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/isodoc/presentation_function/index.rb', line 22

def index1(docxml, indexsect, index)
  c = indexsect.add_child("<ul></ul>").first
  index.keys.sort.each do |k|
    words = index[k].keys.each_with_object({}) do |w, v|
      v[sortable(w).downcase] = w
    end
    words.keys.localize(@lang.to_sym).sort.to_a.each do |w|
      c.add_child index_entries(words, index[k], w)
    end
  end
  index1_cleanup(docxml)
end

#index1_cleanup(docxml) ⇒ Object



35
36
37
38
39
40
# File 'lib/isodoc/presentation_function/index.rb', line 35

def index1_cleanup(docxml)
  docxml.xpath(ns("//indexsect//xref")).each do |x|
    x.children.remove
  end
  @xrefs.bookmark_anchor_names(docxml)
end

#index2bookmark(node) ⇒ Object



167
168
169
170
171
172
# File 'lib/isodoc/presentation_function/index.rb', line 167

def index2bookmark(node)
  node.name = "bookmark"
  node.children.each(&:remove)
  add_id(node)
  node.delete("to")
end

#index_entries(words, index, primary) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/isodoc/presentation_function/index.rb', line 51

def index_entries(words, index, primary)
  ret = index_entries_head(words[primary],
                           index.dig(words[primary], nil, nil),
                           index_entries_opt)
  words2 = index[words[primary]]&.keys&.compact
    &.each_with_object({}) { |w, v| v[w.downcase] = w }
  unless words2.empty?
    ret += "<ul>"
    words2.keys.localize(@lang.to_sym).sort.to_a.each do |w|
      ret += index_entries2(words2, index[words[primary]], w)
    end
    ret += "</ul>"
  end
  "#{ret}</li>"
end

#index_entries2(words, index, secondary) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/isodoc/presentation_function/index.rb', line 67

def index_entries2(words, index, secondary)
  ret = index_entries_head(words[secondary],
                           index.dig(words[secondary], nil),
                           index_entries_opt)
  words3 = index[words[secondary]]&.keys&.compact
    &.each_with_object({}) { |w, v| v[w.downcase] = w }
  unless words3.empty?
    ret += "<ul>"
    words3.keys.localize(@lang.to_sym).sort.to_a.each do |w|
      ret += (index_entries_head(words3[w],
                                 index[words[secondary]][words3[w]],
                                 index_entries_opt) + "</li>")
    end
    ret += "</ul>"
  end
  "#{ret}</li>"
end

#index_entries_head(head, entries, opt) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/isodoc/presentation_function/index.rb', line 85

def index_entries_head(head, entries, opt)
  ret = "<li #{add_id_text}>#{head}"
  xref = entries&.dig(:xref)&.join(", ")
  see = index_entries_see(entries, :see)
  also = index_entries_see(entries, :also)
  ret += "#{opt[:xref_lbl]} #{xref}" if xref
  ret += "#{opt[:see_lbl]} #{see}" if see
  ret += "#{opt[:also_lbl]} #{also}" if also
  ret
end

#index_entries_optObject



47
48
49
# File 'lib/isodoc/presentation_function/index.rb', line 47

def index_entries_opt
  { xref_lbl: ", ", see_lbl: ", #{see_lbl}", also_lbl: ", #{also_lbl}" }
end

#index_entries_see(entries, label) ⇒ Object



96
97
98
99
100
101
102
103
104
105
# File 'lib/isodoc/presentation_function/index.rb', line 96

def index_entries_see(entries, label)
  see_sort = entries&.dig(label) or return nil
  x = see_sort.each_with_object({}) do |w, v|
    v[sortable(w).downcase] = w
  end
  x.keys.localize(@lang.to_sym).sort.to_a.map do |k|
    # see_sort[k]
    x[k]
  end.join(", ")
end

#inline(docxml) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/isodoc/presentation_xml_convert.rb', line 122

def inline(docxml)
  document_footnotes docxml
  comments docxml
  fmt_ref docxml # feeds citeas, xref, eref, origin, concept
  citeas docxml # feeds xref, eref, origin, concept
  xref docxml
  eref docxml # feeds eref2link
  origin docxml # feeds eref2link
  concept docxml
  eref2link docxml # feeds link
  link docxml
  mathml docxml
  ruby docxml
  variant docxml
  identifier docxml
  date docxml
  passthrough docxml
  inline_format docxml
end

#inline_format(docxml) ⇒ Object



122
123
124
125
# File 'lib/isodoc/presentation_function/inline.rb', line 122

def inline_format(docxml)
  custom_charset(docxml)
  text_transform(docxml)
end

#insert_biblio_tag(bib, ordinal, biblio, standard) ⇒ Object



138
139
140
141
142
143
144
145
146
147
# File 'lib/isodoc/presentation_function/refs.rb', line 138

def insert_biblio_tag(bib, ordinal, biblio, standard)
  datefn = date_note_process(bib)
  ids = bibitem_ref_code(bib)
  idents = render_identifier(ids)
  ret = if biblio then biblio_ref_entry_code(ordinal, idents,
                                             standard, datefn, bib)
        else norm_ref_entry_code(ordinal, idents, standard, datefn, bib)
        end
  bib.add_first_child("<biblio-tag>#{@i18n.l10n(ret)}</biblio-tag>")
end

#insert_fn_body_ref(fnote, body) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/isodoc/presentation_function/footnotes.rb', line 40

def insert_fn_body_ref(fnote, body)
  ins = body.at(ns(".//p")) ||
    body.at(ns("./semx")).children.first.before("<p> </p>").previous
  lbl = fn_body_label(fnote)
  ins.children.first.previous = <<~FNOTE.strip
    <fmt-fn-label><span class='fmt-caption-label'>#{lbl}</span><span class="fmt-caption-delim"><tab/></fmt-fn-label>
  FNOTE
end

#labelled_autonum(label, id, num) ⇒ Object



98
99
100
101
102
# File 'lib/isodoc/presentation_function/autonum.rb', line 98

def labelled_autonum(label, id, num)
  elem = "<span class='fmt-element-name'>#{label}</span>"
  num.blank? and return elem
  l10n("#{elem} #{autonum(id, num)}")
end

#large_notation_fmt(symbols, num) ⇒ Object



97
98
99
100
101
102
103
104
105
106
# File 'lib/isodoc/presentation_function/math.rb', line 97

def large_notation_fmt(symbols, num)
  n = symbols[:large_notation]
  min = BigDecimal(symbols[:large_notation_min] || "1e-6")
  max = BigDecimal(symbols[:large_notation_max] || "1e6")
  n1 = large_notation_fmt1(num, n, min, max) and symbols[:notation] = n1
  symbols.delete(:large_notation)
  symbols.delete(:large_notation_min)
  symbols.delete(:large_notation_max)
  symbols
end

#large_notation_fmt1(num, notation, min, max) ⇒ Object



108
109
110
111
112
113
114
115
# File 'lib/isodoc/presentation_function/math.rb', line 108

def large_notation_fmt1(num, notation, min, max)
  notation.nil? || notation == "nil" and return nil
  val = BigDecimal(num).abs
  val.zero? and return nil
  val < min and return notation
  val > max and return notation
  nil
end


76
# File 'lib/isodoc/presentation_function/inline.rb', line 76

def link(xml); end

#list_at_depth(elem, target_depth) ⇒ Object

Return the first ol/ul at the given depth (depth 1 = elem itself)



99
100
101
102
103
104
105
106
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 99

def list_at_depth(elem, target_depth)
  target_depth == 1 and return elem
  elem.xpath(ns(".//ol | .//ul")).find do |sub|
    d = sub.ancestors.take_while { |a| a != elem }
      .count { |a| %w[ol ul].include?(a.name) } + 2
    d == target_depth
  end
end

#list_only_one_title(elem) ⇒ Object



77
78
79
80
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 77

def list_only_one_title(elem)
  (!elem.at(ns(".//ol//name")) && !elem.at(ns(".//ul//name"))) or return nil
  elem.at(ns("./name"))
end

#list_table_body(elem, cellcount) ⇒ Object

Build <tbody> with one <tr> per leaf (terminal sublist) path



109
110
111
112
113
114
115
116
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 109

def list_table_body(elem, cellcount)
  paths = list_table_leaf_paths(elem, 1)
  emitted = {} # li object_id => true when already emitted under a rowspan
  rows = paths.map do |path|
    list_table_row(path, cellcount, emitted)
  end.join
  "<tbody>#{rows}</tbody>"
end

#list_table_build(elem, cellcount) ⇒ Object

Build the full table as a Nokogiri node



31
32
33
34
35
36
37
38
39
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 31

def list_table_build(elem, cellcount)
  xml = "<table>"
  xml += list_table_name(elem)
  xml += list_table_colgroup(elem, cellcount)
  xml += list_table_header(elem, cellcount)
  xml += list_table_body(elem, cellcount)
  xml += "</table>"
  Nokogiri::XML(xml).root
end

#list_table_calc_start(list, li_idx) ⇒ Object

Calculate the start number for a wrapped ol cell (original ol start) + (0-based position of this li) = start for this li’s number



246
247
248
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 246

def list_table_calc_start(list, li_idx)
  (list["start"] || 1).to_i + li_idx - 1
end

#list_table_col_name(elem, depth) ⇒ Object

Find the <name> element of the first ol/ul at the given depth within elem



94
95
96
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 94

def list_table_col_name(elem, depth)
  list_at_depth(elem, depth)&.at(ns("./name"))
end

#list_table_colgroup(elem, cellcount) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 49

def list_table_colgroup(elem, cellcount)
  n = elem["display-directives"] or return ""
  attrs = csv_attribute_extract(n)
  attrs[:colgroup] or return ""
  vals = attrs[:colgroup].split(",").map(&:to_f)
  vals = list_table_normalise_colgroup(vals, cellcount)
  ret = vals.map { |n| "<col width='#{n}%'/>" }.join
  "<colgroup>#{ret}</colgroup>"
end

#list_table_convert(elem) ⇒ Object

Convert a single display=“table” list: build table, insert under fmt-ol



12
13
14
15
16
17
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 12

def list_table_convert(elem)
  n = list_table_depth(elem)
  table = list_table_build(elem, n)
  elem << "<fmt-#{elem.name}></fmt-#{elem.name}>"
  elem.elements.last << table
end

#list_table_count_terminals(listitem) ⇒ Object

Count terminal sublists reachable from a li element (used for rowspan)



171
172
173
174
175
176
177
178
179
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 171

def list_table_count_terminals(listitem)
  sub_xls = listitem.children.select { |c| %w[ol ul].include?(c.name) }
  sub_xls.empty? and return 1
  count = 0
  sub_xls.each do |sub_xl|
    count += list_table_count_terminals_recurse(sub_xl)
  end
  [count, 1].max
end

#list_table_count_terminals_recurse(sub_xl) ⇒ Object



181
182
183
184
185
186
187
188
189
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 181

def list_table_count_terminals_recurse(sub_xl)
  ret = 0
  (sub_xl.xpath(ns(".//ol")) + sub_xl.xpath(ns(".//ul"))).empty? and
    return 1
  sub_xl.xpath(ns("./li")).each do |sub_li|
    ret += list_table_count_terminals(sub_li)
  end
  ret
end

#list_table_degen_terminal_td(list, listitem, li_idx, depth, cellcount) ⇒ Object

Build a terminal <td> for a degenerate li (no child sublist), wrapping just that single li with the correct colspan



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 214

def list_table_degen_terminal_td(list, listitem, li_idx, depth, cellcount)
  colspan = cellcount - depth + 1
  colspan_attr = colspan > 1 ? " colspan='#{colspan}'" : ""
  li_content = list_table_li_content(listitem)
  if list.name == "ol"
    start = list_table_calc_start(list, li_idx)
    type = @counter.ol_type(list, depth).to_s
    "<td#{colspan_attr}><ol start='#{start}' type='#{type}'>" \
      "<li>#{li_content}</li></ol></td>"
  else
    "<td#{colspan_attr}><ul><li>#{li_content}</li></ul></td>"
  end
end

#list_table_depth(elem) ⇒ Object

Maximum depth of nested ol/ul: elem itself = depth 1



20
21
22
23
24
25
26
27
28
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 20

def list_table_depth(elem)
  depths = [1]
  elem.xpath(ns(".//ol | .//ul")).each do |sub|
    d = sub.ancestors.take_while { |a| a != elem }
      .count { |a| %w[ol ul].include?(a.name) } + 2
    depths << d
  end
  depths.max
end

#list_table_header(elem, cellcount) ⇒ Object

Build <thead><tr> with n <th> cells, one per depth level



71
72
73
74
75
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 71

def list_table_header(elem, cellcount)
  list_only_one_title(elem) and return ""
  ths = (1..cellcount).map { |i| list_table_th(elem, i) }.join
  "<thead><tr>#{ths}</tr></thead>"
end

#list_table_leaf_paths(xl, depth) ⇒ Object

Recursively collect all leaf paths from xl downward. Each path is an array of step hashes; the last step has terminal: true. Non-terminal step: { list:, li:, depth:, li_idx: } Terminal step: { list:, depth:, terminal: true }



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 145

def list_table_leaf_paths(xl, depth)
  paths = []
  xl.xpath(ns("./li")).each_with_index do |li, idx|
    li_idx = idx + 1
    sub_xls = li.children.select { |c| %w[ol ul].include?(c.name) }
    if sub_xls.empty?
      # Degenerate: li with no child sublist — treat as its own terminal row
      paths << [{ list: xl, li:, depth:, li_idx:, terminal: true }]
    else
      sub_xls.each do |sub_xl|
        step = { list: xl, li: li, depth: depth, li_idx: li_idx }
        if (sub_xl.xpath(ns(".//ol")) + sub_xl.xpath(ns(".//ul"))).empty?
          paths << [step,
                    { list: sub_xl, depth: depth + 1, terminal: true }]
        else
          list_table_leaf_paths(sub_xl, depth + 1).each do |sub_path|
            paths << ([step] + sub_path)
          end
        end
      end
    end
  end
  paths
end

#list_table_li_content(listitem) ⇒ Object

Serialize a li’s content, excluding any direct ol/ul children



207
208
209
210
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 207

def list_table_li_content(listitem)
  listitem.children.reject { |c| %w[ol ul].include?(c.name) }
    .map { |c| to_xml(c) }.join
end

#list_table_name(elem) ⇒ Object

global table title if there are no nested titled in the list: move list/fmt-name to ol/fmt-ol/table/fmt-name: ol/fmt-ol is all we render



43
44
45
46
47
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 43

def list_table_name(elem)
  list_only_one_title(elem) or return ""
  ret = elem.at(ns("./fmt-name")) or return ""
  to_xml(ret.remove)
end

#list_table_nonterminal_td(list, listitem, li_idx, rowspan, depth) ⇒ Object

Build a nonterminal <td>: wraps a single li (minus nested sublists) in an ol/ul with appropriate start, type, and rowspan



193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 193

def list_table_nonterminal_td(list, listitem, li_idx, rowspan, depth)
  rowspan_attr = rowspan > 1 ? " rowspan='#{rowspan}'" : ""
  li_content = list_table_li_content(listitem)
  if list.name == "ol"
    start = list_table_calc_start(list, li_idx)
    type = @counter.ol_type(list, depth).to_s
    "<td#{rowspan_attr}><ol start='#{start}' type='#{type}'>" \
      "<li>#{li_content}</li></ol></td>"
  else
    "<td#{rowspan_attr}><ul><li>#{li_content}</li></ul></td>"
  end
end

#list_table_normalise_colgroup(vals, cellcount) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 59

def list_table_normalise_colgroup(vals, cellcount)
  vals.size > cellcount and vals = vals[0...cellcount]
  if vals.size < cellcount
    (vals.size...cellcount).each do |_i|
      vals << 10.0
    end
  end
  sum = vals.sum
  vals.map { |i| 100 * i / sum }
end

#list_table_row(path, cellcount, emitted) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 118

def list_table_row(path, cellcount, emitted)
  cells = path.map do |step|
    if step[:terminal]
      if step[:li]
        # Degenerate: single li with no child sublist —
        # render just that li with colspan
        list_table_degen_terminal_td(step[:list], step[:li], step[:li_idx],
                                          step[:depth], cellcount)
      else
        list_table_terminal_td(step[:list], step[:depth], cellcount)
      end
    else
      li = step[:li]
      emitted[li.object_id] and next
      rowspan = list_table_count_terminals(li)
      emitted[li.object_id] = true
      list_table_nonterminal_td(step[:list], li, step[:li_idx], rowspan,
                                step[:depth])
    end
  end.compact.join
  "<tr>#{cells}</tr>"
end

#list_table_terminal_td(xl, depth, cellcount) ⇒ Object

Build a terminal <td>: contains the whole sublist, with colspan if depth < cellcount



230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 230

def list_table_terminal_td(xl, depth, cellcount)
  colspan = cellcount - depth + 1
  colspan_attr = colspan > 1 ? " colspan='#{colspan}'" : ""
  xl_dup = xl.dup
  # Remove <name> from the copy (names go in thead, not in the cell body)
  xl_dup.children.each { |c| c.name == "name" and c.remove }
  if xl.name == "ol"
    type = @counter.ol_type(xl, depth).to_s
    xl_dup["type"] = type
  end
  "<td#{colspan_attr}>#{to_xml(xl_dup)}</td>"
end

#list_table_th(elem, depth) ⇒ Object



82
83
84
85
86
87
88
89
90
91
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 82

def list_table_th(elem, depth)
  name = list_table_col_name(elem, depth)
  name or return "<th/>"
  add_id(name)
  src = name["original-id"] || name["id"]
  children = to_xml(name.children)
  <<~XML
    <th><fmt-name><semx element='name' source='#{src}'>#{children}</semx></fmt-name></th>
  XML
end

#list_to_table(docxml) ⇒ Object

Entry point: find all top-level (ol|ul) and convert each



4
5
6
7
8
9
# File 'lib/isodoc/presentation_function/list_to_table.rb', line 4

def list_to_table(docxml)
  docxml.xpath(ns("//ol[@display='table'] | //ul[@display='table']"))
    .each do |elem|
    list_table_convert(elem)
  end
end

#loc2xref(entry) ⇒ Object



146
147
148
149
150
151
152
153
154
# File 'lib/isodoc/presentation_function/xrefs.rb', line 146

def loc2xref(entry)
  if entry[:target]
    <<~XML
      <fmt-xref nested='true' target='#{entry[:target]}'>#{entry[:label]}</fmt-xref>
    XML
  else
    entry[:label]
  end
end

#locality_delimiter(_loc) ⇒ Object



75
76
77
# File 'lib/isodoc/presentation_function/erefs_locality.rb', line 75

def locality_delimiter(_loc)
  { conn: ", " }
end

#localize_maths(node, locale) ⇒ Object

symbols is merged into TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/isodoc/presentation_function/math.rb', line 23

def localize_maths(node, locale)
  node.xpath(".//m:mn", MATHML).each do |x|
    fmt = x["data-metanorma-numberformat"]
    x.delete("data-metanorma-numberformat")
    x.children =
      if !fmt.nil? && !fmt.empty?
        explicit_number_formatter(x, locale, fmt)
      else implicit_number_formatter(x, locale)
      end
  rescue ArgumentError
  rescue StandardError, RuntimeError => e
    warn "Failure to localise MathML/mn\n#{node.parent.to_xml}\n#{e}"
  end
end

#localized_strings(docxml) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/isodoc/presentation_function/metadata.rb', line 39

def localized_strings(docxml)
  ins, langs, i18n_cache = localized_strings_prep(docxml)
  ins or return
  words = langs.each_with_object([]) do |l, m|
    @i18n = if @lang == l then i18n_cache
            else i18n_init(l, ::Metanorma::Utils.default_script(l), nil, {})
            end
    m << i18n_name(trim_hash(@i18n.get), "", l).join
  end
  ins.next = "<localized-strings>#{words.join}</localized-strings>"
  @i18n = i18n_cache
end

#localized_strings_prep(docxml) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/isodoc/presentation_function/metadata.rb', line 52

def localized_strings_prep(docxml)
  ins = docxml.at(ns("//bibdata")) or return
  langs = docxml.xpath(ns("//bibdata/title/@language")).map(&:to_s)
  langs << @lang
  langs.uniq!
  i18n_cache = @i18n
  [ins, langs, i18n_cache]
end

#logo_expand_pres_metadata(docxml) ⇒ Object

logo-role-format-height/width-number



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/isodoc/presentation_function/metadata.rb', line 18

def (docxml)
  docxml.xpath(ns("//metanorma-extension/presentation-metadata/*"))
    .each do |x|
      (x) or next
      parts = x.name.split("-")
      @output_formats.each_key do |f|
        tagname = "logo-#{parts[1]}-#{f}-#{parts[2..].join('-')}"
        x.parent.next = <<~XML
          <presentation-metadata><#{tagname}>#{x.text}</#{tagname}></presentation-metadata>
        XML
      end
  end
end

#logo_size_pres_metadata_incomplete?(elem) ⇒ Boolean

Returns:

  • (Boolean)


32
33
34
35
36
37
# File 'lib/isodoc/presentation_function/metadata.rb', line 32

def (elem)
  parts = elem.name.split("-")
  elem.name.start_with?("logo-") &&
    %w(author editor publisher authorizer distrbutor).include?(parts[1]) &&
    %w(height width).include?(parts[2])
end

#lower2cap(text) ⇒ Object



8
9
10
11
12
13
14
15
16
# File 'lib/isodoc/presentation_function/block.rb', line 8

def lower2cap(text)
  text.nil? and return text
  x = Nokogiri::XML("<a>#{text}</a>")
  firsttext = x.at(".//text()[string-length(normalize-space(.))>0]") or
    return text
  /^[[:upper:]][[:upper:]]/.match?(firsttext.text) and return text
  firsttext.replace(firsttext.text.capitalize)
  to_xml(x.root.children)
end

#mathml(docxml) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
# File 'lib/isodoc/presentation_function/math.rb', line 9

def mathml(docxml)
  docxml.xpath(ns("//stem")).each { |s| stem_dup(s) }
  locale = @lang.to_sym
  @numfmt = Plurimath::NumberFormatter
    .new(locale, localize_number: @localizenumber,
                 localizer_symbols: twitter_cldr_localiser_symbols)
  docxml.xpath("//m:math", MATHML).each do |f| # rubocop:disable Style/CombinableLoops
    f.parent&.parent&.name == "fmt-stem" or next
    mathml1(f, locale)
  end
end

#mathml1(node, locale) ⇒ Object



198
199
200
201
# File 'lib/isodoc/presentation_function/math.rb', line 198

def mathml1(node, locale)
  mathml_style_inherit(node)
  mathml_number(node, locale)
end

#mathml_number(node, locale) ⇒ Object



221
222
223
224
225
226
227
228
229
230
# File 'lib/isodoc/presentation_function/math.rb', line 221

def mathml_number(node, locale)
  justnumeral = numeric_mathml?(node)
  justnumeral or asciimath_dup(node)
  localize_maths(node, locale)
  if justnumeral
    maths_just_numeral(node)
  else
    mn_to_msup(node)
  end
end

#mathml_number_to_number(node) ⇒ Object



248
249
250
251
252
# File 'lib/isodoc/presentation_function/math.rb', line 248

def mathml_number_to_number(node)
  (node.elements.size == 1 && node.elements.first.name == "mn") or return
  repl = node.at("./m:mn", MATHML).children
  node.replace(repl)
end

#mathml_style_inherit(node) ⇒ Object



242
243
244
245
246
# File 'lib/isodoc/presentation_function/math.rb', line 242

def mathml_style_inherit(node)
  node.at("./ancestor::xmlns:strong") or return
  node.children =
    "<mstyle mathvariant='bold'>#{node.children.to_xml}</mstyle>"
end

#maths_just_numeral(node) ⇒ Object



192
193
194
195
196
# File 'lib/isodoc/presentation_function/math.rb', line 192

def maths_just_numeral(node)
  mn = node.at(".//m:mn", MATHML).children.text
    .sub(/\^([0-9+-]+)$/, "<sup>\\1</sup>")
  node.replace(mn)
end

#merge_preferred_eligible?(first, second) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
# File 'lib/isodoc/presentation_function/designations.rb', line 75

def merge_preferred_eligible?(first, second)
  orig_first, orig_second, firstex, secondex =
    merge_preferred_eligible_prep(first, second)
  orig_first["geographic-area"] == orig_second["geographic-area"] &&
    firstex["language"] == secondex["language"] &&
    !orig_first.at(ns("./pronunciation | ./grammar | ./graphical-symbol")) &&
    !orig_second.at(ns("./pronunciation | ./grammar | ./graphical-symbol")) &&
    orig_first.name == "preferred" && orig_second.name == "preferred"
end

#merge_preferred_eligible_prep(first, second) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/isodoc/presentation_function/designations.rb', line 85

def merge_preferred_eligible_prep(first, second)
  orig_first = semx_orig(first)
  orig_second = semx_orig(second)
  firstex = orig_first.at(ns("./expression")) || {}
  secondex = orig_second.at(ns("./expression")) || {}
  [orig_first, orig_second, firstex, secondex]
end

#merge_second_preferred(term) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/isodoc/presentation_function/designations.rb', line 56

def merge_second_preferred(term)
  pref = nil
  out = term.xpath(ns("./semx")).each_with_index
    .with_object([]) do |(p, i), m|
    if (i.zero? && (pref = p)) || merge_preferred_eligible?(pref, p)
      m << p
    else p.wrap("<p></p>")
    end
  end
  pref&.replace(merge_second_preferred1(out, term))
end

#merge_second_preferred1(desgns, term) ⇒ Object



68
69
70
71
72
73
# File 'lib/isodoc/presentation_function/designations.rb', line 68

def merge_second_preferred1(desgns, term)
  desgns[1..].each(&:remove)
  ret = l10n(desgns.map { |x| to_xml(x) }.join("; "))
  term.ancestors("fmt-related").empty? and ret = "<p>#{ret}</p>"
  ret
end

#metadata(docxml) ⇒ Object



3
4
5
6
7
8
9
10
# File 'lib/isodoc/presentation_function/metadata.rb', line 3

def (docxml)
  (docxml)
  (docxml)
  (docxml)
  attachments_extract(docxml)
  a = docxml.at(ns("//metanorma-extension")) or return
  a.elements.empty? and a.remove
end

#metanorma_extension_insert_pt(xml) ⇒ Object



153
154
155
156
157
158
159
# File 'lib/isodoc/presentation_xml_convert.rb', line 153

def metanorma_extension_insert_pt(xml)
  xml.at(ns("//metanorma-extension")) ||
    xml.at(ns("//bibdata"))&.after("<metanorma-extension/>")
      &.next_element ||
    xml.root.elements.first.before("<metanorma-extension/>")
      .previous_element
end

#middle_title(docxml) ⇒ Object



5
6
7
8
9
10
11
12
# File 'lib/isodoc/presentation_function/title.rb', line 5

def middle_title(docxml)
  sections = docxml.at(ns("//sections")) or return
  template = middle_title_get_template(docxml) or return
  title = populate_template(template, nil) or return
  title.strip.empty? and return
  Nokogiri::XML(title).root.text.strip.empty? and return
  sections.add_first_child title
end

#middle_title_get_template(docxml) ⇒ Object



14
15
16
17
18
19
# File 'lib/isodoc/presentation_function/title.rb', line 14

def middle_title_get_template(docxml)
  m = docxml.at(ns("//presentation-metadata/middle-title"))
  template = m ? to_xml(m.children) : middle_title_template
  template&.strip&.empty? and template = nil
  template
end

#middle_title_templateObject



21
22
23
# File 'lib/isodoc/presentation_function/title.rb', line 21

def middle_title_template
  "<p class='zzSTDTitle1'>{{ doctitle }}</p>"
end

#missing_title(docxml) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/isodoc/presentation_function/title.rb', line 25

def missing_title(docxml)
  docxml.xpath(ns("//definitions[not(./title)]")).each do |d|
    # should only be happening for subclauses
    d.add_first_child "<title>#{@i18n.symbols}</title>"
  end
  docxml.xpath(ns("//foreword[not(./title)]")).each do |d|
    d.add_first_child "<title>#{@i18n.foreword}</title>"
  end
end

#mn_to_msup(node) ⇒ Object

convert any Ascii superscripts to correct(ish) MathML Not bothering to match times, base of 1.0 x 10^-20, just ^-20



214
215
216
217
218
219
# File 'lib/isodoc/presentation_function/math.rb', line 214

def mn_to_msup(node)
  node.xpath(".//m:mn", MATHML).each do |n|
    m = %r{^(.+)\^([0-9+-]+)$}.match(n.text) or next
    n.replace("<msup><mn>#{m[1]}</mn><mn>#{m[2]}</mn></msup>")
  end
end

#modification_dup_align(sem, pres) ⇒ Object



140
141
142
143
144
145
146
147
148
149
# File 'lib/isodoc/presentation_function/terms.rb', line 140

def modification_dup_align(sem, pres)
  m = sem&.at(ns("./modification")) or return
  m1 = pres.at(ns("./modification"))
  if m["original-id"]
    m["id"] = m["original-id"]
    m.delete("original-id")
  end
  new_m1 = semx_fmt_dup(m)
  m1.replace("<modification>#{to_xml(new_m1)}</modification>")
end

#move_norm_ref_to_sections(docxml) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/isodoc/presentation_function/section_refs.rb', line 28

def move_norm_ref_to_sections(docxml)
  docxml.at(ns(@xrefs.klass.norm_ref_xpath)) or return
  s = move_norm_ref_to_sections_insert_pt(docxml) or return
  docxml.xpath(ns(@xrefs.klass.norm_ref_xpath)).each do |r|
    r.at("./ancestor::xmlns:bibliography") or next
    s << r.remove
  end
end

#move_norm_ref_to_sections_insert_pt(docxml) ⇒ Object



37
38
39
40
41
42
43
# File 'lib/isodoc/presentation_function/section_refs.rb', line 37

def move_norm_ref_to_sections_insert_pt(docxml)
  s = docxml.at(ns("//sections")) and return s
  s = docxml.at(ns("//preface")) and
    return s.after("<sections/>").next_element
  docxml.at(ns("//annex | //bibliography"))&.before("<sections/>")
    &.previous_element
end

#multidef(_elem, defn, fmt_defn) ⇒ Object



73
74
75
76
77
78
# File 'lib/isodoc/presentation_function/terms.rb', line 73

def multidef(_elem, defn, fmt_defn)
  ret = defn.each_with_object([]) do |f, m|
    m << "<li #{add_id_text}>#{to_xml(semx_fmt_dup(f))}</li>"
  end
  fmt_defn << "<ol #{add_id_text}>#{ret.join("\n")}</ol>"
end

#no_identifier(bib) ⇒ Object



48
49
50
51
52
53
# File 'lib/isodoc/presentation_function/docid.rb', line 48

def no_identifier(bib)
  @i18n.no_identifier or return nil
  id = Nokogiri::XML::Node.new("docidentifier", bib.document)
  id << @i18n.no_identifier
  id
end

#non_document_footnotes(docxml) ⇒ Object



88
89
90
# File 'lib/isodoc/presentation_function/footnotes.rb', line 88

def non_document_footnotes(docxml)
  table_footnotes(docxml) + figure_footnotes(docxml)
end

#non_locality_elems(node) ⇒ Object



6
7
8
9
10
# File 'lib/isodoc/presentation_function/inline.rb', line 6

def non_locality_elems(node)
  node.children.reject do |c|
    %w{locality localityStack location}.include? c.name
  end
end

#norm_ref_entry_code(_ordinal, ids, _standard, datefn, _bib) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
# File 'lib/isodoc/presentation_function/refs.rb', line 149

def norm_ref_entry_code(_ordinal, ids, _standard, datefn, _bib)
  ret = esc((ids[:ordinal] || ids[:content] || ids[:metanorma] || ids[:sdo])
    .to_s)
  (ids[:ordinal] || ids[:metanorma]) && ids[:sdo] and
    ret += ", #{esc ids[:sdo]}"
  ret += datefn
  ret.empty? and return ret
  ids[:sdo] and ret += ","
  ret.sub(",", "").strip.empty? and return ""
  "#{ret} "
end

#normalise_number(num) ⇒ Object



38
39
40
41
42
# File 'lib/isodoc/presentation_function/math.rb', line 38

def normalise_number(num)
  n = BigDecimal(num).to_s("F")
  /\.\d/.match?(num) or n.sub!(/\.\d+$/, "")
  n
end

#note(docxml) ⇒ Object



52
53
54
# File 'lib/isodoc/presentation_function/block.rb', line 52

def note(docxml)
  docxml.xpath(ns("//note")).each { |f| note1(f) }
end

#note1(elem) ⇒ Object



60
61
62
63
64
# File 'lib/isodoc/presentation_function/block.rb', line 60

def note1(elem)
  %w(bibdata bibitem).include?(elem.parent.name) ||
    elem["notag"] == "true" or lbl = note_label(elem)
  prefix_name(elem, { label: note_delim(elem) }, lbl, "name")
end

#note_delim(_elem) ⇒ Object



56
57
58
# File 'lib/isodoc/presentation_function/block.rb', line 56

def note_delim(_elem)
  "<tab/>"
end

#note_label(elem) ⇒ Object



66
67
68
69
70
# File 'lib/isodoc/presentation_function/block.rb', line 66

def note_label(elem)
  n = @xrefs.get[elem["id"]] || @xrefs.get[elem["original-id"]]
  labelled_autonum(@i18n.note, elem["id"] || elem["original-id"],
                   n&.dig(:label))
end

#notes_inside_bibitem(bib) ⇒ Object



27
28
29
30
31
32
# File 'lib/isodoc/presentation_function/refs.rb', line 27

def notes_inside_bibitem(bib)
  while (n = bib.next_element) && n.name == "note"
    n["type"] = (n["type"] ? "display,#{n['type']}" : "display")
    bib << n.remove
  end
end

#num_precision(num) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/isodoc/presentation_function/math.rb', line 117

def num_precision(num)
  precision = nil
  /\.(?!\d+e)/.match?(num) and
    precision = twitter_cldr_localiser_symbols[:precision] ||
      # [^.]* excludes the delimiter itself, preventing polynomial
      # backtracking on strings with multiple dots.
      num.sub(/\A[^.]*\./, "").size
  precision
end

#num_precision_from_significant(num, significant, base) ⇒ Object

When base != 10 and the source is in E-notation, derive the target-base fractional digit count from the total significant digit count we computed. Plurimath’s default precision_from() returns the decimal fractional digit count, which Numbers::Fraction#change_base then uses as the target-base fractional digit count – producing too few fractional digits in non-decimal bases. Workaround pending upstream fix; see github.com/metanorma/isodoc/issues/788.



166
167
168
169
170
171
172
173
174
175
# File 'lib/isodoc/presentation_function/math.rb', line 166

def num_precision_from_significant(num, significant, base)
  base == 10 and return nil
  significant.nil? and return nil
  /\.(?=\d+e)/.match?(num) or return nil
  m = num.match(/\A-?0?\.(\d+)e(-?\d+)\z/) or return nil
  m[1].length <= m[2].to_i and return 0
  val = BigDecimal(num).abs
  integer_len = val.to_i.zero? ? 0 : val.to_i.to_s(base).length
  [significant - integer_len, 0].max
end

#num_totaldigits(num, base = 10) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/isodoc/presentation_function/math.rb', line 127

def num_totaldigits(num, base = 10)
  totaldigits = nil
  /\.(?=\d+e)/.match?(num) and
    totaldigits = twitter_cldr_localiser_symbols[:significant] ||
      num_totaldigits_compute(num, base)
  totaldigits
end

#num_totaldigits_compute(num, base) ⇒ Object

In base 10, total significant digits = source mantissa length. In other bases, the converted value may have fewer digits. Per github.com/metanorma/isodoc/issues/788: if the source has no fractional part after E-notation expansion, return the length of the integer in the target base (e.g. 123 -> 7B = 2 digits, not 3); if the source has a fractional part, preserve the source mantissa length so Plurimath pads the converted fraction (e.g. 123.25 -> 7B.400, 123.0 -> 7B.00).



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/isodoc/presentation_function/math.rb', line 143

def num_totaldigits_compute(num, base)
  # [^.]* and [^e]* exclude their respective delimiters,
  # preventing polynomial backtracking.
  mantissa = num.sub(/\A0\./, ".").sub(/\A[^.]*\./, "")
    .sub(/e[^e]*\z/, "")
  return mantissa.size if base == 10

  m = num.match(/\A-?0?\.(\d+)e(-?\d+)\z/)
  if m && m[1].length <= m[2].to_i
    BigDecimal(num).to_i.abs.to_s(base).length
  else
    mantissa.size
  end
end

#numbered_clause_invalid_context?(elem) ⇒ Boolean

context in which clause numbering is invalid: metanorma-extension, boilerplate

Returns:

  • (Boolean)


22
23
24
25
26
27
28
29
30
31
32
# File 'lib/isodoc/presentation_function/section.rb', line 22

def numbered_clause_invalid_context?(elem)
  @ncic_cache ||= {}
  elem or return false
  @ncic_cache.key?(elem) and return @ncic_cache[elem]
  if ["metanorma-extension", "boilerplate"].include?(elem.name)
    @ncic_cache[elem] = true
  else
    elem.respond_to?(:parent) or return false
    @ncic_cache[elem] = numbered_clause_invalid_context?(elem.parent)
  end
end

#numberformat_type(ret) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/isodoc/presentation_function/math.rb', line 53

def numberformat_type(ret)
  %i(precision significant digit_count group_digits fraction_group_digits
     base)
    .each do |i|
    ret[i] &&= ret[i].to_i
  end
  %i(notation exponent_sign number_sign locale hex_capital).each do |i|
    ret[i] &&= ret[i].to_sym
  end
  %i(base_prefix base_suffix).each do |i|
    ["", "nil"].include?(ret[i]) and ret[i] = nil
  end
  ret
end

#numeric_mathml?(node) ⇒ Boolean

Returns:

  • (Boolean)


232
233
234
235
236
237
238
239
240
# File 'lib/isodoc/presentation_function/math.rb', line 232

def numeric_mathml?(node)
  m = {}
  node.traverse do |x|
    %w(mstyle mrow math text).include?(x.name) and next
    m[x.name] ||= 0
    m[x.name] += 1
  end
  m.keys.size == 1 && m["mn"] == 1
end

#ol(docxml) ⇒ Object



22
23
24
25
26
# File 'lib/isodoc/presentation_function/list.rb', line 22

def ol(docxml)
  ol_prep(docxml)
  docxml.xpath(ns("//ol")).each { |f| ol1(f) }
  docxml.xpath(ns("//ol/li")).each { |f| ol_label(f) }
end

#ol1(elem) ⇒ Object



46
47
48
49
50
# File 'lib/isodoc/presentation_function/list.rb', line 46

def ol1(elem)
  elem["type"] ||= ol_depth(elem).to_s # feeds ol_label_format
  elem.at(ns("./name")) and
    prefix_name(elem, {}, "", "name") # copy name to fmt-name
end

#ol_depth(node) ⇒ Object



41
42
43
44
# File 'lib/isodoc/presentation_function/list.rb', line 41

def ol_depth(node)
  depth = node.ancestors("ul, ol").size + 1
  @counter.ol_type(node, depth) # defined in Xref::Counter
end

#ol_label(elem) ⇒ Object



52
53
54
55
56
57
# File 'lib/isodoc/presentation_function/list.rb', line 52

def ol_label(elem)
  val = @xrefs.anchor(elem["id"] || elem["original-id"], :label, false)
  semx = "<semx element='autonum' source='#{elem['id'] || elem["original-id"]}'>#{val}</semx>"
  lbl = "<fmt-name>#{ol_label_format(semx, elem)}</fmt-name>"
  elem.add_first_child(lbl)
end

#ol_label_format(semx, elem) ⇒ Object



69
70
71
72
# File 'lib/isodoc/presentation_function/list.rb', line 69

def ol_label_format(semx, elem)
  template = ol_label_template(elem)[elem.parent["type"].to_sym]
  template.sub("%", semx)
end

#ol_label_template(_elem) ⇒ Object



59
60
61
62
63
64
65
66
67
# File 'lib/isodoc/presentation_function/list.rb', line 59

def ol_label_template(_elem)
  {
    alphabet: %{%<span class="fmt-label-delim">)</span>},
    alphabet_upper: %{%<span class="fmt-label-delim">.</span>},
    roman: %{%<span class="fmt-label-delim">)</span>},
    roman_upper: %{%<span class="fmt-label-delim">.</span>},
    arabic: %{%<span class="fmt-label-delim">)</span>},
  }
end

#ol_numbering(docxml) ⇒ Object



28
29
30
31
32
# File 'lib/isodoc/presentation_function/list.rb', line 28

def ol_numbering(docxml)
  docxml.xpath(ns("//ol")).each do |elem|
    elem["type"] ||= ol_depth(elem).to_s # feeds ol_label_format
  end
end

#ol_prep(docxml) ⇒ Object



34
35
36
37
38
39
# File 'lib/isodoc/presentation_function/list.rb', line 34

def ol_prep(docxml)
  ol_numbering(docxml)
  @xrefs.list_anchor_names(docxml.xpath(ns(@xrefs.sections_xpath)))
  @xrefs.localise_anchors("list")
  @xrefs.localise_anchors("listitem")
end

#orig_id_cleanup(docxml) ⇒ Object

if have moved a new GUID id to original-id in copying, move it back to id



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/isodoc/presentation_function/ids.rb', line 47

def orig_id_cleanup(docxml)
  @doc_orig_ids = {}
  docxml.xpath("//*[@original-id]").each do |x|
    if !@doc_ids[x["original-id"]] && !x["id"]
      x["id"] = x["original-id"]
      x.delete("original-id")
      @doc_ids[x["id"]] = x.line
    else
      @doc_orig_ids[x["original-id"]] = x.line
    end
  end
end

#origin(docxml) ⇒ Object



67
68
69
# File 'lib/isodoc/presentation_function/inline.rb', line 67

def origin(docxml)
  docxml.xpath(ns("//fmt-origin[not(.//termref)]")).each { |f| xref1(f) }
end

#passthrough(docxml) ⇒ Object



171
172
173
174
175
176
# File 'lib/isodoc/presentation_function/inline.rb', line 171

def passthrough(docxml)
  formats = @output_formats.keys
  docxml.xpath(ns("//passthrough")).each do |p|
    passthrough1(p, formats)
  end
end

#passthrough1(elem, formats) ⇒ Object



178
179
180
181
182
183
184
# File 'lib/isodoc/presentation_function/inline.rb', line 178

def passthrough1(elem, formats)
  (elem["formats"] && !elem["formats"].empty?) or elem["formats"] = "all"
  f = elem["formats"].split(",")
  (f - formats).size == f.size or f = "all"
  f == ["all"] and f = formats.dup
  elem["formats"] = " #{f.join(' ')} "
end

#permission(docxml) ⇒ Object



17
18
19
20
21
22
# File 'lib/isodoc/presentation_function/reqt.rb', line 17

def permission(docxml)
  docxml.xpath(ns("//permission")).each do |f|
    recommendation1(f, lower2cap(f["class"]) ||
                    lower2cap(@i18n.permission))
  end
end

#populate_id(docxml) ⇒ Object



90
91
92
93
94
95
# File 'lib/isodoc/presentation_function/ids.rb', line 90

def populate_id(docxml)
  docxml.xpath("//*[@id]").each do |x|
    x["semx-id"] = x["id"]
    x["anchor"] and x["id"] = to_ncname(x["anchor"])
  end
end

#postprocess(result, filename, _dir) ⇒ Object



161
162
163
164
# File 'lib/isodoc/presentation_xml_convert.rb', line 161

def postprocess(result, filename, _dir)
  to_xml_file(result, filename)
  @files_to_delete.each { |f| FileUtils.rm_rf f }
end

#preceding_floating_titles(node, idx) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/isodoc/presentation_function/title.rb', line 50

def preceding_floating_titles(node, idx)
  out = node.xpath("./preceding-sibling::*")
    .reverse.each_with_object([]) do |p, m|
    %w(note admonition p floating-title).include?(p.name) or break m
    m << p
  end
  out.reject { |c| c["displayorder"] }.reverse_each do |c|
    skip_display_order?(c) and next
    c["displayorder"] = idx
    idx += 1
  end
  idx
end

#preceding_floats(clause) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/isodoc/presentation_function/title.rb', line 88

def preceding_floats(clause)
  ret = []
  p = clause
  while prev = p.previous_element
    if prev.name == "floating-title"
      ret << prev
      p = prev
    else break
    end
  end
  ret
end

#pref_ref_code(bib) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/isodoc/presentation_function/docid.rb', line 9

def pref_ref_code(bib)
  bib["suppress_identifier"] == "true" and return nil
  ret = bib.xpath(ns("./docidentifier[@scope = 'biblio-tag']"))
  ret.empty? or return ret.map { |x| to_xml(x.children) }
  ret = pref_ref_code_parse(bib) or return nil
  ins = bib.at(ns("./docidentifier[last()]"))
  ret.reverse_each do |r|
    id = docid_l10n(r, citation: false)
    ins.next = "<docidentifier scope='biblio-tag'>#{id}</docidentifier>"
  end
  ret
end

#pref_ref_code_parse(bib) ⇒ Object



22
23
24
25
26
27
# File 'lib/isodoc/presentation_function/docid.rb', line 22

def pref_ref_code_parse(bib)
  data, = @bibrender.parse(bib)
  ret = data[:authoritative_identifier] or return nil
  ret.empty? and return nil
  ret.map { |x| @i18n.l10n(x) } # get rid of `<esc>` wrappers
end

#preface_move(clauses, after, _doc) ⇒ Object



124
125
126
127
128
129
130
131
132
133
# File 'lib/isodoc/presentation_function/section.rb', line 124

def preface_move(clauses, after, _doc)
  clauses.empty? and return
  preface = clauses.first.parent
  clauses.each do |clause|
    float = preceding_floats(clause)
    xpath = after.map { |n| "./self::xmlns:#{n}" }.join(" | ")
    xpath.empty? and xpath = "./self::*[not(following-sibling::*)]"
    preface_move1(clause, preface, float, nil, xpath)
  end
end

#preface_move1(clause, preface, float, prev, xpath) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/isodoc/presentation_function/section.rb', line 135

def preface_move1(clause, preface, float, prev, xpath)
  preface.elements.each do |x|
    ((x.name == "floating-title" || x.at(xpath)) &&
    xpath != "./self::*[not(following-sibling::*)]") or prev = x
    x.at(xpath) or next
    clause == prev and break
    prev ||= preface.children.first
    prev.next = clause
    float.each { |n| prev.next = n }
    break
  end
end

#preface_rearrange(doc) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/isodoc/presentation_function/section.rb', line 112

def preface_rearrange(doc)
  [["//preface/abstract",
    %w(foreword introduction clause acknowledgements executivesummary)],
   ["//preface/foreword",
    %w(introduction clause acknowledgements executivesummary)],
   ["//preface/introduction", %w(clause acknowledgements executivesummary)],
   ["//preface/acknowledgements", %w(executivesummary)],
   ["//preface/executivesummary", %w()]].each do |x|
    preface_move(doc.xpath(ns(x[0])), x[1], doc)
  end
end

#prefix_bracketed_ref(text) ⇒ Object



175
176
177
# File 'lib/isodoc/presentation_function/refs.rb', line 175

def prefix_bracketed_ref(text)
  "#{text}<tab/>"
end

#prefix_container(container, linkend, node, target) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/isodoc/presentation_function/xrefs.rb', line 16

def prefix_container(container, linkend, node, target)
  prefix_container?(container, node) or return linkend
  container_container = prefix_container_container(container)
  cntnr_label =
    prefix_container(container_container,
                     anchor_xref(node, container, container: true),
                     node, target)
  l10n(connectives_spans(@i18n.nested_xref
    .sub("%1", "<span class='fmt-xref-container'>#{esc cntnr_label}</span>")
    .sub("%2", esc(linkend))))
end

#prefix_container?(container, node) ⇒ Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
92
# File 'lib/isodoc/presentation_function/xrefs.rb', line 86

def prefix_container?(container, node)
  node["style"] == "modspec" and return false # TODO: move to mn-requirements?
  type = @xrefs.anchor(node["target"], :type)
  container &&
    get_note_container_id(node, type) != container &&
    @xrefs.get[node["target"]]
end

#prefix_container_container(container) ⇒ Object



126
127
128
129
130
131
132
133
134
# File 'lib/isodoc/presentation_function/autonum.rb', line 126

def prefix_container_container(container)
  container_container = @xrefs.anchor(container, :container, false)
  container_container == container and return nil
  if @xrefs.anchor(container, :type) == "bibitem"
    p = @bibitem_lookup[container].parent
    p and container_container ||= p["id"]
  end
  container_container
end

#prefix_container_fmt_xref_label(container, xref) ⇒ Object



115
116
117
118
119
120
121
122
123
124
# File 'lib/isodoc/presentation_function/autonum.rb', line 115

def prefix_container_fmt_xref_label(container, xref)
  container or return xref
  container_container = prefix_container_container(container)
  container_xref = @xrefs.anchor(container, :xref, false)
  container_label =
    prefix_container_fmt_xref_label(container_container, container_xref)
  l10n(connectives_spans(@i18n.nested_xref
    .sub("%1", "<span class='fmt-xref-container'>#{esc container_label}</span>")
    .sub("%2", xref || "[Unknown]")))
end

#prefix_name(node, delims, label, elem, fmt_xref_label: true) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
# File 'lib/isodoc/presentation_function/autonum.rb', line 3

def prefix_name(node, delims, label, elem, fmt_xref_label: true)
  sem_xml_descendant?(node) and return
  label, delims = prefix_name_defaults(node, delims, label, elem)
  name, ins, ids, number = prefix_name_prep(node, elem)
  fmt_xref_label and ins.next = fmt_xref_label(label, number, ids)
  # autonum can be empty, e.g single note in clause: "NOTE []"
  number and node["autonum"] = number.gsub(/<[^>]+>/, "")
  !node.at(ns("./fmt-#{elem}")) &&
    (c = fmt_caption(label, elem, name, ids, delims)) and ins.next = c
  prefix_name_postprocess(node, elem)
end

#prefix_name_defaults(node, delims, label, elem) ⇒ Object



15
16
17
18
19
20
21
22
# File 'lib/isodoc/presentation_function/autonum.rb', line 15

def prefix_name_defaults(node, delims, label, elem)
  label&.empty? and label = nil
  node["unnumbered"] == "true" && !node.at(ns("./#{elem}")) &&
    node.name != "admonition" and label = nil
  # do not caption unnumbered uncaptioned blocks, other than admonitions
  delims.nil? and delims = {}
  [label, delims]
end

#prefix_name_labels(node) ⇒ Object



33
34
35
36
37
# File 'lib/isodoc/presentation_function/autonum.rb', line 33

def prefix_name_labels(node)
  id = "_#{UUIDTools::UUID.random_create}"
  @new_ids[id] = nil
  { elem: node["id"], name: id }
end

#prefix_name_postprocess(node, elem) ⇒ Object



39
40
41
42
43
44
# File 'lib/isodoc/presentation_function/autonum.rb', line 39

def prefix_name_postprocess(node, elem)
  node.at(ns("./sentinel"))&.remove
  strip_duplicate_ids(node, node.at(ns("./#{elem}")),
                      node.at(ns("./fmt-#{elem}")))
  node.at(ns("./fmt-#{elem}"))
end

#prefix_name_prep(node, elem) ⇒ Object



24
25
26
27
28
29
30
31
# File 'lib/isodoc/presentation_function/autonum.rb', line 24

def prefix_name_prep(node, elem)
  lbls = prefix_name_labels(node)
  name = node.at(ns("./#{elem}")) and name["id"] = lbls[:name]
  ins = name || node.add_first_child("<sentinel/>").elements.first
  node["unnumbered"] or
    number = @xrefs.anchor(node["id"], :value, false)&.strip
  [name, ins, lbls, number]
end

#prep_for_rendering(bib) ⇒ Object



13
14
15
16
17
# File 'lib/isodoc/presentation_function/refs.rb', line 13

def prep_for_rendering(bib)
  bib["suppress_identifier"] == true and
    bib.xpath(ns("./docidentifier")).each(&:remove)
  bib["type"] ||= "standard"
end

#preprocess_metadata(docxml) ⇒ Object



12
13
14
15
# File 'lib/isodoc/presentation_function/metadata.rb', line 12

def (docxml)
  localized_strings(docxml)
  (docxml)
end

#presmeta(name, value) ⇒ Object



125
126
127
# File 'lib/isodoc/presentation_function/metadata.rb', line 125

def presmeta(name, value)
  "<#{name}>#{value}</#{name}>"
end

#presmeta_insert_pt(xmldoc) ⇒ Object



118
119
120
121
122
123
# File 'lib/isodoc/presentation_function/metadata.rb', line 118

def presmeta_insert_pt(xmldoc)
  ins = xmldoc.at(ns("//presentation-metadata")) and return ins
  ins = extension_insert_pt(xmldoc)
  ins << "<presentation-metadata> </presentation-metadata>"
  ins.elements.last
end

#presxml_convert_init(docxml, filename, dir) ⇒ Object



47
48
49
50
51
52
53
54
55
56
# File 'lib/isodoc/presentation_xml_convert.rb', line 47

def presxml_convert_init(docxml, filename, dir)
  @outputdir = dir
  @outputfile = Pathname.new(filename).basename.to_s
  docid_prefixes(docxml) # feeds @xrefs.parse citation processing
  provide_ids docxml # feeds @xrefs.parse
  bibitem_lookup(docxml) # feeds citeas
  @xrefs.parse docxml
  @xrefs.klass.meta = @meta
  counter_init
end

#provide_ids(docxml) ⇒ Object



76
77
78
79
80
# File 'lib/isodoc/presentation_function/ids.rb', line 76

def provide_ids(docxml)
  anchor_sanitise(docxml)
  populate_id(docxml)
  add_missing_id(docxml)
end

#quote(docxml) ⇒ Object



197
198
199
# File 'lib/isodoc/presentation_function/block.rb', line 197

def quote(docxml)
  docxml.xpath(ns("//quote")).each { |f| quote1(f) }
end

#quote1(elem) ⇒ Object



201
202
203
204
205
206
207
# File 'lib/isodoc/presentation_function/block.rb', line 201

def quote1(elem)
  author = elem.at(ns("./author"))
  source = elem.at(ns("./source"))
  author.nil? && source.nil? and return
  p = quote_attribution(author, source, elem)
  elem << "<attribution><p>#{l10n p}</p></attribution>"
end

#quote_attribution(author, source, elem) ⇒ Object

e: duplicate of source, will be duplicated in fmt-eref, need to delete after



211
212
213
214
215
216
217
# File 'lib/isodoc/presentation_function/block.rb', line 211

def quote_attribution(author, source, elem)
  p = "&#x2014; "
  p += to_xml(semx_fmt_dup(author)) if author
  p += ", " if author && source
  source or return p
  p + to_xml(quote_source(source, elem))
end

#quote_source(source, elem) ⇒ Object



219
220
221
222
223
224
225
226
227
# File 'lib/isodoc/presentation_function/block.rb', line 219

def quote_source(source, elem)
  s = semx_fmt_dup(source)
  e = Nokogiri::XML::Node.new("eref", elem.document)
  e << s.children
  s << e
  source.attributes.each_key { |k| e[k] = source[k] }
  e["deleteme"] = "true"
  s
end

#rearrange_clauses(docxml) ⇒ Object



148
149
150
151
# File 'lib/isodoc/presentation_function/section.rb', line 148

def rearrange_clauses(docxml)
  preface_rearrange(docxml) # feeds toc_title
  toc_title(docxml)
end

#recommendation(docxml) ⇒ Object



3
4
5
6
7
8
# File 'lib/isodoc/presentation_function/reqt.rb', line 3

def recommendation(docxml)
  docxml.xpath(ns("//recommendation")).each do |f|
    recommendation1(f, lower2cap(f["class"]) ||
                    lower2cap(@i18n.recommendation))
  end
end

#recommendation1(elem, type) ⇒ Object



24
25
26
27
28
# File 'lib/isodoc/presentation_function/reqt.rb', line 24

def recommendation1(elem, type)
  lbl = @reqt_models.model(elem["model"])
    .recommendation_label(elem, type, xrefs)
  prefix_name(elem, {}, @i18n.l10n(lbl), "name")
end

#redundant_eref(elem) ⇒ Object

redundant eref copied from quote/source



59
60
61
62
63
64
65
# File 'lib/isodoc/presentation_function/inline.rb', line 59

def redundant_eref(elem)
  if elem.next.name == "semx"
    elem.next.elements.first.delete("deleteme")
    elem.next.replace(elem.next.children)
  end
  elem.remove
end

#reference_name(ref) ⇒ Object



20
21
22
23
24
25
26
# File 'lib/isodoc/presentation_function/section_refs.rb', line 20

def reference_name(ref)
  identifiers = render_identifier(bibitem_ref_code(ref))
  reference = docid_l10n(identifiers[:content] || identifiers[:metanorma] ||
                         identifiers[:sdo] || identifiers[:ordinal] ||
                         identifiers[:doi])
  @xrefs.get[ref["id"]] = { xref: esc(reference), type: "bibitem" }
end

#reference_names(docxml) ⇒ Object



14
15
16
17
18
# File 'lib/isodoc/presentation_function/section_refs.rb', line 14

def reference_names(docxml)
  docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |ref|
    reference_name(ref)
  end
end

#references(docxml) ⇒ Object



3
4
5
6
7
8
9
10
11
12
# File 'lib/isodoc/presentation_function/section_refs.rb', line 3

def references(docxml)
  @ref_renderings = references_render(docxml)
  docxml.xpath(ns("//references/bibitem")).each do |x|
    bibitem(x, @ref_renderings)
    reference_name(x)
  end
  bibliography_bibitem_number(docxml)
  hidden_items(docxml)
  move_norm_ref_to_sections(docxml)
end

#references_render(docxml) ⇒ Object



3
4
5
6
7
8
9
10
11
# File 'lib/isodoc/presentation_function/refs.rb', line 3

def references_render(docxml)
  d = docxml.clone
  d.remove_namespaces!
  refs = d.xpath("//references/bibitem").each_with_object([]) do |b, m|
    prep_for_rendering(b)
    m << to_xml(b)
  end.join
  @bibrender.render_all("<references>#{refs}</references>")
end

#reinsert_callout(xml) ⇒ Object



145
146
147
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 145

def reinsert_callout(xml)
  "<span class='c'>#{to_xml(xml)}</span>"
end


3
4
5
# File 'lib/isodoc/presentation_function/designations.rb', line 3

def related(docxml)
  docxml.xpath(ns("//fmt-related/semx")).each { |f| related1(f) }
end

#related1(node) ⇒ Object

Only render related if rendered and hyperlinked



8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/isodoc/presentation_function/designations.rb', line 8

def related1(node)
  p, ref, orig = related1_prep(node)
  label = @i18n.relatedterms[orig["type"]].upcase
  ret = if p && ref
          if p.text == ref.text
            "<em>#{Common::to_xml(ref)}</em>"
          else
            "<em>#{to_xml(p)}</em> (#{Common::to_xml(ref)})"
          end
        else "<strong>**RELATED TERM NOT FOUND**</strong>"
        end
  node.children = (l10n("<p><strong>#{label}:</strong> #{ret}</p>"))
end

#related1_prep(node) ⇒ Object



22
23
24
25
26
27
# File 'lib/isodoc/presentation_function/designations.rb', line 22

def related1_prep(node)
  p = node.at(ns("./fmt-preferred"))&.children
  ref = node.at(ns("./xref | ./eref | ./termref"))
  orig = semx_orig(node)
  [p, ref, orig]
end


29
30
31
32
33
34
35
36
# File 'lib/isodoc/presentation_function/designations.rb', line 29

def related_designation1(desgn)
  out = desgn.parent.at(ns("./fmt-#{desgn.name}"))
  d1 = semx_fmt_dup(desgn)
  %w(preferred admitted deprecates).each do |w|
    d = d1.at(ns("./#{w}[last()]")) and d.after("<fmt-#{w}/>")
  end
  out << d1
end

#render_identifier(ident) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/isodoc/presentation_function/docid.rb', line 87

def render_identifier(ident)
  { metanorma: bracket(ident[0]),
    sdo: unbracket(ident[1]),
    doi: unbracket(ident[2]),
    ordinal: bracket(ident[3]),
    content: unbracket(ident[4]) }
end

#renumber_document_footnote(fnote, idx, seen) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/isodoc/presentation_function/footnotes.rb', line 123

def renumber_document_footnote(fnote, idx, seen)
  fnote["original-reference"] = fnote["reference"]
  if sem_xml_descendant?(fnote)
    fnote.delete("reference")
    return idx
  elsif seen[fnote["reference"]]
    fnote["reference"] = seen[fnote["reference"]]
  else
    seen[fnote["reference"]] = idx
    fnote["reference"] = idx
    idx += 1
  end
  idx
end

#renumber_document_footnotes(fns_by_section, idx) ⇒ Object

can instead restart at i=1 each section



114
115
116
117
118
119
120
121
# File 'lib/isodoc/presentation_function/footnotes.rb', line 114

def renumber_document_footnotes(fns_by_section, idx)
  fns_by_section.reject(&:empty?).each_with_object({}) do |s, seen|
    s.each do |f|
      idx = renumber_document_footnote(f, idx, seen)
    end
  end
  fns_by_section.flatten
end

#repeat_id_validate(doc) ⇒ Object



39
40
41
42
43
44
# File 'lib/isodoc/presentation_function/ids.rb', line 39

def repeat_id_validate(doc)
  @doc_ids = {}
  doc.xpath("//*[@id]").each do |x|
    repeat_id_validate1(x)
  end
end

#repeat_id_validate1(elem) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/isodoc/presentation_function/ids.rb', line 31

def repeat_id_validate1(elem)
  if @doc_ids[elem["id"]]
    @log&.add("STANDOC_36", elem,
              params: [elem["id"], @doc_ids[elem["id"]]])
  end
  @doc_ids[elem["id"]] = elem.line
end

#requirement(docxml) ⇒ Object



10
11
12
13
14
15
# File 'lib/isodoc/presentation_function/reqt.rb', line 10

def requirement(docxml)
  docxml.xpath(ns("//requirement")).each do |f|
    recommendation1(f, lower2cap(f["class"]) ||
                    lower2cap(@i18n.requirement))
  end
end

#requirement_render(docxml) ⇒ Object



34
35
36
37
38
39
40
41
42
43
# File 'lib/isodoc/presentation_function/reqt.rb', line 34

def requirement_render(docxml)
  requirement_render_preprocessing(docxml)
  REQS.each do |x|
    REQS.each do |y|
      docxml.xpath(ns("//#{x}//#{y}")).each { |r| requirement_render1(r) }
    end
  end
  docxml.xpath(ns("//requirement | //recommendation | //permission"))
    .each { |r| requirement_render1(r) }
end

#requirement_render1(node) ⇒ Object



45
46
47
48
# File 'lib/isodoc/presentation_function/reqt.rb', line 45

def requirement_render1(node)
  node.replace(@reqt_models.model(node["model"])
    .requirement_render1(node))
end

#requirement_render_preprocessing(docxml) ⇒ Object



30
# File 'lib/isodoc/presentation_function/reqt.rb', line 30

def requirement_render_preprocessing(docxml); end

#resolve_comma_connectives(locs) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/isodoc/presentation_function/erefs.rb', line 84

def resolve_comma_connectives(locs)
  locs1 = []
  add = ""
  until locs.empty?
    locs, locs1, add = resolve_comma_connectives1(locs, locs1, add)
  end
  locs1 << { ref: add } unless add.empty?
  locs1
end

#resolve_comma_connectives1(locs, locs1, add) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/isodoc/presentation_function/erefs.rb', line 94

def resolve_comma_connectives1(locs, locs1, add)
  if [", ", " ", ""].include?(locs.dig(1, :conn)) && locs.size > 2
    add += [locs[0][:ref], locs[1][:custom] || locs[1][:conn],
            locs[2][:ref]].join
    locs.shift(3)
  else
    locs1 << add unless add.empty?
    add = ""
    locs1 << locs.shift
  end
  [locs, locs1, add]
end

#resolve_eref_connectives(locs) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/isodoc/presentation_function/erefs.rb', line 44

def resolve_eref_connectives(locs)
  locs = resolve_eref_connectives1(locs)
  locs.size < 3 and return locs.map do |x|
    x[:custom] || x[:conn] || x[:ref]
  end
  locs = resolve_eref_connectives_split(locs)
  locs = locs.each_slice(2).with_object([]) do |a, m|
    m << { custom: a[0][:custom], conn: a[0][:conn], label: a.dig(1, :ref) }
  end
  [", ", combine_conn(locs)]
end

#resolve_eref_connectives1(locs) ⇒ Object



56
57
58
59
60
# File 'lib/isodoc/presentation_function/erefs.rb', line 56

def resolve_eref_connectives1(locs)
  locs = escape_l10n(locs)
  locs = resolve_comma_connectives(locs)
  resolve_to_connectives(locs)
end

#resolve_eref_connectives_split(locs) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/isodoc/presentation_function/erefs.rb', line 62

def resolve_eref_connectives_split(locs)
  locs.each_with_object([]) do |x, m|
    if m.empty?
      m << x
    elsif m[-1][:conn] && x[:conn]
      m[-1][:conn] += x[:conn]
      x[:custom] and m[-1][:custom] = x[:custom]
    elsif m[-1][:conn] && x[:conn]
      m[-1][:ref] += x[:ref]
    else m << x
    end
  end
end

#resolve_to_connectives(locs) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/isodoc/presentation_function/erefs.rb', line 107

def resolve_to_connectives(locs)
  locs1 = []
  until locs.empty?
    if locs.dig(1, :conn) == "to"
      x = @i18n.chain_to.sub("%1", locs[0][:ref])
        .sub("%2", locs[2][:ref])
      c = locs[1][:custom] and x = conn_sub(x, c)
      locs1 << { ref: connectives_spans(x) }
      locs.shift(3)
    elsif locs[0][:conn] == "from" && locs[0][:custom]
      locs1 << { conn: locs[0][:custom] }
      locs.shift # strip "from" and English
    # TODO languages with obligatory "from"
    else
      locs1 << locs.shift
    end
  end
  locs1
end

#rouge_css_locationObject

replace in local gem rather than specify overrides of default



21
22
23
24
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 21

def rouge_css_location
  File.read(File.join(File.dirname(__FILE__), "..", "base_style",
                      "rouge.css"))
end

#ruby(docxml) ⇒ Object



196
197
198
199
200
201
# File 'lib/isodoc/presentation_function/inline.rb', line 196

def ruby(docxml)
  (docxml.xpath(ns("//ruby")) - docxml.xpath(ns("//ruby//ruby")))
    .each do |r|
    ruby1(r)
  end
end

#ruby1(elem) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/isodoc/presentation_function/inline.rb', line 203

def ruby1(elem)
  v = elem.at(ns("./ruby-pronunciation | ./ruby-annotation")).remove
  elem.xpath(ns("./ruby")).each do |r|
    ruby1(r)
  end
  t = elem.children.to_xml
  elem.replace("<ruby><rb>#{t}</rb><rt>#{v['value']}</rt></ruby>")
end

#save_attachment(attachment, dir) ⇒ Object



71
72
73
74
75
# File 'lib/isodoc/presentation_function/metadata.rb', line 71

def save_attachment(attachment, dir)
  n = File.join(dir, File.basename(attachment["name"]))
  c = attachment.text.sub(%r{^data:[^;]+;(?:charset=[^;]+;)?base64,}, "")
  File.open(n, "wb") { |f| f.write(Base64.decode64(c)) }
end

#section(docxml) ⇒ Object

parse annex after term, references, to deal with single-term and single-ref annexes



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/isodoc/presentation_xml_convert.rb', line 82

def section(docxml)
  references docxml
  # feeds middle_title
  # triggers xrefs reparse, so put references before all other sections,
  # which alter titles and thus can alter xrefs
  rearrange_clauses docxml # feeds toc, display_order, clausetitle,
  # clause, middle_title
  middle_title docxml
  missing_title docxml # feeds clause
  annex docxml
  clause docxml # feeds clausetitle
  term docxml
  clausetitle docxml # feeds floattitle
  floattitle docxml # feeds rearrange_clauses
  index docxml # fed by strip_duplicate_ids
  toc docxml
  display_order docxml # feeds document_footnotes
end

#see_lblObject



107
108
109
# File 'lib/isodoc/presentation_function/index.rb', line 107

def see_lbl
  @lang == "en" ? @i18n.see : "<em>#{@i18n.see}</em>"
end

#sem_xml_descendant?(node) ⇒ Boolean

do not change to Presentation XML rendering this is sensitive to ordering of Presentation XML processing: blocks > terms > inline

Returns:

  • (Boolean)


178
179
180
181
182
183
184
185
# File 'lib/isodoc/presentation_function/autonum.rb', line 178

def sem_xml_descendant?(node)
  ancestor_names = node.ancestors.map(&:name)
  sem_xml_descendant_terms?(node, ancestor_names) and return true
  sem_xml_descendant_inline?(node, ancestor_names) and return true
  sem_xml_descendant_bibitem?(node, ancestor_names) and return true
  sem_xml_descendant_provision?(node, ancestor_names) and return true
  false
end

#sem_xml_descendant_bibitem?(_node, ancestor_names) ⇒ Boolean

Returns:

  • (Boolean)


196
197
198
199
200
201
# File 'lib/isodoc/presentation_function/autonum.rb', line 196

def sem_xml_descendant_bibitem?(_node, ancestor_names)
  ancestor_names.include?("bibitem") &&
    %w[formattedref biblio-tag].none? do |name|
      ancestor_names.include?(name)
    end
end

#sem_xml_descendant_inline?(_node, ancestor_names) ⇒ Boolean

Returns:

  • (Boolean)


203
204
205
206
207
208
# File 'lib/isodoc/presentation_function/autonum.rb', line 203

def sem_xml_descendant_inline?(_node, ancestor_names)
  %w[xref eref origin link name title newcontent]
    .any? do |name|
    ancestor_names.include?(name)
  end and return true
end

#sem_xml_descendant_provision?(node, ancestor_names) ⇒ Boolean

keep Presentation XML blocks within provisions, they are processed separately into distinct Presentation XML fmt-provision later

Returns:

  • (Boolean)


190
191
192
193
194
# File 'lib/isodoc/presentation_function/autonum.rb', line 190

def sem_xml_descendant_provision?(node, ancestor_names)
  block?(node) and return false
  (ancestor_names & %w[requirement recommendation permission]).any? &&
    !ancestor_names.include?("fmt-provision")
end

#sem_xml_descendant_terms?(node, ancestor_names) ⇒ Boolean

keep Presentation XML blocks within designations, they are processed separately into distinct Presentation XML fmt-* designations later

Returns:

  • (Boolean)


213
214
215
216
217
218
219
# File 'lib/isodoc/presentation_function/autonum.rb', line 213

def sem_xml_descendant_terms?(node, ancestor_names)
  block?(node) and return false
  %w[preferred admitted deprecated related definition source]
    .any? do |name|
    ancestor_names.include?(name)
  end
end

#semx(node, label, element = "autonum") ⇒ Object



81
82
83
84
85
86
# File 'lib/isodoc/presentation_function/autonum.rb', line 81

def semx(node, label, element = "autonum")
  id = node["id"] || node[:id] || node["original-id"]
  /<semx element='[^']+' source='#{id}'/.match?(label) and return label
  l = stripsemx(label)
  %(<semx element='#{element}' source='#{id}'>#{l}</semx>)
end

#semx_fmt_dup(elem) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/isodoc/presentation_function/autonum.rb', line 53

def semx_fmt_dup(elem)
  add_id(elem)
  new = Nokogiri::XML(<<~XML).root
    <semx xmlns='#{elem.namespace.href}' element='#{elem.name}' source='#{elem['original-id'] || elem['id']}'>#{to_xml(elem.children)}</semx>
  XML
  strip_duplicate_ids(nil, elem, new)
  new
end

#semx_orig(node, orig = nil) ⇒ Object



93
94
95
96
# File 'lib/isodoc/presentation_function/autonum.rb', line 93

def semx_orig(node, orig = nil)
  orig ||= node.parent.parent
  orig.at(".//*[@id = '#{node['source']}']")
end

#single_term_clause_retitle(elem) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/isodoc/presentation_function/section.rb', line 59

def single_term_clause_retitle(elem)
  t = elem.at(ns("./terms | ./definitions | ./references"))
  title1 = elem.at(ns("./title"))
  title2 = t.at(ns("./title"))&.remove
  !title1 && title2 and
    elem.first_element_child.previous = title2
end

#single_term_clause_unnest(elem) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/isodoc/presentation_function/section.rb', line 67

def single_term_clause_unnest(elem)
  t = elem.at(ns("./terms | ./definitions | ./references"))
  t.xpath(ns(".//clause | .//terms | .//definitions | .//references"))
    .each do |c|
      tit = c.at(ns("./fmt-title")) or next
      tit["depth"] = tit["depth"].to_i - 1 unless tit["depth"] == "1"
    end
end

#singledef(_elem, defn, fmt_defn) ⇒ Object



80
81
82
# File 'lib/isodoc/presentation_function/terms.rb', line 80

def singledef(_elem, defn, fmt_defn)
  fmt_defn << semx_fmt_dup(defn.first)
end

#skip_display_order?(node) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/isodoc/presentation_function/section.rb', line 76

def skip_display_order?(node)
  node.name == "floating-title"
end

#sort_footnote_sections(docxml) ⇒ Object

bibdata, boilerplate, @displayorder sections



80
81
82
83
84
85
86
# File 'lib/isodoc/presentation_function/footnotes.rb', line 80

def sort_footnote_sections(docxml)
  sects = docxml.xpath(".//*[@displayorder]")
    .sort_by { |c| c["displayorder"].to_i }
  b = docxml.at(ns("//boilerplate")) and sects.unshift b
  b = docxml.at(ns("//bibdata")) and sects.unshift b
  sects
end

#sort_indexterms(terms, see, also) ⇒ Object



115
116
117
118
119
120
121
122
123
# File 'lib/isodoc/presentation_function/index.rb', line 115

def sort_indexterms(terms, see, also)
  index = extract_indexterms(terms)
  index = extract_indexsee(index, see, :see)
  index = extract_indexsee(index, also, :also)
  index.keys.sort.each_with_object({}) do |k, v|
    v[sortable(k)[0].upcase.transliterate] ||= {}
    v[sortable(k)[0].upcase.transliterate][k] = index[k]
  end
end

#sortable(str) ⇒ Object



42
43
44
45
# File 'lib/isodoc/presentation_function/index.rb', line 42

def sortable(str)
  str or return " "
  HTMLEntities.new.decode(Nokogiri::XML.fragment(str).text)
end

#source(docxml) ⇒ Object

TODO will go back to just one source/modification, preserving it



4
5
6
7
8
9
10
11
12
13
# File 'lib/isodoc/presentation_function/source.rb', line 4

def source(docxml)
  fmt_source(docxml)
  docxml.xpath(ns("//fmt-source/source/modification")).each do |f|
    source_modification(f)
  end
  source_types(docxml)
  docxml.xpath(ns("//fmt-source/source")).each do |f|
    f.replace(semx_fmt_dup(f))
  end
end

#source1(elem, ancestor) ⇒ Object



42
43
44
45
46
47
48
49
50
# File 'lib/isodoc/presentation_function/source.rb', line 42

def source1(elem, ancestor)
  esc_origin(elem)
  source_elems = source1_gather(elem)
  source_elems.each do |e|
    esc_origin(e)
    elem << "#{source_join_delim(elem)}#{to_xml(e.remove.children).strip}"
  end
  source1_label(elem, @i18n.l10n(to_xml(elem.children).strip), ancestor)
end

#source1_gather(elem) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/isodoc/presentation_function/source.rb', line 52

def source1_gather(elem)
  source_elems = []
  while elem = elem&.next_element
    case elem.name
    when "source"
    when "fmt-source"
      source_elems << elem
    else break
    end
  end
  source_elems
end

#source1_label(elem, sources, _ancestor) ⇒ Object



65
66
67
# File 'lib/isodoc/presentation_function/source.rb', line 65

def source1_label(elem, sources, _ancestor)
  elem.children = l10n("[#{@i18n.source}: #{esc sources}]")
end

#source_highlight(elem, linenums, lang) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 86

def source_highlight(elem, linenums, lang)
  @highlighter or return
  markup = source_remove_markup(elem)
  p = source_lex(elem, lang)
  elem.children = if linenums
                    r = sourcecode_table_to_elem(elem, p)
                    source_restore_markup_table(r, markup)
                  else
                    r = @highlighter[:formatter].format(p)
                    source_restore_markup(Nokogiri::XML.fragment(r), markup)
                  end
end

#source_join_delim(_elem) ⇒ Object



38
39
40
# File 'lib/isodoc/presentation_function/source.rb', line 38

def source_join_delim(_elem)
  "; "
end

#source_label(elem) ⇒ Object



171
172
173
174
175
176
177
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 171

def source_label(elem)
  if !labelled_ancestor(elem) && # do not number if labelled_ancestor
      lbl = @xrefs.anchor(elem["id"], :label, false)
    s = labelled_autonum(lower2cap(@i18n.figure), elem["id"], lbl)&.strip
  end
  prefix_name(elem, { caption: block_delim }, s, "name")
end

#source_lex(elem, lang) ⇒ Object



162
163
164
165
166
167
168
169
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 162

def source_lex(elem, lang)
  lexer = Rouge::Lexer.find(lang || "plaintext") ||
    Rouge::Lexer.find("plaintext")
  l = Rouge::Lexers::Escape.new(start: "{^^{", end: "}^^}", lang: lexer)
  source = to_xml(elem.children).gsub("<", "{^^{<").gsub(">", ">}^^}")
  l.lang.reset!
  l.lex(@c.decode(source))
end

#source_modification(mod) ⇒ Object



69
70
71
# File 'lib/isodoc/presentation_function/source.rb', line 69

def source_modification(mod)
  termsource_modification(mod.parent)
end

#source_remove_annotations(ret, elem) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 106

def source_remove_annotations(ret, elem)
  ret[:ann] = elem.xpath(ns("./callout-annotation")).each(&:remove)
  ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
    m << { xml: c.remove, line: c.line - elem.line }
  end
  ret
end

#source_remove_markup(elem) ⇒ Object



99
100
101
102
103
104
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 99

def source_remove_markup(elem)
  ret = {}
  name = elem.at(ns("./name")) and ret[:name] = name.remove.to_xml
  source_remove_annotations(ret, elem)
  ret
end

#source_restore_callouts(code, callouts) ⇒ Object



125
126
127
128
129
130
131
132
133
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 125

def source_restore_callouts(code, callouts)
  text = to_xml(code)
  text.split(/[\n\r]/).each_with_index do |c, i|
    while !callouts.empty? && callouts[0][:line] == i
      c.sub!(/\s+$/, " #{reinsert_callout(callouts[0][:xml])} ")
      callouts.shift
    end
  end.join("\n")
end

#source_restore_callouts_table(table, callouts) ⇒ Object



135
136
137
138
139
140
141
142
143
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 135

def source_restore_callouts_table(table, callouts)
  table.xpath(".//td[@class = 'rouge-code']/sourcecode")
    .each_with_index do |c, i|
    while !callouts.empty? && callouts[0][:line] == i
      c << " #{reinsert_callout(callouts[0][:xml])} "
      callouts.shift
    end
  end
end

#source_restore_markup(wrapper, markup) ⇒ Object



114
115
116
117
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 114

def source_restore_markup(wrapper, markup)
  ret = source_restore_callouts(wrapper, markup[:call])
  "#{markup[:name]}#{ret}#{markup[:ann]}"
end

#source_restore_markup_table(wrapper, markup) ⇒ Object



119
120
121
122
123
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 119

def source_restore_markup_table(wrapper, markup)
  source_restore_callouts_table(wrapper, markup[:call])
  ret = to_xml(wrapper)
  "#{markup[:name]}#{ret}#{markup[:ann]}"
end

#source_types(docxml) ⇒ Object



15
16
17
18
# File 'lib/isodoc/presentation_function/source.rb', line 15

def source_types(docxml)
  docxml.xpath(ns("//table/fmt-source")).each { |f| tablesource(f) }
  docxml.xpath(ns("//figure/fmt-source")).each { |f| figuresource(f) }
end

#sourcecode(docxml) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 41

def sourcecode(docxml)
  sourcehighlighter_css(docxml)
  @highlighter = sourcehighlighter
  @callouts = {}
  (docxml.xpath(ns("//sourcecode")) -
   docxml.xpath(ns("//metanorma-extension//sourcecode")))
    .each do |f|
    sourcecode1(f)
  end
end

#sourcecode1(elem) ⇒ Object



52
53
54
55
56
57
58
59
60
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 52

def sourcecode1(elem)
  ret1 = semx_fmt_dup(elem)
  b = ret1.at(ns(".//body")) and b.replace(b.children)
  source_label(elem)
  source_highlight(ret1, elem["linenums"] == "true", elem["lang"])
  callouts(elem)
  annotations(elem, ret1)
  fmt_sourcecode(elem, ret1)
end

#sourcecode_table_to_elem(elem, tokens) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 149

def sourcecode_table_to_elem(elem, tokens)
  r = Nokogiri::XML(@highlighter[:formatter_line].format(tokens)).root
  r.xpath(".//td[@class = 'rouge-code']/pre").each do |pre|
    %w(style).each { |n| elem[n] and pre[n] = elem[n] }
    pre.name = "sourcecode"
    pre.children = to_xml(pre.children).sub(/\s+$/, "")
  end
  r.xpath(".//tr[@id]").each do |tr| # disambig Rouge ids
    tr["id"] = "#{elem['source']}_#{tr['id']}"
  end
  r
end

#sourcehighlighterObject



26
27
28
29
30
31
32
33
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 26

def sourcehighlighter
  @sourcehighlighter or return
  Rouge::Formatter.enable_escape!
  f = Rouge::Formatters::HTML.new
  opts = { gutter_class: "rouge-gutter", code_class: "rouge-code" }
  f1 = Rouge::Formatters::HTMLLineTable.new(f, opts)
  { formatter: f, formatter_line: f1 }
end

#sourcehighlighter_css(docxml) ⇒ Object



3
4
5
6
7
8
9
# File 'lib/isodoc/presentation_function/sourcecode.rb', line 3

def sourcehighlighter_css(docxml)
  ret = custom_css(docxml)
  ret.empty? and return
  ins = extension_insert(docxml)
  ins << "<source-highlighter-css>#{ret}" \
         "</source-highlighter-css>"
end

#standard?(bib) ⇒ Boolean

Returns:

  • (Boolean)


214
215
216
217
218
219
220
221
222
# File 'lib/isodoc/presentation_function/refs.rb', line 214

def standard?(bib)
  ret = false
  bib.xpath(ns("./docidentifier")).each do |id|
    id["type"].nil? || id.at(".//self::*[#{SERIAL_NUM_DOCID} or "\
      "@type = 'metanorma']") and next
    ret = true
  end
  ret
end

#stem_dup(node) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/isodoc/presentation_function/math.rb', line 203

def stem_dup(node)
  sem_xml_descendant?(node) and return
  ret = semx_fmt_dup(node)
  f = Nokogiri::XML::Node.new("fmt-stem", node.document)
  t = node["type"] and f["type"] = t
  f << ret
  node.next = f
end

#strip_duplicate_ids(_node, sem_title, pres_title) ⇒ Object

remove ids duplicated between sem_title and pres_title index terms are assumed transferred to pres_title from sem_title



70
71
72
73
74
75
76
77
78
79
# File 'lib/isodoc/presentation_function/autonum.rb', line 70

def strip_duplicate_ids(_node, sem_title, pres_title)
  (sem_title && pres_title) or return
  ids = gather_all_ids(pres_title)
  sem_title.xpath(".//*[@id]").each do |x|
    ids.include?(x["id"]) or next
    x["original-id"] = x["id"]
    x.delete("id")
  end
  sem_title.xpath(ns(".//index")).each(&:remove)
end

#strip_index(docxml) ⇒ Object



3
4
5
# File 'lib/isodoc/presentation_function/index.rb', line 3

def strip_index(docxml)
  docxml.xpath(ns("//index | //index-xref | //indexsect")).each(&:remove)
end

#subfigure_delimObject



56
57
58
59
# File 'lib/isodoc/presentation_function/image.rb', line 56

def subfigure_delim
  ""
  # "<span class='fmt-label-delim'>)</span>"
end

#suffix_url(url) ⇒ Object



167
168
169
170
171
# File 'lib/isodoc/presentation_function/erefs.rb', line 167

def suffix_url(url)
  url.nil? || %r{^https?://|^#}.match?(url) and return url
  File.extname(url).empty? or return url
  url.sub(/#{File.extname(url)}$/, ".html")
end

#svg_emf_double(img) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/isodoc/presentation_function/image.rb', line 111

def svg_emf_double(img)
  if emf?(img["mimetype"])
    img = emf_encode(img)
    # img.children.first.previous = emf_to_svg(img)
    img.add_first_child emf_to_svg(img)
  elsif img["mimetype"] == "image/svg+xml"
    src = svg_to_emf(img) or return
    img.add_child("<emf/>")
    img.elements.last["src"] = src
  end
end

#svg_extract(elem) ⇒ Object



45
46
47
48
49
50
51
52
53
54
# File 'lib/isodoc/presentation_function/image.rb', line 45

def svg_extract(elem)
  return unless %r{^data:image/svg\+xml;}.match?(elem["src"])
  return if elem.at("./m:svg", SVG)

  svg = Base64.strict_decode64(elem["src"]
    .sub(%r{^data:image/svg\+xml;(charset=[^;]+;)?base64,}, ""))
  x = Nokogiri::XML.fragment(svg.sub(/\A<\?xml[^<>]*>\n?/, ""), &:huge)
  elem["src"] = ""
  elem.children = x
end

#svg_impose_height_attr(node) ⇒ Object



179
180
181
182
183
184
185
# File 'lib/isodoc/presentation_function/image.rb', line 179

def svg_impose_height_attr(node)
  e = node.elements&.first or return
  (e.name == "svg" &&
    (!node["height"] || node["height"] == "auto")) or return
  node["height"] = e["height"]
  node["width"] = e["width"]
end

#svg_load(directory, filename) ⇒ Object

used downstream to load svg images inline directory can be string, or array



189
190
191
192
193
194
195
196
197
# File 'lib/isodoc/presentation_function/image.rb', line 189

def svg_load(directory, filename)
  dir = File.join(@libdir, "html", *directory)
  filename = File.join(dir, filename)
  File.exist?(filename) or return
  file = File.read(filename) or return
  file.sub(
    '<?xml version="1.0" encoding="UTF-8"?>', ""
  )
end

#svg_prep(img) ⇒ Object



130
131
132
133
134
# File 'lib/isodoc/presentation_function/image.rb', line 130

def svg_prep(img)
  img["mimetype"] = "image/svg+xml"
  %r{^data:}.match?(img["src"]) or
    img["src"] = Vectory::Emf.from_path(img["src"]).to_uri.content
end

#svg_scale(elem) ⇒ Object



22
23
24
# File 'lib/isodoc/presentation_function/image.rb', line 22

def svg_scale(elem)
  elem["preserveaspectratio"] = "xMidYMin slice"
end

#svg_to_emf(node) ⇒ Object



162
163
164
165
166
167
168
169
170
# File 'lib/isodoc/presentation_function/image.rb', line 162

def svg_to_emf(node)
  @output_formats[:doc] or return
  svg_impose_height_attr(node)
  node.elements&.first&.name == "svg" || %r{^data:}.match?(node["src"]) and
    return svg_to_emf_from_node(node)
  target_path = imgfile_suffix(node["src"], "emf")
  File.exist?(target_path) and return target_path
  svg_to_emf_from_node(node, target_path)
end

#svg_to_emf_from_node(node, target_path = nil) ⇒ Object



172
173
174
175
176
177
# File 'lib/isodoc/presentation_function/image.rb', line 172

def svg_to_emf_from_node(node, target_path = nil)
  emf = Vectory::Svg.from_node(node).to_emf
  return emf.write(target_path).to_uri.content if target_path

  emf.to_uri.content
end

#svg_wrap(elem) ⇒ Object



16
17
18
19
20
# File 'lib/isodoc/presentation_function/image.rb', line 16

def svg_wrap(elem)
  elem.parent.name == "image" and return
  elem.wrap("<image src='' mimetype='image/svg+xml' height='auto' " \
            "width='auto'></image>")
end

#svgmap_extract(elem) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
# File 'lib/isodoc/presentation_function/image.rb', line 26

def svgmap_extract(elem)
  if elem.at(ns("./figure"))
    if n1 = elem.next_element
      n1.name == "semx" && n1["element"] == "svgmap" and return
    end

    n = semx_fmt_dup(elem)
    n.xpath(ns("./target")).each(&:remove)
    elem.next = n
  end
end

#table(docxml) ⇒ Object



105
106
107
108
# File 'lib/isodoc/presentation_function/block.rb', line 105

def table(docxml)
  table_long_strings_cleanup(docxml)
  docxml.xpath(ns("//table")).each { |f| table1(f) }
end

#table1(elem) ⇒ Object



116
117
118
119
120
121
122
123
124
# File 'lib/isodoc/presentation_function/block.rb', line 116

def table1(elem)
  table_fn(elem)
  table_css(elem)
  table1_caption?(elem) or return
  n = @xrefs.anchor(elem["id"] || elem["original-id"], :label, false)
  lbl = labelled_autonum(lower2cap(@i18n.table),
                         elem["id"] || elem["original-id"], n)
  prefix_name(elem, { caption: table_delim }, lbl, "name")
end

#table1_caption?(elem) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
# File 'lib/isodoc/presentation_function/block.rb', line 110

def table1_caption?(elem)
  !labelled_ancestor(elem) &&
    !(elem["unnumbered"] && !elem.at(ns("./name"))) &&
    !%w(fmt-ol fmt-ul).include?(elem.parent.name)
end

#table_css(elem) ⇒ Object



126
127
128
129
130
131
132
133
134
# File 'lib/isodoc/presentation_function/block.rb', line 126

def table_css(elem)
  parser = IsoDoc::CssBorderParser::BorderParser.new
  elem.xpath(ns(".//tr | .//th | .//td | .//table")).each do |n|
    n["style"] or next
    parsed_properties = parser.parse_declaration(n["style"])
    new_style = parser.to_css_string(parsed_properties)
    n["style"] = new_style
  end
end

#table_delimObject



136
137
138
# File 'lib/isodoc/presentation_function/block.rb', line 136

def table_delim
  block_delim
end

#table_fn(elem) ⇒ Object



63
64
65
66
67
68
# File 'lib/isodoc/presentation_function/footnotes.rb', line 63

def table_fn(elem)
  fnotes = elem.xpath(ns(".//fn")) - elem.xpath(ns("./name//fn")) -
    elem.xpath(ns("./fmt-name//fn"))
  ret = footnote_collect(fnotes)
  f = footnote_container(fnotes, ret) and elem << f
end

#table_footnotes(docxml) ⇒ Object



92
93
94
95
96
97
98
# File 'lib/isodoc/presentation_function/footnotes.rb', line 92

def table_footnotes(docxml)
  docxml.xpath(ns("//table//fn")) -
    docxml.xpath(ns("//table/name//fn")) -
    docxml.xpath(ns("//table/fmt-name//fn")) -
    docxml.xpath(ns("//fmt-provision/table//fn")) +
    docxml.xpath(ns("//fmt-provision/table//table//fn"))
end

#table_long_strings_cleanup(docxml) ⇒ Object



140
141
142
143
144
145
146
147
148
149
# File 'lib/isodoc/presentation_function/block.rb', line 140

def table_long_strings_cleanup(docxml)
  @break_up_urls_in_tables or return
  docxml.xpath(ns("//td | //th")).each do |d|
    d.traverse do |n|
      n.text? or next
      ret = Metanorma::Utils::break_up_long_str(n.text)
      n.content = ret
    end
  end
end

#tablesource(elem) ⇒ Object



30
31
32
# File 'lib/isodoc/presentation_function/source.rb', line 30

def tablesource(elem)
  source1(elem, :table)
end

#tag_translate(tag, lang, value) ⇒ Object



83
84
85
86
87
88
# File 'lib/isodoc/presentation_function/bibdata.rb', line 83

def tag_translate(tag, lang, value)
  tag["language"] = ""
  tag.next = tag.dup
  tag.next["language"] = lang
  tag.next.children = value
end

#target_desgn_elem(name) ⇒ Object



6
7
8
9
10
# File 'lib/isodoc/presentation_function/terms.rb', line 6

def target_desgn_elem(name)
  target = "fmt-#{name}"
  name == "source" and target = "fmt-termsource"
  target
end

#term(docxml) ⇒ Object



213
214
215
# File 'lib/isodoc/presentation_function/terms.rb', line 213

def term(docxml)
  docxml.xpath(ns("//term")).each { |f| term1(f) }
end

#term1(elem) ⇒ Object



217
218
219
220
# File 'lib/isodoc/presentation_function/terms.rb', line 217

def term1(elem)
  lbl = @xrefs.anchor(elem["id"], :label, false) or return
  prefix_name(elem, {}, "#{lbl}#{clausedelim}", "name")
end

#term_hash_init(hash, term, term2, term3, label) ⇒ Object



160
161
162
163
164
165
# File 'lib/isodoc/presentation_function/index.rb', line 160

def term_hash_init(hash, term, term2, term3, label)
  hash[term] ||= {}
  hash[term][term2] ||= {}
  hash[term][term2][term3] ||= {}
  hash[term][term2][term3][label] ||= []
end

#termcleanup(docxml) ⇒ Object



21
22
23
24
25
26
27
28
29
30
# File 'lib/isodoc/presentation_function/terms.rb', line 21

def termcleanup(docxml)
  docxml.xpath(ns("//term")).each do |t|
    DESIGNATION_ELEMS.each do |w|
      target = target_desgn_elem(w)
      t.xpath(ns("./#{w}//fmt-name | ./#{w}//fmt-xref-label")).each(&:remove)
      f = t.at(ns(".//#{target}"))
      f&.children&.empty? and f.remove
    end
  end
end

#termcontainers(docxml) ⇒ Object



12
13
14
15
16
17
18
19
# File 'lib/isodoc/presentation_function/terms.rb', line 12

def termcontainers(docxml)
  docxml.xpath(ns("//term")).each do |t|
    DESIGNATION_ELEMS.each do |w|
      target = target_desgn_elem(w)
      d = t.at(ns("./#{w}[last()]")) and d.after("<#{target}/>")
    end
  end
end

#termdefinition(docxml) ⇒ Object



54
55
56
# File 'lib/isodoc/presentation_function/terms.rb', line 54

def termdefinition(docxml)
  docxml.xpath(ns("//term[definition]")).each { |f| termdefinition1(f) }
end

#termdefinition1(elem) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/isodoc/presentation_function/terms.rb', line 58

def termdefinition1(elem)
  d = elem.xpath(ns("./definition"))
  d1 = elem.at(ns("./fmt-definition"))
  if d.size > 1 then multidef(elem, d, d1)
  else singledef(elem, d, d1)
  end
  unwrap_definition(elem, d1)
  s1 = d.xpath(ns(".//source"))
  s2 = d1.xpath(ns(".//source"))
  s1.each_with_index do |s, i|
    modification_dup_align(s, s2[i])
  end
  termdomain(elem, d1)
end

#termdomain(elem, fmt_defn) ⇒ Object



93
94
95
96
97
98
# File 'lib/isodoc/presentation_function/terms.rb', line 93

def termdomain(elem, fmt_defn)
  d = elem.at(ns(".//domain")) or return
  p = fmt_defn.at(ns(".//p")) or return
  d1 = semx_fmt_dup(d)
  p.add_first_child "&lt;#{to_xml(d1)}&gt;  "
end

#termexample(docxml) ⇒ Object



32
33
34
# File 'lib/isodoc/presentation_function/terms.rb', line 32

def termexample(docxml)
  docxml.xpath(ns("//termexample")).each { |f| example1(f) }
end

#termnote(docxml) ⇒ Object



36
37
38
# File 'lib/isodoc/presentation_function/terms.rb', line 36

def termnote(docxml)
  docxml.xpath(ns("//termnote")).each { |f| termnote1(f) }
end

#termnote1(elem) ⇒ Object



44
45
46
47
48
# File 'lib/isodoc/presentation_function/terms.rb', line 44

def termnote1(elem)
  lbl = termnote_label(elem)
  prefix_name(elem, { label: termnote_delim(elem, lbl) },
              lower2cap(lbl), "name")
end

#termnote_delim(_elem, lbl) ⇒ Object



40
41
42
# File 'lib/isodoc/presentation_function/terms.rb', line 40

def termnote_delim(_elem, lbl)
  l10n(": ", { prev: lbl })
end

#termnote_label(elem) ⇒ Object



50
51
52
# File 'lib/isodoc/presentation_function/terms.rb', line 50

def termnote_label(elem)
  @xrefs.anchor(elem["id"], :label, false) || "???"
end

#terms(docxml) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/isodoc/presentation_xml_convert.rb', line 142

def terms(docxml)
  termcontainers docxml
  termexample docxml
  termnote docxml
  termdefinition docxml
  designation docxml
  termsource docxml
  related docxml
  termcleanup docxml
end

#termsource(docxml) ⇒ Object

TODO should I wrap fmt-definition//termsource in fmt-termsource, in order to preserve termsource attributes? differentiating term and nonterm source under designations is not worth it



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/isodoc/presentation_function/terms.rb', line 103

def termsource(docxml)
  copy_baselevel_termsource(docxml)
  docxml.xpath(ns("//fmt-termsource/source | //fmt-definition//source | //fmt-preferred//source | //fmt-admitted//source | //fmt-deprecates//source"))
    .each do |f|
    termsource_modification(f)
  end
  docxml.xpath(ns("//fmt-preferred//fmt-termsource | //fmt-admitted//fmt-termsource | //fmt-deprecates//fmt-termsource"))
    .each do |f|
      termsource_designation(f)
    end
  docxml.xpath(ns("//fmt-termsource/source | //fmt-definition//source | //fmt-preferred//source | //fmt-admitted//source | //fmt-deprecates//source"))
    .each do |f|
    f.parent and termsource1(f)
  end
end

#termsource1(elem) ⇒ Object

concatenate sources. localise the concatenation, escaping the docids within the concatenands from punctuation localisation: l10n(<esc>A</esc>, <esc>B</esc>) pass the result to termsource_label, where it will be appended after “SOURCE: ”, and therefore again needs to be escaped



162
163
164
165
166
167
168
169
170
171
# File 'lib/isodoc/presentation_function/terms.rb', line 162

def termsource1(elem)
  ret = [semx_fmt_dup(elem)]
  while elem.next_element&.name == "source"
    ret << semx_fmt_dup(elem.next_element.remove)
  end
  ret.each { |element| esc_origin(element) }
  s = ret.map { |x| to_xml(x) }.map(&:strip)
    .join(termsource_join_delim(elem))
  termsource_label(elem, @i18n.l10n(s))
end

#termsource_add_modification_text(mod) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
# File 'lib/isodoc/presentation_function/terms.rb', line 194

def termsource_add_modification_text(mod)
  mod or return
  if mod.text.strip.empty?
    mod.remove
    return
  end
  mod.previous = termsource_mod_text_delim(mod)
  c = mod.at(ns("./semx")) || mod
  c.elements.size == 1 and c.children = to_xml(c.elements[0].children)
  mod.replace(mod.children)
end

#termsource_designation(fmtsource) ⇒ Object



119
120
121
122
123
124
# File 'lib/isodoc/presentation_function/terms.rb', line 119

def termsource_designation(fmtsource)
  p = fmtsource.previous_element
  p&.name == "p" or return
  p << " "
  p << fmtsource.children
end

#termsource_join_delim(_elem) ⇒ Object



173
174
175
# File 'lib/isodoc/presentation_function/terms.rb', line 173

def termsource_join_delim(_elem)
  "; "
end

#termsource_label(elem, sources) ⇒ Object



177
178
179
# File 'lib/isodoc/presentation_function/terms.rb', line 177

def termsource_label(elem, sources)
  elem.replace(l10n("[#{@i18n.source}: #{esc sources}]"))
end

#termsource_mod_text_delim(_elem) ⇒ Object



190
191
192
# File 'lib/isodoc/presentation_function/terms.rb', line 190

def termsource_mod_text_delim(_elem)
  " &#x2014; "
end

#termsource_modification(elem) ⇒ Object



181
182
183
184
185
186
187
188
# File 'lib/isodoc/presentation_function/terms.rb', line 181

def termsource_modification(elem)
  elem.xpath(".//text()[normalize-space() = '']").each(&:remove)
  origin = elem.at(ns("./origin"))
  s = termsource_status(elem["status"]) and
    origin.next = l10n(", #{s}", @lang, @script, { prev: origin.text })
  mod = elem.at(ns("./modification")) or return
  termsource_add_modification_text(mod)
end

#termsource_status(status) ⇒ Object



206
207
208
209
210
211
# File 'lib/isodoc/presentation_function/terms.rb', line 206

def termsource_status(status)
  case status
  when "modified" then @i18n.modified
  when "adapted" then @i18n.adapted
  end
end

#text_transform(docxml) ⇒ Object



127
128
129
130
131
# File 'lib/isodoc/presentation_function/inline.rb', line 127

def text_transform(docxml)
  docxml.xpath(ns("//span[contains(@style, 'text-transform')]")).each do |s|
    text_transform1(s)
  end
end

#text_transform1(span) ⇒ Object



133
134
135
136
137
138
139
140
# File 'lib/isodoc/presentation_function/inline.rb', line 133

def text_transform1(span)
  m = span["style"].split(/;\s*/)
  i = m.index { |x| /^text-transform/.match?(x) }
  value = m[i].sub(/^text-transform:/, "")
  change_case(span, value, true)
  m[i] = "text-transform:none"
  span["style"] = m.join(";")
end

#to_ncname(ident) ⇒ Object

do not sanitise “#”



110
111
112
113
# File 'lib/isodoc/presentation_function/ids.rb', line 110

def to_ncname(ident)
  ret = ident.split("#", 2)
  ret.map { |x| Metanorma::Utils::to_ncname(x) }.join("#")
end

#to_xml_file(result, filename) ⇒ Object



166
167
168
# File 'lib/isodoc/presentation_xml_convert.rb', line 166

def to_xml_file(result, filename)
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
end

#toc(docxml) ⇒ Object



153
154
155
# File 'lib/isodoc/presentation_function/section.rb', line 153

def toc(docxml)
  toc_refs(docxml)
end

#toc_metadata(docxml) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/isodoc/presentation_function/metadata.rb', line 95

def (docxml)
  @tocfigures || @toctables || @tocrecommendations or return
  ins = extension_insert(docxml)
  @tocfigures and
    ins.add_child "<toc type='figure'><title>#{@i18n.toc_figures}</title></toc>"
  @toctables and
    ins << "<toc type='table'><title>#{@i18n.toc_tables}</title></toc>"
  @tocfigures and
    ins << "<toc type='recommendation'><title>#{@i18n.toc_recommendations}" \
    "</title></toc>"
end

#toc_refs(docxml) ⇒ Object



157
158
159
160
161
162
# File 'lib/isodoc/presentation_function/section.rb', line 157

def toc_refs(docxml)
  docxml.xpath(ns("//toc//xref[text()]")).each do |x|
    lbl = @xrefs.anchor(x["target"], :label, false) or next
    x.add_first_child "#{lbl}<span class='fmt-caption-delim'><tab/></span>"
  end
end

#toc_title(docxml) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/isodoc/presentation_function/title.rb', line 101

def toc_title(docxml)
  docxml.at(ns("//preface/clause[@type = 'toc']")) and return
  ins = toc_title_insert_pt(docxml) or return
  ins.previous = <<~CLAUSE
    <clause type = 'toc' #{add_id_text}><fmt-title depth='1'>#{@i18n.table_of_contents}</fmt-title></clause>
  CLAUSE
end

#toc_title_insert_pt(docxml) ⇒ Object



109
110
111
112
113
114
115
116
# File 'lib/isodoc/presentation_function/title.rb', line 109

def toc_title_insert_pt(docxml)
  ins = docxml.at(ns("//preface")) ||
    docxml.at(ns("//sections | //annex | //bibliography"))
      &.before("<preface> </preface>")
      &.previous_element or return nil
  ins.children.empty? and ins << " "
  ins.children.first
end

#transfer_id(old, new) ⇒ Object



46
47
48
49
50
51
# File 'lib/isodoc/presentation_function/autonum.rb', line 46

def transfer_id(old, new)
  old["id"] or return
  new["id"] = old["id"]
  old["original-id"] = old["id"]
  old.delete("id")
end

#trim_hash(hash) ⇒ Object



170
171
172
173
174
175
176
177
# File 'lib/isodoc/presentation_function/metadata.rb', line 170

def trim_hash(hash)
  loop do
    h_new = trim_hash1(hash)
    break hash if hash == h_new

    hash = h_new
  end
end

#trim_hash1(hash) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/isodoc/presentation_function/metadata.rb', line 179

def trim_hash1(hash)
  hash.is_a?(Hash) or return hash
  hash.each_with_object({}) do |(k, v), g|
    blank?(v) and next
    g[k] = case v
           when Hash then trim_hash1(hash[k])
           when Array
             hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
           else v
           end
  end
end

#twitter_cldr_localiser_symbolsObject



177
178
179
# File 'lib/isodoc/presentation_function/math.rb', line 177

def twitter_cldr_localiser_symbols
  {}
end

#ul(docxml) ⇒ Object



12
13
14
15
# File 'lib/isodoc/presentation_function/list.rb', line 12

def ul(docxml)
  docxml.xpath(ns("//ul")).each { |f| ul1(f) }
  docxml.xpath(ns("//ul/li")).each { |f| ul_label(f) }
end

#ul1(elem) ⇒ Object



17
18
19
20
# File 'lib/isodoc/presentation_function/list.rb', line 17

def ul1(elem)
  elem.at(ns("./name")) and
    prefix_name(elem, {}, "", "name") # copy name to fmt-name
end

#ul_label(elem) ⇒ Object



84
85
86
87
88
89
# File 'lib/isodoc/presentation_function/list.rb', line 84

def ul_label(elem)
  val = ul_label_value(elem)
  semx = "<semx element='autonum' source='#{elem['id'] || elem["original-id"]}'>#{val}</semx>"
  lbl = "<fmt-name>#{semx}</fmt-name>"
  elem.add_first_child(lbl)
end

#ul_label_list(_elem) ⇒ Object



74
75
76
# File 'lib/isodoc/presentation_function/list.rb', line 74

def ul_label_list(_elem)
  %w(&#x2014;)
end

#ul_label_list_from_metadata(docxml) ⇒ Object



78
79
80
81
82
# File 'lib/isodoc/presentation_function/list.rb', line 78

def (docxml)
  list = docxml.xpath(ns("//presentation-metadata/ul-label-list"))
  list.empty? and return nil
  list.map(&:text)
end

#ul_label_value(elem) ⇒ Object



91
92
93
94
95
96
# File 'lib/isodoc/presentation_function/list.rb', line 91

def ul_label_value(elem)
  depth = elem.ancestors("ul, ol").size
  val = (elem.document.root) ||
    ul_label_list(elem)
  val[(depth - 1) % val.size]
end

#unbracket(ident) ⇒ Object



80
81
82
83
84
85
# File 'lib/isodoc/presentation_function/docid.rb', line 80

def unbracket(ident)
  if ident.respond_to?(:size)
    ident.map { |x| unbracket1(x) }.join("&#xA0;/ ")
  else unbracket1(ident)
  end
end

#unbracket1(ident) ⇒ Object



74
75
76
77
78
# File 'lib/isodoc/presentation_function/docid.rb', line 74

def unbracket1(ident)
  ident.nil? and return nil
  ident.is_a?(String) or ident = xml_to_string_skip_fn(ident)
  ident.sub(/^\[/, "").sub(/\]$/, "")
end

#unnest_linkend(node) ⇒ Object

so not <origin bibitemid=“ISO7301” citeas=“ISO 7301”> <locality type=“section”><reference>3.1</reference></locality></origin>



27
28
29
30
31
32
# File 'lib/isodoc/presentation_function/inline.rb', line 27

def unnest_linkend(node)
  node.at(ns("./fmt-xref[@nested]")) or return
  node.xpath(ns("./fmt-xref[@nested]")).each { |x| x.delete("nested") }
  node.xpath(ns("./location | ./locationStack")).each(&:remove)
  node.replace(node.children)
end

#unnumbered_clause?(elem) ⇒ Boolean

Returns:

  • (Boolean)


14
15
16
17
18
# File 'lib/isodoc/presentation_function/section.rb', line 14

def unnumbered_clause?(elem)
  numbered_clause_invalid_context?(elem) ||
    @suppressheadingnumbers || elem["unnumbered"] ||
    elem.at("./ancestor::*[@unnumbered = 'true']")
end

#unwrap_definition(_elem, fmt_defn) ⇒ Object



84
85
86
87
88
89
90
91
# File 'lib/isodoc/presentation_function/terms.rb', line 84

def unwrap_definition(_elem, fmt_defn)
  fmt_defn.xpath(ns(".//semx[@element = 'definition']")).each do |d|
    %w(verbal-definition non-verbal-representation).each do |e|
      v = d&.at(ns("./#{e}"))
      v&.replace(v.children)
    end
  end
end

#validate(docxml) ⇒ Object



58
59
60
# File 'lib/isodoc/presentation_xml_convert.rb', line 58

def validate(docxml)
  id_validate(docxml)
end

#variant(xml) ⇒ Object

there should be no //variant in bibdata now



79
80
81
82
83
84
85
86
87
88
# File 'lib/isodoc/presentation_function/inline.rb', line 79

def variant(xml)
  b = xml.xpath(ns("//bibdata//variant"))
  (xml.xpath(ns("//variant")) - b).each { |f| variant1(f) }
  (xml.xpath(ns("//variant[@remove = 'true']")) - b).each(&:remove)
  (xml.xpath(ns("//variant")) - b).each do |v|
    v.next&.name == "variant" or next
    v.next = "/"
  end
  (xml.xpath(ns("//variant")) - b).each { |f| f.replace(f.children) }
end

#variant1(node) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/isodoc/presentation_function/inline.rb', line 90

def variant1(node)
  if !((!node["lang"] || node["lang"] == @lang) &&
      (!node["script"] || node["script"] == @script)) &&
      found_matching_variant_sibling(node)
    node["remove"] = "true"
  end
end

#xml_encode_attr(str) ⇒ Object



134
135
136
137
138
139
# File 'lib/isodoc/presentation_function/index.rb', line 134

def xml_encode_attr(str)
  HTMLEntities.new.encode(str, :basic, :hexadecimal)
    .gsub(/&#x([^;]+);/) do |_x|
    "&#x#{$1.upcase};"
  end
end

#xml_to_string_skip_fn(node) ⇒ Object



55
56
57
58
59
# File 'lib/isodoc/presentation_function/docid.rb', line 55

def xml_to_string_skip_fn(node)
  node1 = node.dup
  node1.xpath(ns(".//fn")).each(&:remove)
  to_xml(node1.children)
end

#xref(docxml) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/isodoc/presentation_function/inline.rb', line 41

def xref(docxml)
  docxml.xpath(ns("//fmt-xref")).each { |f| xref1(f) }
  docxml.xpath(ns("//fmt-xref//fmt-xref")).each do |f|
    f.replace(f.children)
  end
  docxml.xpath(ns("//fmt-xref//xref")).each { |f| f.replace(f.children) }
end

#xref1(node) ⇒ Object



71
72
73
74
# File 'lib/isodoc/presentation_function/inline.rb', line 71

def xref1(node)
  sem_xml_descendant?(node) and return
  get_linkend(node)
end

#xref_empty?(node) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
37
# File 'lib/isodoc/presentation_function/inline.rb', line 34

def xref_empty?(node)
  c1 = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
  c1.empty?
end

#xref_new_contenthash_id(docxml, ids) ⇒ Object



133
134
135
136
137
138
139
140
141
# File 'lib/isodoc/presentation_function/ids.rb', line 133

def xref_new_contenthash_id(docxml, ids)
  Metanorma::Utils::anchor_attributes(presxml: true).each do |e|
    docxml.xpath("//xmlns:#{e[0]}[@#{e[1]}]").each do |x|
      ids.has_key?(x[e[1]]) or next
      ids[x[e[1]]] or next
      x[e[1]] = ids[x[e[1]]]
    end
  end
end