metanorma-ieee 1.5.3 → 1.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isodoc/ieee/html/header.html +3 -3
  3. data/lib/isodoc/ieee/html/html_ieee_titlepage.html +15 -2
  4. data/lib/isodoc/ieee/html/htmlstyle.css +160 -46
  5. data/lib/isodoc/ieee/html/htmlstyle.scss +96 -0
  6. data/lib/isodoc/ieee/html/ieee.css +46 -1
  7. data/lib/isodoc/ieee/html/ieee.scss +42 -1
  8. data/lib/isodoc/ieee/html/word_ieee_titlepage.html +10 -2
  9. data/lib/isodoc/ieee/html/wordstyle.css +48 -0
  10. data/lib/isodoc/ieee/html/wordstyle.scss +44 -0
  11. data/lib/isodoc/ieee/html/wordstyle_wp.css +47 -0
  12. data/lib/isodoc/ieee/html/wordstyle_wp.scss +43 -0
  13. data/lib/isodoc/ieee/html_convert.rb +5 -0
  14. data/lib/isodoc/ieee/i18n-en.yaml +3 -0
  15. data/lib/isodoc/ieee/ieee.amendment.xsl +1526 -964
  16. data/lib/isodoc/ieee/ieee.standard.xsl +1526 -964
  17. data/lib/isodoc/ieee/metadata.rb +22 -11
  18. data/lib/isodoc/ieee/presentation_bibitem.rb +103 -0
  19. data/lib/isodoc/ieee/presentation_ref.rb +169 -97
  20. data/lib/isodoc/ieee/presentation_terms.rb +52 -12
  21. data/lib/isodoc/ieee/presentation_xml_convert.rb +24 -75
  22. data/lib/isodoc/ieee/word_authority.rb +37 -59
  23. data/lib/isodoc/ieee/word_cleanup.rb +83 -35
  24. data/lib/isodoc/ieee/word_cleanup_blocks.rb +0 -1
  25. data/lib/isodoc/ieee/word_convert.rb +19 -16
  26. data/lib/isodoc/ieee/word_toc.rb +46 -0
  27. data/lib/metanorma/ieee/boilerplate.adoc +6 -5
  28. data/lib/metanorma/ieee/boilerplate_wp.adoc +1 -2
  29. data/lib/metanorma/ieee/cleanup.rb +69 -15
  30. data/lib/metanorma/ieee/cleanup_boilerplate.rb +1 -4
  31. data/lib/metanorma/ieee/cleanup_ref.rb +33 -106
  32. data/lib/metanorma/ieee/cleanup_ref_fn.rb +117 -0
  33. data/lib/metanorma/ieee/front.rb +14 -0
  34. data/lib/metanorma/ieee/isodoc.rng +44 -19
  35. data/lib/metanorma/ieee/processor.rb +1 -0
  36. data/lib/metanorma/ieee/relaton-ieee.rng +4 -0
  37. data/lib/metanorma/ieee/validate.rb +1 -1
  38. data/lib/metanorma/ieee/version.rb +1 -1
  39. data/lib/relaton/render/config.yml +10 -3
  40. metadata +5 -2
@@ -54,6 +54,20 @@ module IsoDoc
54
54
  wg(xml)
55
55
  bg(xml)
56
56
  program(xml)
57
+ coverpage_stmt(xml)
58
+ end
59
+
60
+ def agency(xml)
61
+ super
62
+ logos = xml.xpath(ns("//bibdata/contributor[xmlns:role/@type = 'author']/" \
63
+ "organization/logo/image/@src"))
64
+ set(:corporate_author_logos, logos.map { |l| to_datauri(l.value) })
65
+ set(:corporate_author_logo_attrs, contrib_logo_attrs(xml, "author"))
66
+ end
67
+
68
+ def coverpage_stmt(xml)
69
+ p = xml.at(ns("//presentation-metadata/coverpage-statement")) and
70
+ set(:coverpage_statement, p.children.to_xml)
57
71
  end
58
72
 
59
73
  def program(xml)
@@ -105,6 +119,8 @@ module IsoDoc
105
119
  set(:stdid_pdf, dn&.text || "STDXXXXX")
106
120
  dn = isoxml.at(ns("//#{id}[@scope = 'print']"))
