isodoc 2.10.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/isodoc.gemspec +9 -4
  4. data/lib/isodoc/base_style/all.css +96 -0
  5. data/lib/isodoc/base_style/reset.css +96 -0
  6. data/lib/isodoc/base_style/reset.scss +75 -0
  7. data/lib/isodoc/base_style/scripts.html +45 -14
  8. data/lib/isodoc/class_utils.rb +4 -2
  9. data/lib/isodoc/convert.rb +0 -21
  10. data/lib/isodoc/css.rb +2 -4
  11. data/lib/isodoc/function/blocks.rb +37 -52
  12. data/lib/isodoc/function/blocks_example_note.rb +75 -29
  13. data/lib/isodoc/function/cleanup.rb +9 -44
  14. data/lib/isodoc/function/inline.rb +67 -13
  15. data/lib/isodoc/function/lists.rb +20 -14
  16. data/lib/isodoc/function/references.rb +9 -126
  17. data/lib/isodoc/function/reqt.rb +4 -3
  18. data/lib/isodoc/function/section.rb +30 -35
  19. data/lib/isodoc/function/section_titles.rb +22 -11
  20. data/lib/isodoc/function/table.rb +3 -3
  21. data/lib/isodoc/function/terms.rb +49 -26
  22. data/lib/isodoc/function/to_word_html.rb +46 -16
  23. data/lib/isodoc/function/utils.rb +11 -12
  24. data/lib/isodoc/gem_tasks.rb +1 -1
  25. data/lib/isodoc/html_function/footnotes.rb +2 -1
  26. data/lib/isodoc/html_function/html.rb +5 -7
  27. data/lib/isodoc/html_function/postprocess.rb +25 -6
  28. data/lib/isodoc/html_function/postprocess_cover.rb +13 -7
  29. data/lib/isodoc/html_function/postprocess_footnotes.rb +52 -47
  30. data/lib/isodoc/init.rb +31 -0
  31. data/lib/isodoc/metadata.rb +20 -13
  32. data/lib/isodoc/metadata_contributor.rb +5 -10
  33. data/lib/isodoc/metadata_date.rb +1 -1
  34. data/lib/isodoc/presentation_function/autonum.rb +153 -0
  35. data/lib/isodoc/presentation_function/bibdata.rb +4 -5
  36. data/lib/isodoc/presentation_function/block.rb +107 -40
  37. data/lib/isodoc/presentation_function/concepts.rb +184 -19
  38. data/lib/isodoc/presentation_function/docid.rb +78 -0
  39. data/lib/isodoc/presentation_function/erefs.rb +55 -31
  40. data/lib/isodoc/presentation_function/image.rb +64 -19
  41. data/lib/isodoc/presentation_function/index.rb +180 -0
  42. data/lib/isodoc/presentation_function/inline.rb +47 -16
  43. data/lib/isodoc/presentation_function/math.rb +128 -71
  44. data/lib/isodoc/presentation_function/metadata.rb +29 -66
  45. data/lib/isodoc/presentation_function/refs.rb +75 -28
  46. data/lib/isodoc/presentation_function/reqt.rb +7 -4
  47. data/lib/isodoc/presentation_function/section.rb +51 -129
  48. data/lib/isodoc/presentation_function/sourcecode.rb +52 -19
  49. data/lib/isodoc/presentation_function/terms.rb +107 -118
  50. data/lib/isodoc/presentation_function/title.rb +107 -0
  51. data/lib/isodoc/presentation_function/xrefs.rb +37 -17
  52. data/lib/isodoc/presentation_xml_convert.rb +24 -10
  53. data/lib/isodoc/version.rb +1 -1
  54. data/lib/isodoc/word_function/body.rb +9 -37
  55. data/lib/isodoc/word_function/comments.rb +0 -1
  56. data/lib/isodoc/word_function/footnotes.rb +1 -1
  57. data/lib/isodoc/word_function/lists.rb +13 -9
  58. data/lib/isodoc/word_function/postprocess.rb +6 -0
  59. data/lib/isodoc/word_function/postprocess_cover.rb +6 -4
  60. data/lib/isodoc/word_function/postprocess_table.rb +1 -1
  61. data/lib/isodoc/word_function/postprocess_toc.rb +10 -6
  62. data/lib/isodoc/word_function/table.rb +2 -2
  63. data/lib/isodoc/xref/clause_order.rb +41 -0
  64. data/lib/isodoc/xref/xref_anchor.rb +31 -16
  65. data/lib/isodoc/xref/xref_counter.rb +18 -3
  66. data/lib/isodoc/xref/xref_counter_types.rb +14 -0
  67. data/lib/isodoc/xref/xref_gen.rb +61 -37
  68. data/lib/isodoc/xref/xref_gen_seq.rb +148 -81
  69. data/lib/isodoc/xref/xref_sect_gen.rb +84 -88
  70. data/lib/isodoc/xref/xref_util.rb +53 -4
  71. data/lib/isodoc/xref.rb +29 -10
  72. data/lib/isodoc/xslfo_convert.rb +14 -9
  73. data/lib/isodoc-yaml/i18n-ar.yaml +17 -13
  74. data/lib/isodoc-yaml/i18n-de.yaml +17 -13
  75. data/lib/isodoc-yaml/i18n-en.yaml +18 -17
  76. data/lib/isodoc-yaml/i18n-es.yaml +17 -13
  77. data/lib/isodoc-yaml/i18n-fr.yaml +17 -13
  78. data/lib/isodoc-yaml/i18n-ja.yaml +56 -52
  79. data/lib/isodoc-yaml/i18n-ru.yaml +17 -16
  80. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +17 -13
  81. data/lib/nokogiri/xml/node.rb +14 -0
  82. data/lib/relaton/render-isodoc/config.yml +1 -1
  83. metadata +90 -13