107
121
  set(:stdid_print, dn&.text || "STDPDXXXXX")
122
+ dn = isoxml.at(ns("//bibdata/docidentifier[@type = 'IEEE-draft']")) and
123
+ set(:docid_draft, dn.text)
108
124
  dn = isoxml.at(ns("//bibdata/ext/structuredidentifier/amendment")) and
109
125
  set(:amd, dn.text)
110
126
  dn = isoxml.at(ns("//bibdata/ext/structuredidentifier/corrigendum")) and
@@ -114,18 +130,13 @@ module IsoDoc
114
130
  def title(isoxml, _out)
115
131
  metadata_parse_init(isoxml)
116
132
  super
117
- draft = isoxml.at(ns("//bibdata/version/draft"))
118
133
  doctype(isoxml, _out)
119
- set(:full_doctitle, fulltitle(@metadata[:doctype], draft))
120
- set(:abbrev_doctitle, fulltitle(@metadata[:doctype_abbrev], draft))
121
- prov = isoxml.at(ns("//bibdata/title[@type='provenance']")) and
122
- set(:provenance_doctitle, Common::to_xml(prov.children))
123
- end
124
-
125
- def fulltitle(type, draft)
126
- title = "#{type || '???'} for #{@metadata[:doctitle] || '???'}"
127
- draft and title = "Draft #{title}"
128
- title
134
+ { doctitle: "title-main", full_doctitle: "main",
135
+ abbrev_doctitle: "title-abbrev", provenance_doctitle: "provenance" }
136
+ .each do |k, v|
137
+ t = isoxml.at(ns("//bibdata/title[@type='#{v}']")) and
138
+ set(k, Common::to_xml(t.children))
139
+ end
129
140
  end
130
141
 
131
142
  def metadata_parse_init(isoxml)
@@ -0,0 +1,103 @@
1
+ require_relative "../../relaton/render/general"
2
+
3
+ module IsoDoc
4
+ module Ieee
5
+ class PresentationXMLConvert < IsoDoc::PresentationXMLConvert
6
+ def references_render(docxml)
7
+ @author = {}
8
+ super
9
+ end
10
+
11
+ def bibrender_relaton(xml, renderings)
12
+ bibrender_relaton1(xml, renderings)
13
+ author_date(xml, renderings)
14
+ @author[xml["id"]] = renderings[xml["id"]][:author]
15
+ end
16
+
17
+ def bibrender_relaton1(xml, renderings)
18
+ f = renderings[xml["id"]][:formattedref] or return
19
+ fn = availability_note(xml)
20
+ f = "<formattedref>#{f}#{fn}</formattedref>"
21
+ if x = xml.at(ns("./formattedref"))
22
+ x.replace(f)
23
+ elsif xml.children.empty?
24
+ xml << f
25
+ else
26
+ xml.children.first.previous = f
27
+ end
28
+ end
29
+
30
+ def author_date(xml, renderings)
31
+ author_date?(xml) or return
32
+ cit = renderings[xml["id"]][:citation]
33
+ xml << "<docidentifier type='metanorma'>#{cit}</docidentifier>"
34
+ xml.at(ns("./biblio-tag"))&.remove
35
+ xml << "<biblio-tag>#{cit}, </biblio-tag>"
36
+ end
37
+
38
+ def author_date?(xml)
39
+ ret = !xml["type"]
40
+ ret ||= %w(standard techreport website webresource)
41
+ .include?(xml["type"])
42
+ ret ||= xml.at(".//ancestor::xmlns:references[@normative = 'false']")
43
+ ret ||= xml.at(ns("./docidentifier[@type = 'metanorma']"))
44
+ ret and return false
45
+ true
46
+ end
47
+
48
+ def creatornames(bib)
49
+ ::Relaton::Render::Ieee::General
50
+ .new(language: @lang, i18nhash: @i18n.get,
51
+ # template: { (bib["type"] || "misc").to_sym =>
52
+ # "{{ creatornames }}" },
53
+ template: "{{ creatornames }}",
54
+ extenttemplate: { (bib["type"] || "misc").to_sym => "{{page}}" },
55
+ sizetemplate: { (bib["type"] || "misc").to_sym => "{{data}}" })
56
+ .render1(RelatonBib::XMLParser.from_xml(bib.to_xml))
57
+ end
58
+
59
+ def bibliography_bibitem_number1(bibitem, idx, normative)
60
+ bibitem.xpath(ns(".//docidentifier[@type = 'metanorma' or " \
61
+ "@type = 'metanorma-ordinal']")).each do |mn|
62
+ /^\[?B?\d\]?$/.match?(mn&.text) and mn.remove
63
+ end
64
+ unless bibliography_bibitem_number_skip(bibitem) || normative
65
+ idx += 1
66
+ docidentifier_insert_pt(bibitem).next =
67
+ "<docidentifier type='metanorma-ordinal'>[B#{idx}]</docidentifier>"
68
+ end
69
+ idx
70
+ end
71
+
72
+ def docidentifier_insert_pt(bibitem)
73
+ bibitem.at(ns(".//docidentifier"))&.previous ||
74
+ bibitem.at(ns(".//title")) ||
75
+ bibitem.at(ns(".//formattedref"))
76
+ end
77
+
78
+ def availability_note(bib)
79
+ notes = bib.xpath(ns("./note[@type = 'Availability']"))
80
+ notes.map do |note|
81
+ id = UUIDTools::UUID.random_create.to_s
82
+ @new_ids[id] = nil
83
+ "<fn id='#{id}' reference='#{id}'><p>#{note.content}</p></fn>"
84
+ end.join
85
+ end
86
+
87
+ def omit_docid_prefix(prefix)
88
+ prefix == "DOI" and return true
89
+ prefix == "title" and return true
90
+ super
91
+ end
92
+
93
+ def bracket_if_num(num)
94
+ num.nil? and return nil
95
+ ret = num.dup
96
+ ret.xpath(ns(".//fn")).each(&:remove)
97
+ ret = ret.text.strip.sub(/^\[/, "").sub(/\]$/, "")
98
+ /^B?\d+$/.match?(ret) and return "[#{ret}]"
99
+ ret
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,142 +1,214 @@
1
- require_relative "../../relaton/render/general"
2
-
3
1
  module IsoDoc
4
2
  module Ieee
5
3
  class PresentationXMLConvert < IsoDoc::PresentationXMLConvert
4
+ def xref_empty?(node)
5
+ if node["citeas"] &&
6
+ @bibanchors[node["bibitemid"]] && !node.children.empty?
7
+ true
8
+ else super
9
+ end
10
+ end
11
+
12
+ def inline(docxml)
13
+ @bibanchors ||= biblio_ids_titles(docxml, false)
14
+ @normrefanchors ||= biblio_ids_titles(docxml, true)
15
+ super
16
+ end
17
+
6
18
  # Style manual 19
7
19
  def anchor_linkend(node, linkend)
8
- @bibanchors ||= biblio_ids_titles(node.document)
9
20
  if node["citeas"] && i = @bibanchors[node["bibitemid"]]
10
- biblio_anchor_linkend(node, i)
21
+ biblio_anchor_linkend(node, i, linkend)
22
+ elsif node["citeas"] && (i = @normrefanchors[node["bibitemid"]])
23
+ cit = normref_anchor_linkend(node, i)
24
+ cit || super
11
25
  else super
12
26
  end
13
27
  end
14
28
 
15
- def biblio_anchor_linkend(node, bib)
16
- if %w(techreport standard).include?(bib[:type])
17
- [node["citeas"], bib[:ord]].compact.join(" ")
18
- elsif bib[:author]
19
- "#{bib[:author]} " + node["citeas"]
20
- else
21
- node["citeas"]
22
- end
29
+ # force Author-Date referencing on non-standards in norm ref
30
+ def normref_anchor_linkend(node, bib)
31
+ @ref_renderings or return nil
32
+ %w(standard).include?(bib[:type]) and return nil
33
+ cit = @ref_renderings[node["bibitemid"]][:citation]&.strip
34
+ cit.empty? and cit = nil
35
+ cit
23
36
  end
24
37
 