@@ -0,0 +1,153 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def prefix_name(node, delims, label, elem)
4
+ label, delims = prefix_name_defaults(node, delims, label)
5
+ name, ins, ids, number = prefix_name_prep(node, elem)
6
+ ins.next = fmt_xref_label(label, number, ids)
7
+ # autonum can be empty, e.g single note in clause: "NOTE []"
8
+ number and node["autonum"] = number.gsub(/<[^>]+>/, "")
9
+ !node.at(ns("./fmt-#{elem}")) &&
10
+ (c = fmt_caption(label, elem, name, ids, delims)) and ins.next = c
11
+ prefix_name_postprocess(node, elem)
12
+ end
13
+
14
+ def prefix_name_defaults(node, delims, label)
15
+ label&.empty? and label = nil
16
+ delims.nil? and delims = {}
17
+ [label, delims]
18
+ end
19
+
20
+ def prefix_name_prep(node, elem)
21
+ lbls = prefix_name_labels(node)
22
+ name = node.at(ns("./#{elem}")) and name["id"] = lbls[:name]
23
+ ins = name || node.add_first_child("<sentinel/>").elements.first
24
+ node["unnumbered"] or
25
+ number = @xrefs.anchor(node["id"], :value, false)&.strip
26
+ [name, ins, lbls, number]
27
+ end
28
+
29
+ def prefix_name_labels(node)
30
+ { elem: node["id"],
31
+ name: "_#{UUIDTools::UUID.random_create}" }
32
+ end
33
+
34
+ def prefix_name_postprocess(node, elem)
35
+ node.at(ns("./sentinel"))&.remove
36
+ strip_duplicate_ids(node, node.at(ns("./#{elem}")),
37
+ node.at(ns("./fmt-#{elem}")))
38
+ end
39
+
40
+ def transfer_id(old, new)
41
+ old["id"] or return
42
+ new["id"] = old["id"]
43
+ old["original-id"] = old["id"]
44
+ old.delete("id")
45
+ end
46
+
47
+ def semx_fmt_dup(elem)
48
+ elem["id"] ||= "_#{UUIDTools::UUID.random_create}"
49
+ new = Nokogiri::XML(<<~XML).root
50
+ <semx xmlns='#{elem.namespace.href}' element='#{elem.name}' source='#{elem['original-id'] || elem['id']}'>#{to_xml(elem.children)}</semx>
51
+ XML
52
+ strip_duplicate_ids(nil, elem, new)
53
+ new
54
+ end
55
+
56
+ def gather_all_ids(elem)
57
+ elem.xpath(".//*[@id]").each_with_object([]) do |i, m|
58
+ m << i["id"]
59
+ end
60
+ end
61
+
62
+ # remove ids duplicated between sem_title and pres_title
63
+ # index terms are assumed transferred to pres_title from sem_title
64
+ def strip_duplicate_ids(_node, sem_title, pres_title)
65
+ sem_title && pres_title or return
66
+ ids = gather_all_ids(pres_title)
67
+ sem_title.xpath(".//*[@id]").each do |x|
68
+ ids.include?(x["id"]) or next
69
+ x["original-id"] = x["id"]
70
+ x.delete("id")
71
+ end
72
+ sem_title.xpath(ns(".//index")).each(&:remove)
73
+ end
74
+
75
+ def semx(node, label, element = "autonum")
76
+ id = node["id"] || node[:id]
77
+ /<semx element='[^']+' source='#{id}'/.match?(label) and return label
78
+ l = stripsemx(label)
79
+ %(<semx element='#{element}' source='#{id}'>#{l}</semx>)
80
+ end
81
+
82
+ def autonum(id, num)
83
+ /<semx/.match?(num) and return num # already contains markup
84
+ "<semx element='autonum' source='#{id}'>#{num}</semx>"
85
+ end
86
+
87
+ def semx_orig(node, orig = nil)
88
+ orig ||= node.parent.parent
89
+ orig.at(".//*[@id = '#{node['source']}']")
90
+ end
91
+
92
+ def labelled_autonum(label, id, num)
93
+ elem = "<span class='fmt-element-name'>#{label}</span>"
94
+ num.blank? and return elem
95
+ l10n("#{elem} #{autonum(id, num)}")
96
+ end
97
+
98
+ def fmt_xref_label(label, _number, ids)
99
+ label or return ""
100
+ x = @xrefs.anchor(ids[:elem], :xref, false) or return ""
101
+ ret = "<fmt-xref-label>#{x}</fmt-xref-label>"
102
+ container = @xrefs.anchor(ids[:elem], :container, false)
103
+ y = prefix_container_fmt_xref_label(container, x)
104
+ y != x and
105
+ ret += "<fmt-xref-label container='#{container}'>#{y}</fmt-xref-label>"
106
+ ret
107
+ end
108
+
109
+ def prefix_container_fmt_xref_label(container, xref)
110
+ container or return xref
111
+ container_container = @xrefs.anchor(container, :container, false)
112
+ container_label =
113
+ prefix_container_fmt_xref_label(container_container,
114
+ @xrefs.anchor(container, :xref, false))
115
+ l10n(connectives_spans(@i18n.nested_xref
116
+ .sub("%1", "<span class='fmt-xref-container'>#{container_label}</span>")
117
+ .sub("%2", xref)))
118
+ end
119
+
120
+ # detect whether string which may contain XML markup is empty
121
+ def empty_xml?(str)
122
+ str.blank? and return true
123
+ x = Nokogiri::XML::DocumentFragment.parse(str)
124
+ x.to_str.strip.empty?
125
+ end
126
+
127
+ # Remove ".blank?" tests if want empty delim placeholders for manipulation
128
+ def fmt_caption(label, elem, name, ids, delims)
129
+ label = fmt_caption_label_wrap(label)
130
+ c = fmt_caption2(label, elem, name, ids, delims)
131
+ empty_xml?(c) and return
132
+ !delims[:label].blank? and
133
+ f = "<span class='fmt-label-delim'>#{delims[:label]}</span>"
134
+ "<fmt-#{elem}>#{c}#{f}</fmt-#{elem}>"
135
+ end
136
+
137
+ def fmt_caption_label_wrap(label)
138
+ empty_xml?(label) || %r{<span class=['"]fmt-caption-label['"]}.match?(label) or
139
+ label = "<span class='fmt-caption-label'>#{label}</span>"
140
+ label
141
+ end
142
+
143
+ def fmt_caption2(label, elem, name, ids, delims)
144
+ if name && !name.children.empty?
145
+ empty_xml?(label) or
146
+ d = "<span class='fmt-caption-delim'>#{delims[:caption]}</span>"
147
+ attr = " element='#{elem}' source='#{ids[:name]}'"
148
+ "#{label}#{d}<semx #{attr}>#{to_xml(name.children)}</semx>"
149
+ elsif label then label
150
+ end
151
+ end
152
+ end
153
+ end
@@ -29,11 +29,10 @@ module IsoDoc
29
29
 
30
30
  def bibdata_current(docxml)
31
31
  a = docxml.at(ns("//bibdata")) or return
32
- a.xpath(ns("./language")).each do |l|
33
- l.text == @lang and l["current"] = "true"
34
- end
35
- a.xpath(ns("./script")).each do |l|
36
- l.text == @script and l["current"] = "true"
32
+ { language: @lang, script: @script, locale: @locale }.each do |k, v|
33
+ a.xpath(ns("./#{k}")).each do |l|
34
+ l.text == v and l["current"] = "true"
35
+ end
37
36
  end
38
37
  a
39
38
  end
@@ -1,30 +1,23 @@
1
1
  require_relative "image"
2
2
  require_relative "sourcecode"
3
+ require_relative "autonum"
3
4
  require "rouge"
4
5
 
5
6
  module IsoDoc
6
7
  class PresentationXMLConvert < ::IsoDoc::Convert
7
8
  def lower2cap(text)
8
- /^[[:upper:]][[:upper:]]/.match?(text) and return text
9
- text.capitalize
9
+ text.nil? and return text
10
+ x = Nokogiri::XML("<a>#{text}</a>")
11
+ firsttext = x.at(".//text()[string-length(normalize-space(.))>0]") or return text
12
+ /^[[:upper:]][[:upper:]]/.match?(firsttext.text) and return text
13
+ firsttext.replace(firsttext.text.capitalize)
14
+ to_xml(x.root.children)
10
15
  end
11
16
 
12
17
  def block_delim
13
18
  "&#xa0;&#x2014; "
14
19
  end
15
20
 
16
- def prefix_name(node, delim, number, elem)
17
- number.nil? || number.empty? and return
18
- unless name = node.at(ns("./#{elem}"))
19
- (node.children.empty? and node.add_child("<#{elem}></#{elem}>")) or
20
- node.children.first.previous = "<#{elem}></#{elem}>"
21
- name = node.children.first
22
- end
23
- if name.children.empty? then name.add_child(cleanup_entities(number.strip))
24
- else (name.children.first.previous = "#{number.strip}#{delim}")
25
- end
26
- end
27
-
28
21
  def formula(docxml)
29
22
  docxml.xpath(ns("//formula")).each { |f| formula1(f) }
30
23
  end
@@ -32,7 +25,7 @@ module IsoDoc
32
25
  def formula1(elem)
33
26
  formula_where(elem.at(ns("./dl")))
34
27
  lbl = @xrefs.anchor(elem["id"], :label, false)
35
- prefix_name(elem, "", lbl, "name")
28
+ lbl.nil? || lbl.empty? or prefix_name(elem, {}, lbl, "name")
36
29
  end
37
30
 
38
31
  def formula_where(dlist)
@@ -48,25 +41,27 @@ module IsoDoc
48
41
 
49
42
  def example1(elem)
50
43
  n = @xrefs.get[elem["id"]]
51
- lbl = if n.nil? || n[:label].nil? || n[:label].empty?
52
- @i18n.example
53
- else l10n("#{@i18n.example} #{n[:label]}")
54
- end
55
- prefix_name(elem, block_delim, lbl, "name")
44
+ lbl = labelled_autonum(@i18n.example, elem["id"], n&.dig(:label))
45
+ prefix_name(elem, { caption: block_delim }, lbl, "name")
56
46
  end
57
47
 
58
48
  def note(docxml)
59
49
  docxml.xpath(ns("//note")).each { |f| note1(f) }
60
50
  end
61
51
 
52
+ def note_delim(_elem)
53
+ "<tab/>"
54
+ end
55
+
62
56
  def note1(elem)
63
57
  %w(bibdata bibitem).include?(elem.parent.name) ||
64
- elem["notag"] == "true" and return
58
+ elem["notag"] == "true" or lbl = note_label(elem)
59
+ prefix_name(elem, { label: note_delim(elem) }, lbl, "name")
60
+ end
61
+
62
+ def note_label(elem)
65
63
  n = @xrefs.get[elem["id"]]
66
- lbl = @i18n.note
67
- (n.nil? || n[:label].nil? || n[:label].empty?) or
68
- lbl = l10n("#{lbl} #{n[:label]}")
69
- prefix_name(elem, "", lbl, "name")
64
+ labelled_autonum(@i18n.note, elem["id"], n&.dig(:label))
70
65
  end
71
66
 
72
67
  def admonition(docxml)
@@ -76,16 +71,30 @@ module IsoDoc
76
71
  def admonition1(elem)
77
72
  if elem["type"] == "box"
78
73
  admonition_numbered1(elem)
74
+ elsif elem["notag"] == "true" || elem.at(ns("./name"))
75
+ prefix_name(elem, { label: admonition_delim(elem) }, nil, "name")
79
76
  else
80
- elem["notag"] == "true" || elem.at(ns("./name")) and return
81
- prefix_name(elem, "", @i18n.admonition[elem["type"]]&.upcase, "name")
77
+ label = admonition_label(elem, nil)
78
+ prefix_name(elem, { label: admonition_delim(elem) }, label, "name")
82
79
  end
83
80
  end
84
81
 
85
82
  def admonition_numbered1(elem)
86
- elem["unnumbered"] && !elem.at(ns("./name")) and return
87
- n = @xrefs.anchor(elem["id"], :label, false)
88
- prefix_name(elem, block_delim, l10n("#{@i18n.box} #{n}"), "name")
83
+ # elem["unnumbered"] && !elem.at(ns("./name")) and return
84
+ label = admonition_label(elem, @xrefs.anchor(elem["id"], :label, false))
85
+ prefix_name(elem, { caption: block_delim }, label, "name")
86
+ end
87
+
88
+ def admonition_label(elem, num)
89
+ lbl = if elem["type"] == "box" then @i18n.box
90
+ else @i18n.admonition[elem["type"]]&.upcase end
91
+ #lbl &&= "<span class='fmt-element-name'>#{lbl}</span>"
92
+ #num and lbl = l10n("#{lbl} #{autonum(elem['id'], num)}")
93
+ labelled_autonum(lbl, elem["id"], num)
94
+ end
95
+
96
+ def admonition_delim(_elem)
97
+ ""
89
98
  end
90
99
 
91
100
  def table(docxml)
@@ -94,11 +103,18 @@ module IsoDoc
94
103
  end
95
104
 
96
105
  def table1(elem)
106
+ table_fn(elem)
97
107
  labelled_ancestor(elem) and return
98
108
  elem["unnumbered"] && !elem.at(ns("./name")) and return
99
109
  n = @xrefs.anchor(elem["id"], :label, false)
100
- prefix_name(elem, block_delim, l10n("#{lower2cap @i18n.table} #{n}"),
101
- "name")
110
+ #lbl = "<span class='fmt-element-name'>#{lower2cap @i18n.table}</span> "\
111
+ #"#{autonum(elem['id'], n)}"
112
+ lbl = labelled_autonum(lower2cap(@i18n.table), elem["id"], n)
113
+ prefix_name(elem, { caption: table_delim }, l10n(lbl), "name")
114
+ end
115
+
116
+ def table_delim
117
+ block_delim
102
118
  end
103
119
 
104
120
  def table_long_strings_cleanup(docxml)
@@ -112,16 +128,45 @@ module IsoDoc
112
128
  end
113
129
  end
114
130
 
115
- # we use this to eliminate the semantic amend blocks from rendering
131
+ def table_fn(elem)
132
+ (elem.xpath(ns(".//fn")) - elem.xpath(ns("./name//fn")))
133
+ .each_with_index do |f, i|
134
+ table_fn1(elem, f, i)
135
+ end
136
+ end
137
+
138
+ def table_fn1(table, fnote, idx); end
139
+
116
140
  def amend(docxml)
117
141
  docxml.xpath(ns("//amend")).each { |f| amend1(f) }
118
142
  end
119
143
 
120
144
  def amend1(elem)
121
- elem.xpath(ns("./autonumber")).each(&:remove)
122
- elem.xpath(ns("./newcontent")).each { |a| a.name = "quote" }
123
- elem.xpath(ns("./description")).each { |a| a.replace(a.children) }
124
- elem.replace(elem.children)
145
+ ret = semx_fmt_dup(elem)
146
+ ret.xpath(ns("./locality | ./localityStack | ./autonumber | " \
147
+ "./classification | ./contributor")).each(&:remove)
148
+ ret.xpath(ns("./newcontent")).each { |a| a.name = "quote" }
149
+ ret.xpath(ns("./description")).each { |a| a.replace(a.children) }
150
+ elem.xpath(ns(".//fmt-name | .//fmt-xref-label")).each(&:remove)
151
+ elem.next = ret
152
+ end
153
+
154
+ def dl(docxml)
155
+ docxml.xpath(ns("//dl")).each { |f| dl1(f) }
156
+ end
157
+
158
+ def dl1(elem)
159
+ elem.at(ns("./name")) and
160
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
161
+ end
162
+
163
+ def ul(docxml)
164
+ docxml.xpath(ns("//ul")).each { |f| ul1(f) }
165
+ end
166
+
167
+ def ul1(elem)
168
+ elem.at(ns("./name")) and
169
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
125
170
  end
126
171
 
127
172
  def ol(docxml)
@@ -145,9 +190,8 @@ module IsoDoc
145
190
 
146
191
  def ol1(elem)
147
192
  elem["type"] ||= ol_depth(elem).to_s
148
- elem.xpath(ns("./li")).each do |li|
149
- li["id"] ||= "_#{UUIDTools::UUID.random_create}"
150
- end
193
+ elem.at(ns("./name")) and
194
+ prefix_name(elem, {}, "", "name") # copy name to fmt-name
151
195
  end
152
196
 
153
197
  def ol_label(elem)
@@ -180,5 +224,28 @@ module IsoDoc
180
224
  def source_modification(mod)
181
225
  termsource_modification(mod.parent)
182
226
  end
227
+
228
+ def quote(docxml)
229
+ docxml.xpath(ns("//quote")).each { |f| quote1(f) }
230
+ end
231
+
232
+ def quote1(elem)
233
+ author = elem.at(ns("./author"))
234
+ source = elem.at(ns("./source"))
235
+ author.nil? && source.nil? and return
236
+ p = "&#x2014; "
237
+ p += to_xml(semx_fmt_dup(author)) if author
238
+ p += ", " if author && source
239
+ if source
240
+ s = semx_fmt_dup(source)
241
+ e = Nokogiri::XML::Node.new("eref", elem.document)
242
+ e << s.children
243
+ s << e
244
+ source.attributes.each_key { |k| e[k] = source[k] }
245
+ e["deleteme"] = "true" # duplicate of source, will be duplicated in fmt-eref, need to delete after
246
+ p += to_xml(s)
247
+ end
248
+ elem << "<attribution><p>#{l10n p}</p></attribution>"
249
+ end
183
250
  end
184
251
  end
@@ -7,7 +7,8 @@ module IsoDoc
7
7
  end
8
8
 
9
9
  def concept1(node)
10
- xref = node&.at(ns("./xref/@target"))&.text or
10
+ node.ancestors("definition, termsource, related").empty? or return
11
+ xref = node&.at(ns("./semx/fmt-xref/@target"))&.text or
11
12
  return concept_render(node, ital: "true", ref: "true", bold: "false",
12
13
  linkref: "true", linkmention: "false")
13
14
  if @definition_ids[xref]
@@ -19,13 +20,25 @@ module IsoDoc
19
20
  end
20
21
 
21
22
  def concept_render(node, defaults)
22
- opts, render, ref = concept_render_init(node, defaults)
23
- node&.at(ns("./refterm"))&.remove
23
+ #require "debug"; binding.b
24
+ opts, render, ref, ret = concept_render_init(node, defaults)
25
+ ret&.at(ns("./refterm"))&.remove
24
26
  ref && opts[:ref] != "false" and render&.next = " "
25
27
  concept1_linkmention(ref, render, opts)
26
- concept1_ref(node, ref, opts)
27
- concept1_style(node, opts)
28
- node.replace(node.children)
28
+ concept1_ref(ret, ref, opts)
29
+ concept1_style(ret, opts)
30
+ concept_dup(node, ret)
31
+ end
32
+
33
+ def concept_dup(node, ret)
34
+ node.xpath(".//xmlns:semx[xmlns:fmt-xref | xmlns:fmt-eref | xmlns:fmt-origin | xmlns:fmt-link]").each(&:remove)
35
+ ret.xpath(ns(".//xref | .//eref | .//origin | .//link")).each(&:remove)
36
+ ret.xpath(ns(".//semx")).each do |s|
37
+ s.children.empty? and s.remove
38
+ end
39
+ f = Nokogiri::XML::Node.new("fmt-concept", node.document)
40
+ f << ret
41
+ node.next = f
29
42
  end
30
43
 
31
44
  def concept1_style(node, opts)
@@ -37,25 +50,37 @@ module IsoDoc
37
50
  end
38
51
 
39
52
  def concept_render_init(node, defaults)
40
- opts = %i(bold ital ref linkref linkmention)
53
+ opts = concept_render_opts(node, defaults)
54
+ ret = semx_fmt_dup(node)
55
+ ret.children.each { |x| x.text? and x.remove }
56
+ [opts, ret.at(ns("./renderterm")),
57
+ ret.at(ns("./semx/fmt-xref | ./semx/fmt-eref | ./termref")), ret]
58
+ end
59
+
60
+ def concept_render_opts(node, defaults)
61
+ %i(bold ital ref linkref linkmention)
41
62
  .each_with_object({}) { |x, m| m[x] = node[x.to_s] || defaults[x] }
42
- [opts, node.at(ns("./renderterm")),
43
- node.at(ns("./xref | ./eref | ./termref"))]
44
63
  end
45
64
 
46
65
  def concept1_linkmention(ref, renderterm, opts)
47
66
  (opts[:linkmention] == "true" && !renderterm.nil? && !ref.nil?) or return
48
67
  ref2 = ref.clone
49
68
  r2 = renderterm.clone
50
- renderterm.replace(ref2).children = r2
69
+ #renderterm.replace(ref2).children = r2
70
+ ref2.children = r2
71
+ if ref.parent.name == "semx"
72
+ renderterm.replace("<semx element='#{ref.parent['element']}' source='#{ref.parent['source']}'>#{to_xml(ref2)}</semx>")
73
+ else
74
+ renderterm.replace(ref2)
75
+ end
51
76
  end
52
77
 
53
78
  def concept1_ref(_node, ref, opts)
54
79
  ref.nil? and return
55
80
  opts[:ref] == "false" and return ref.remove
56
81
  concept1_ref_content(ref)
57
- %w(xref eref).include? ref.name and get_linkend(ref)
58
- opts[:linkref] == "false" && %w(xref eref).include?(ref.name) and
82
+ %w(fmt-xref fmt-eref).include? ref.name and get_linkend(ref)
83
+ opts[:linkref] == "false" && %w(fmt-xref fmt-eref).include?(ref.name) and
59
84
  ref.replace(ref.children)
60
85
  end
61
86
 
@@ -64,27 +89,167 @@ module IsoDoc
64
89
  foll = "]"
65
90
  non_locality_elems(ref).select do |c|
66
91
  !c.text? || /\S/.match(c)
67
- end.empty? and
92
+ end.empty? or
68
93
  (prev, foll = @i18n.term_defined_in.split("%"))
69
94
  ref.previous = prev
70
95
  ref.next = foll
71
96
  end
72
97
 
73
98
  def related(docxml)
74
- docxml.xpath(ns("//related")).each { |f| related1(f) }
99
+ docxml.xpath(ns("//fmt-related/semx")).each { |f| related1(f) }
75
100
  end
76
101
 
77
102
  def related1(node)
78
- p = node.at(ns("./preferred"))
79
- ref = node.at(ns("./xref | ./eref | ./termref"))
80
- label = @i18n.relatedterms[node["type"]].upcase
103
+ p, ref, orig = related1_prep(node)
104
+ label = @i18n.relatedterms[orig["type"]].upcase
81
105
  if p && ref
82
- node.replace(l10n("<p><strong>#{label}:</strong> " \
106
+ node.children =(l10n("<p><strong>#{label}:</strong> " \
83
107
  "<em>#{to_xml(p)}</em> (#{Common::to_xml(ref)})</p>"))
84
108
  else
85
- node.replace(l10n("<p><strong>#{label}:</strong> " \
109
+ node.children = (l10n("<p><strong>#{label}:</strong> " \
86
110
  "<strong>**RELATED TERM NOT FOUND**</strong></p>"))
87
111
  end
88
112
  end
113
+
114
+ def related1_prep(node)
115
+ p = node.at(ns("./fmt-preferred"))&.children
116
+ ref = node.at(ns("./xref | ./eref | ./termref"))
117
+ orig = semx_orig(node)
118
+ [p, ref, orig]
119
+ end
120
+
121
+ def related_designation1(desgn)
122
+ out = desgn.parent.at(ns("./fmt-#{desgn.name}"))
123
+ d1 = semx_fmt_dup(desgn)
124
+ %w(preferred admitted deprecates).each do |w|
125
+ d = d1.at(ns("./#{w}[last()]")) and d.after("<fmt-#{w}/>")
126
+ end
127
+ out << d1
128
+ end
129
+
130
+ def designation(docxml)
131
+ docxml.xpath(ns("//related")).each { |p| related_designation1(p) }
132
+ docxml.xpath(ns("//preferred | //admitted | //deprecates"))
133
+ .each { |p| designation1(p) }
134
+ docxml.xpath(ns("//fmt-preferred | //fmt-admitted | //fmt-deprecates"))
135
+ .each { |t| merge_second_preferred(t) }
136
+ docxml.xpath(ns("//fmt-deprecates")).each { |d| deprecates(d) }
137
+ docxml.xpath(ns("//fmt-admitted")).each { |d| admits(d) }
138
+ end
139
+
140
+ def deprecates(elem)
141
+ elem.xpath(ns(".//semx[@element = 'deprecates']")).each do |t|
142
+ t.previous = @i18n.l10n("#{@i18n.deprecated}: ")
143
+ end
144
+ end
145
+
146
+ def admits(elem); end
147
+
148
+ def merge_second_preferred(term)
149
+ pref = nil
150
+ out = term.xpath(ns("./semx")).each_with_index
151
+ .with_object([]) do |(p, i), m|
152
+ if (i.zero? && (pref = p)) || merge_preferred_eligible?(pref, p)
153
+ m << p
154
+ else
155
+ p.wrap("<p></p>")
156
+ end
157
+ end
158
+ pref&.replace(merge_second_preferred1(out, term))
159
+ end
160
+
161
+ def merge_second_preferred1(desgns, term)
162
+ desgns[1..].each(&:remove)
163
+ ret = l10n(desgns.map { |x| to_xml(x) }.join("; "))
164
+ term.ancestors("fmt-related").empty? and ret = "<p>#{ret}</p>"
165
+ ret
166
+ end
167
+
168
+ def merge_preferred_eligible?(first, second)
169
+ orig_first, orig_second, firstex, secondex =
170
+ merge_preferred_eligible_prep(first, second)
171
+ orig_first["geographic-area"] == orig_second["geographic-area"] &&
172
+ firstex["language"] == secondex["language"] &&
173
+ !orig_first.at(ns("./pronunciation | ./grammar | ./graphical-symbol")) &&
174
+ !orig_second.at(ns("./pronunciation | ./grammar | ./graphical-symbol")) &&
175
+ orig_first.name == "preferred" && orig_second.name == "preferred"
176
+ end
177
+
178
+ def merge_preferred_eligible_prep(first, second)
179
+ orig_first = semx_orig(first)
180
+ orig_second = semx_orig(second)
181
+ firstex = orig_first.at(ns("./expression")) || {}
182
+ secondex = orig_second.at(ns("./expression")) || {}
183
+ [orig_first, orig_second, firstex, secondex]
184
+ end
185
+
186
+ def designation1(desgn)
187
+ desgn.parent.name == "related" and return
188
+ out = desgn.parent.at(ns("./fmt-#{desgn.name}"))
189
+ d1 = semx_fmt_dup(desgn)
190
+ s = d1.at(ns("./termsource"))
191
+ name = d1.at(ns("./expression/name | ./letter-symbol/name | " \
192
+ "./graphical-symbol")) or return
193
+ designation_annotate(d1, name, desgn)
194
+ out << d1
195
+ s and out << s.wrap("<fmt-termsource></fmt-termsource>").parent
196
+ end
197
+
198
+ def designation_annotate(desgn, name, orig)
199
+ designation_boldface(desgn)
200
+ designation_field(desgn, name, orig)
201
+ #g = desgn.at(ns("./expression/grammar")) and
202
+ #name << ", #{designation_grammar(g).join(', ')}"
203
+ designation_grammar(desgn, name)
204
+ designation_localization(desgn, name, orig)
205
+ designation_pronunciation(desgn, name)
206
+ designation_bookmarks(desgn, name)
207
+ desgn.children = name.children
208
+ end
209
+
210
+ def designation_boldface(desgn)
211
+ desgn["element"] == "preferred" or return
212
+ name = desgn.at(ns("./expression/name | ./letter-symbol/name")) or return
213
+ name.children = "<strong>#{name.children}</strong>"
214
+ end
215
+
216
+ def designation_field(desgn, name, orig)
217
+ f = orig.xpath(ns("./field-of-application | ./usage-info"))
218
+ &.map { |u| to_xml(semx_fmt_dup(u)) }&.join(", ")
219
+ f&.empty? and return nil
220
+ name << "<span class='fmt-designation-field'>, &#x3c;#{f}&#x3e;</span>"
221
+ end
222
+
223
+ def designation_grammar(desgn, name)
224
+ g = desgn.at(ns("./expression/grammar")) or return
225
+ ret = []
226
+ g.xpath(ns("./gender | ./number")).each do |x|
227
+ ret << @i18n.grammar_abbrevs[x.text]
228
+ end
229
+ %w(isPreposition isParticiple isAdjective isVerb isAdverb isNoun)
230
+ .each do |x|
231
+ g.at(ns("./#{x}[text() = 'true']")) and ret << @i18n.grammar_abbrevs[x]
232
+ end
233
+ name << ", #{ret.join(', ')}"
234
+ end
235
+
236
+ def designation_localization(desgn, name, orig_desgn)
237
+ loc = [desgn.at(ns("./expression/@language"))&.text,
238
+ desgn.at(ns("./expression/@script"))&.text,
239
+ orig_desgn.at("./@geographic-area")&.text].compact
240
+ loc.empty? and return
241
+ name << ", #{loc.join(' ')}"
242
+ end
243
+
244
+ def designation_pronunciation(desgn, name)
245
+ f = desgn.at(ns("./expression/pronunciation")) or return
246
+ name << ", /#{to_xml(f.children)}/"
247
+ end
248
+
249
+ def designation_bookmarks(desgn, name)
250
+ desgn.xpath(ns(".//bookmark")).each do |b|
251
+ name << b.remove
252
+ end
253
+ end
89
254
  end
90
255
  end