25
- def biblio_ids_titles(xmldoc)
26
- xmldoc.xpath(ns("//references[@normative = 'false']/bibitem"))
27
- .each_with_object({}) do |b, m|
28
- m[b["id"]] =
29
- { docid: pref_ref_code(b), type: b["type"],
30
- title: (b.at(ns("./title")) ||
31
- b.at(ns("./formattedref")))&.text,
32
- author: @author[b["id"]] || (b.at(ns("./title")) ||
33
- b.at(ns("./formattedref")))&.text,
34
- ord: b.at(ns("./docidentifier[@type = 'metanorma' or " \
35
- "@type = 'metanorma-ordinal']"))&.text }
38
+ def biblio_anchor_linkend(node, bib, linkend)
39
+ if %w(standard).include?(bib[:type])
40
+ biblio_anchor_linkend_std(node, bib, linkend)
41
+ else biblio_anchor_linkend_nonstd(node, bib)
36
42
  end
37
43
  end
38
44
 
39
- def citestyle
40
- "author-date"
45
+ def linkend_content(node)
46
+ c1 = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
47
+ c2 = node.xpath(ns("./locality | ./localityStack"))
48
+ [c1, c2]
41
49
  end
42
50
 
43
- def references_render(docxml)
44
- @author = {}
45
- super
51
+ def biblio_anchor_linkend_std(node, bib, linkend)
52
+ c1, c2 = linkend_content(node)
53
+ node["style"] == "no-biblio-tag" or tag = bib[:ord]
54
+ if !c1.empty?
55
+ c2.each(&:remove)
56
+ c1.map(&:to_xml).join
57
+ elsif node.at(ns("./location"))
58
+ linkend
59
+ elsif node["citeas"] == bib[:ord] then node["citeas"]
60
+ else [linkend, tag].compact.join(" ")
61
+ end
46
62
  end
47
63
 
48
- def bibrender_relaton(xml, renderings)
49
- bibrender_relaton1(xml, renderings)
50
- author_date(xml, renderings)
51
- @author[xml["id"]] = renderings[xml["id"]][:author]
64
+ def biblio_anchor_linkend_nonstd(node, bib)
65
+ c1, c2 = linkend_content(node)
66
+ node["style"] == "no-biblio-tag" or tag = node["citeas"]
67
+ if !c1.empty?
68
+ c2.each(&:remove)
69
+ "#{c1.map(&:to_xml).join} #{tag}".strip
70
+ elsif node.at(ns("./location"))
71
+ tag
72
+ elsif node["style"] == "title" && bib[:title]
73
+ "#{bib[:title]} #{tag}".strip
74
+ elsif bib[:author] # default, also if node["style"] == "title"
75
+ "#{bib[:author]} #{tag}".strip
76
+ else tag.strip
77
+ end
52
78
  end
53
79
 
54
- def bibrender_relaton1(xml, renderings)
55
- f = renderings[xml["id"]][:formattedref] or return
56
- fn = availability_note(xml)
57
- f = "<formattedref>#{f}#{fn}</formattedref>"
58
- if x = xml.at(ns("./formattedref"))
59
- x.replace(f)
60
- elsif xml.children.empty?
61
- xml << f
62
- else
63
- xml.children.first.previous = f
80
+ def biblio_ids_titles(xmldoc, normative)
81
+ xmldoc.xpath(ns("//references[@normative = '#{normative}']/bibitem"))
82
+ .each_with_object({}) do |b, acc|
83
+ biblio_ids_titles1(b, acc)
64
84
  end
65
85
  end
66
86
 
67
- def author_date(xml, renderings)
68
- author_date?(xml) or return
69
- cit = renderings[xml["id"]][:citation]
70
- xml << "<docidentifier type='metanorma'>#{cit}</docidentifier>"
71
- xml.at(ns("./biblio-tag"))&.remove
72
- xml << "<biblio-tag>#{cit}, </biblio-tag>"
87
+ def biblio_ids_titles1(bib, acc)
88
+ acc[bib["id"]] =
89
+ { docid: pref_ref_code(bib), type: bib["type"],
90
+ title: bib.at(ns("./title")) || bib.at(ns("./formattedref")),
91
+ author: @author[bib["id"]] || (bib.at(ns("./title")) ||
92
+ bib.at(ns("./formattedref"))),
93
+ ord: bib.at(ns("./docidentifier[@type = 'metanorma' or " \
94
+ "@type = 'metanorma-ordinal']")) }
95
+ %i(title author ord).each do |k|
96
+ acc[bib["id"]][k].is_a?(Nokogiri::XML::Node) and
97
+ acc[bib["id"]][k] = acc[bib["id"]][k].text
98
+ end
73
99
  end
74
100
 
75
- def author_date?(xml)
76
- ret = !xml["type"]
77
- ret ||= %w(standard techreport website webresource)
78
- .include?(xml["type"])
79
- ret ||= xml.at(".//ancestor::xmlns:references[@normative = 'false']")
80
- ret ||= xml.at(ns("./docidentifier[@type = 'metanorma']"))
81
- ret and return false
82
- true
101
+ def citestyle
102
+ "author-date"
83
103
  end
84
104
 
85
- def creatornames(bib)
86
- ::Relaton::Render::Ieee::General
87
- .new(language: @lang, i18nhash: @i18n.get,
88
- # template: { (bib["type"] || "misc").to_sym =>
89
- # "{{ creatornames }}" },
90
- template: "{{ creatornames }}",
91
- extenttemplate: { (bib["type"] || "misc").to_sym => "{{page}}" },
92
- sizetemplate: { (bib["type"] || "misc").to_sym => "{{data}}" })
93
- .render1(RelatonBib::XMLParser.from_xml(bib.to_xml))
105
+ def expand_citeas(text)
106
+ std_docid_semantic(super)
94
107
  end
95
108
 
96
- def bibliography_bibitem_number1(bibitem, idx, normative)
97
- bibitem.xpath(ns(".//docidentifier[@type = 'metanorma' or " \
98
- "@type = 'metanorma-ordinal']")).each do |mn|
99
- /^\[?B?\d\]?$/.match?(mn&.text) and mn.remove
100
- end
101
- unless bibliography_bibitem_number_skip(bibitem) || normative
102
- idx += 1
103
- docidentifier_insert_pt(bibitem).next =
104
- "<docidentifier type='metanorma-ordinal'>[B#{idx}]</docidentifier>"
109
+ def eref_localities_conflated(refs, target, node)
110
+ droploc = node["droploc"]
111
+ node["droploc"] = true
112
+ ret = resolve_eref_connectives(eref_locality_stacks(refs, target,
113
+ node))
114
+ node["droploc"] = droploc
115
+ p = prefix_clause(target, refs.first.at(ns("./locality")))
116
+ eref_localities1({ target: target, number: "pl",
117
+ type: p,
118
+ from: l10n(ret[1..-1].join), node: node,
119
+ lang: @lang })
120
+ end
121
+
122
+ def prefix_clause(target, loc)
123
+ loc["type"] == "clause" or return loc["type"]
124
+ if subclause?(target, loc["type"],
125
+ loc&.at(ns("./referenceFrom"))&.text)
126
+ ""
127
+ else "clause"
105
128
  end
106
- idx
107
129
  end
108
130
 
109
- def docidentifier_insert_pt(bibitem)
110
- bibitem.at(ns(".//docidentifier"))&.previous ||
111
- bibitem.at(ns(".//title")) ||
112
- bibitem.at(ns(".//formattedref"))
131
+ def subclause?(target, type, from)
132
+ (from&.include?(".") && type == "clause") ||
133
+ target&.gsub(/<[^<>]+>/, "")&.match?(/^IEV$|^IEC 60050-/)
113
134
  end
114
135
 
115
- def expand_citeas(text)
116
- std_docid_semantic(super)
136
+ def eref_localities1(opt)
137
+ opt[:type] == "anchor" and return nil
138
+ opt[:type].downcase!
139
+ opt[:lang] == "zh" and return l10n(eref_localities1_zh(opt))
140
+ ret = ""
141
+ opt[:node]["droploc"] != "true" &&
142
+ !subclause?(opt[:target], opt[:type], opt[:from]) and
143
+ ret = eref_locality_populate(opt[:type], opt[:node], opt[:number])
144
+ ret += " #{opt[:from]}" if opt[:from]
145
+ ret += "&#x2013;#{opt[:upto]}" if opt[:upto]
146
+ ret += ")" if opt[:type] == "list"
147
+ l10n(ret)
148
+ end
149
+
150
+ def anchor_linkend1(node)
151
+ linkend = @xrefs.anchor(node["target"], :xref)
152
+ @xrefs.anchor(node["target"], :type) == "clause" &&
153
+ @xrefs.anchor(node["target"], :level) > 1 &&
154
+ !start_of_sentence(node) and
155
+ linkend = strip_initial_clause(linkend)
156
+ container = @xrefs.anchor(node["target"], :container, false)
157
+ linkend = prefix_container(container, linkend, node, node["target"])
158
+ capitalise_xref(node, linkend, anchor_value(node["target"]))
117
159
  end
118
160
 
119
- def availability_note(bib)
120
- notes = bib.xpath(ns("./note[@type = 'Availability']"))
121
- notes.map do |note|
122
- id = UUIDTools::UUID.random_create.to_s
123
- @new_ids[id] = nil
124
- "<fn id='#{id}' reference='#{id}'><p>#{note.content}</p></fn>"
125
- end.join
161
+ def strip_initial_clause(linkend)
162
+ x = Nokogiri::XML("<a>#{linkend}</a>")
163
+ x.at(".//span[@class = 'fmt-element-name']")&.remove
164
+ to_xml(x.elements.first.children).strip
126
165
  end
127
166
 
128
- def omit_docid_prefix(prefix)
129
- prefix == "DOI" and return true
167
+ def eref_locality_populate(type, node, number)
168
+ type == "page" and return ""
130
169
  super
131
170
  end
132
171
 
133
- def bracket_if_num(num)
134
- num.nil? and return nil
135
- ret = num.dup
136
- ret.xpath(ns(".//fn")).each(&:remove)
137
- ret = ret.text.strip.sub(/^\[/, "").sub(/\]$/, "")
138
- /^B?\d+$/.match?(ret) and return "[#{ret}]"
139
- ret
172
+ def first_biblio_eref_fn(docxml)
173
+ @bibanchors ||= biblio_ids_titles(docxml)
174
+ docxml.xpath("//*[@citeas]").each do |node|
175
+ @bibanchors[node["bibitemid"]] or next
176
+ node.children.empty? or next
177
+ insert_biblio_footnote(node, docxml)
178
+ break
179
+ end
180
+ end
181
+
182
+ private
183
+
184
+ def insert_biblio_footnote(node, docxml)
185
+ n = node.next_sibling
186
+ # Check if the next sibling is a text node that starts with punctuation
187
+ if n&.text? && (match = n.content.match(/^([.,;:])(?=\s|$)/))
188
+ insert_biblio_footnote_with_punctuation1(n, match, docxml)
189
+ else # Default behavior: insert footnote immediately after the node
190
+ node.next = biblio_ref_inform_fn
191
+ end
192
+ end
193
+
194
+ # If so, split the text at the punctuation
195
+ # and replace the text node with punctuation + footnote + remaining text
196
+ def insert_biblio_footnote_with_punctuation1(node, match, docxml)
197
+ punct = match[0]
198
+ remaining_text = node.content[punct.length..-1]
199
+ node.content = punct
200
+ node.add_next_sibling(biblio_ref_inform_fn)
201
+ remaining_text && !remaining_text.empty? and
202
+ node.next_sibling
203
+ .add_next_sibling(Nokogiri::XML::Text.new(
204
+ remaining_text, docxml
205
+ ))
206
+ end
207
+
208
+ def biblio_ref_inform_fn
209
+ <<~XML
210
+ <fn reference='#{UUIDTools::UUID.random_create}'><p>#{@i18n.biblio_ref_inform_fn}</p></fn>
211
+ XML
140
212
  end
141
213
  end
142
214
  end
@@ -31,11 +31,21 @@ module IsoDoc
31
31
  end
32
32
  end
33
33
 
34
- def wrap_nodeset_in_parens(xpath)
35
- unless xpath.empty?
36
- xpath[0].previous = " ("
37
- xpath[-1].next = ")"
38
- end
34
+ def wrap_termsource_in_parens(xpath)
35
+ xpath.empty? and return xpath
36
+ opening_paren = Nokogiri::XML::Node.new("span", xpath[0].document)
37
+ opening_paren["class"] = "fmt-termsource-delim"
38
+ opening_paren.content = "("
39
+ xpath[0].add_previous_sibling(opening_paren)
40
+ closing_paren = Nokogiri::XML::Node.new("span", xpath[-1].document)
41
+ closing_paren["class"] = "fmt-termsource-delim"
42
+ closing_paren.content = ")"
43
+ xpath[-1].add_next_sibling(closing_paren)
44
+ # Return expanded nodeset including parentheses
45
+ parent = xpath[0].parent
46
+ start_index = parent.children.index(opening_paren)
47
+ end_index = parent.children.index(closing_paren)
48
+ parent.children[start_index..end_index]
39
49
  end
40
50
 
41
51
  def unwrap_definition1(d)
@@ -44,11 +54,15 @@ module IsoDoc
44
54
  if v.elements.all? { |n| %w(source p).include?(n.name) }
45
55
  p = v.xpath(ns("./p"))
46
56
  s = v.xpath(ns("./source"))
47
- s.empty? or s = " (#{s.map { |x| to_xml(x) }.join})"
57
+ s = wrap_termsource_in_parens(s) unless s.empty?
48
58
  v.children =
49
- "#{p.map(&:children).map { |x| to_xml(x) }.join("\n")}#{s}"
59
+ "#{p.map(&:children).map do |x|
60
+ to_xml(x)
61
+ end.join("\n")}#{s.map do |x|
62
+ to_xml(x)
63
+ end.join}"
50
64
  else
51
- wrap_nodeset_in_parens(v.xpath(ns("./source")))
65
+ wrap_termsource_in_parens(v.xpath(ns("./source")))
52
66
  end
53
67
  v.replace(v.children)
54
68
  end
@@ -120,15 +134,19 @@ module IsoDoc
120
134
  end
121
135
 
122
136
  def collapse_term_template_tail(opt)
123
- opt[:source] and src = "(#{to_xml(opt[:source].children).strip})"
124
- opt[:fns].empty? or fn = opt[:fns].map(&:to_xml).join
125
- "#{collapse_term_related(opt[:rels])} #{src}#{fn}"
137
+ if opt[:source]
138
+ # For this context, we need to use the old string-based approach
139
+ # since the source element has been removed from its parent
140
+ src = "<span class='fmt-termsource-delim'>(</span>#{to_xml(opt[:source].children).strip}<span class='fmt-termsource-delim'>)</span>"
141
+ end
142
+ opt[:fns].empty? or fn = opt[:fns].map { |f| to_xml(f) }.join
143
+ "#{collapse_term_related(opt[:rels])} #{src}#{fn}".strip
126
144
  end
127
145
 
128
146
  def collapse_term_pref(opt)
129
147
  p = opt[:pref]
130
148
  p.text.strip.empty? and return "**TERM NOT FOUND**"
131
- wrap_nodeset_in_parens(p.xpath(ns(".//semx[@element = 'source']")))
149
+ wrap_termsource_in_parens(p.xpath(ns(".//semx[@element = 'source']")))
132
150
  p.xpath(ns(".//fmt-termsource")).each { |x| x.replace(x.children) }
133
151
  to_xml(p.children).strip
134
152
  end
@@ -172,6 +190,28 @@ module IsoDoc
172
190
  end
173
191
 
174
192
  def term(docxml); end
193
+
194
+ def license_termnote(elem, idx)
195
+ elem.name = "fn"
196
+ elem["reference"] = "_termnote_license_#{idx}"
197
+ elem.parent << elem
198
+ end
199
+
200
+ def termsource_brackets(docxml)
201
+ docxml.xpath(ns("//term//semx[@element = 'source']")).each do |s|
202
+ text = termsource_text_content(s)
203
+ text&.include?("(") && text.include?(")") or next
204
+ prevbr = s.at("./preceding-sibling::xmlns:span[@class='fmt-termsource-delim']")
205
+ nextbr = s.at("./following-sibling::xmlns:span[@class='fmt-termsource-delim']")
206
+ prevbr.children = "["
207
+ nextbr.children = "]"
208
+ end
209
+ end
210
+
211
+ def termsource_text_content(span)
212
+ span.dup.xpath(ns(".//localityStack | .//locality")).each(&:remove)
213
+ .text
214
+ end
175
215
  end
176
216
  end
177
217
  end