isodoc 1.2.4 → 1.3.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +69 -0
  3. data/README.adoc +1 -3
  4. data/isodoc.gemspec +3 -1
  5. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  6. data/lib/isodoc-yaml/i18n-fr.yaml +8 -7
  7. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  8. data/lib/isodoc/base_style/all.css +5 -1
  9. data/lib/isodoc/base_style/blocks.scss +2 -2
  10. data/lib/isodoc/base_style/reset.css +5 -1
  11. data/lib/isodoc/base_style/reset.scss +6 -1
  12. data/lib/isodoc/base_style/typography.scss +1 -1
  13. data/lib/isodoc/convert.rb +12 -97
  14. data/lib/isodoc/css.rb +95 -0
  15. data/lib/isodoc/function/inline.rb +0 -33
  16. data/lib/isodoc/function/lists.rb +2 -1
  17. data/lib/isodoc/function/references.rb +8 -13
  18. data/lib/isodoc/function/to_word_html.rb +2 -2
  19. data/lib/isodoc/html_function/postprocess.rb +12 -3
  20. data/lib/isodoc/i18n.rb +23 -51
  21. data/lib/isodoc/metadata.rb +44 -111
  22. data/lib/isodoc/metadata_contributor.rb +90 -0
  23. data/lib/isodoc/metadata_date.rb +11 -0
  24. data/lib/isodoc/presentation_function/bibdata.rb +96 -0
  25. data/lib/isodoc/presentation_function/block.rb +14 -9
  26. data/lib/isodoc/presentation_function/inline.rb +151 -34
  27. data/lib/isodoc/presentation_xml_convert.rb +6 -0
  28. data/lib/isodoc/version.rb +1 -1
  29. data/lib/isodoc/word_convert.rb +0 -20
  30. data/lib/isodoc/word_function/body.rb +12 -0
  31. data/lib/isodoc/word_function/postprocess.rb +1 -1
  32. data/lib/isodoc/xref/xref_anchor.rb +8 -3
  33. data/lib/isodoc/xref/xref_counter.rb +20 -9
  34. data/lib/isodoc/xref/xref_gen.rb +4 -4
  35. data/lib/isodoc/xref/xref_sect_gen.rb +1 -1
  36. data/lib/isodoc/xslfo_convert.rb +6 -1
  37. data/spec/assets/html.scss +14 -0
  38. data/spec/assets/i18n.yaml +22 -5
  39. data/spec/isodoc/blocks_spec.rb +100 -221
  40. data/spec/isodoc/footnotes_spec.rb +4 -5
  41. data/spec/isodoc/i18n_spec.rb +89 -16
  42. data/spec/isodoc/inline_spec.rb +185 -163
  43. data/spec/isodoc/lists_spec.rb +1 -1
  44. data/spec/isodoc/metadata_spec.rb +69 -19
  45. data/spec/isodoc/postproc_spec.rb +33 -8
  46. data/spec/isodoc/presentation_xml_spec.rb +584 -1
  47. data/spec/isodoc/ref_spec.rb +328 -10
  48. data/spec/isodoc/section_spec.rb +9 -9
  49. data/spec/isodoc/table_spec.rb +1 -1
  50. data/spec/isodoc/terms_spec.rb +1 -1
  51. data/spec/isodoc/xref_spec.rb +35 -35
  52. data/spec/spec_helper.rb +6 -0
  53. metadata +36 -7
  54. data/.github/workflows/macos.yml +0 -42
  55. data/.github/workflows/ubuntu.yml +0 -62
  56. data/.github/workflows/windows.yml +0 -44
@@ -0,0 +1,90 @@
1
+ module IsoDoc
2
+ class Metadata
3
+ def extract_person_names(authors)
4
+ authors.reduce([]) do |ret, a|
5
+ if a.at(ns('./name/completename'))
6
+ ret << a.at(ns('./name/completename')).text
7
+ else
8
+ fn = []
9
+ forenames = a.xpath(ns('./name/forename'))
10
+ forenames.each { |f| fn << f.text }
11
+ surname = a&.at(ns('./name/surname'))&.text
12
+ ret << fn.join(' ') + ' ' + surname
13
+ end
14
+ end
15
+ end
16
+
17
+ def extract_person_affiliations(authors)
18
+ authors.reduce([]) do |m, a|
19
+ name = a&.at(ns('./affiliation/organization/name'))&.text
20
+ location = a&.at(ns('./affiliation/organization/address/'\
21
+ 'formattedAddress'))&.text
22
+ m << (!name.nil? && !location.nil? ? "#{name}, #{location}" :
23
+ (name || location || ''))
24
+ m
25
+ end
26
+ end
27
+
28
+ def extract_person_names_affiliations(authors)
29
+ names = extract_person_names(authors)
30
+ affils = extract_person_affiliations(authors)
31
+ ret = {}
32
+ affils.each_with_index do |a, i|
33
+ ret[a] ||= []
34
+ ret[a] << names[i]
35
+ end
36
+ ret
37
+ end
38
+
39
+ def personal_authors(isoxml)
40
+ authors = isoxml.xpath(ns("//bibdata/contributor[role/@type = 'author' "\
41
+ "or xmlns:role/@type = 'editor']/person"))
42
+ set(:authors, extract_person_names(authors))
43
+ set(:authors_affiliations, extract_person_names_affiliations(authors))
44
+ end
45
+
46
+ def author(xml, _out)
47
+ personal_authors(xml)
48
+ agency(xml)
49
+ end
50
+
51
+ def iso?(org)
52
+ name = org&.at(ns('./name'))&.text
53
+ abbrev = org&.at(ns('./abbreviation'))&.text
54
+ (abbrev == 'ISO' ||
55
+ name == 'International Organization for Standardization')
56
+ end
57
+
58
+ def agency1(xml)
59
+ agency = ''
60
+ publisher = []
61
+ xml.xpath(ns("//bibdata/contributor[xmlns:role/@type = 'publisher']/"\
62
+ 'organization')).each do |org|
63
+ name = org&.at(ns('./name'))&.text
64
+ agency1 = org&.at(ns('./abbreviation'))&.text || name
65
+ publisher << name if name
66
+ agency = iso?(org) ? "ISO/#{agency}" : "#{agency}#{agency1}/"
67
+ end
68
+ [agency, publisher]
69
+ end
70
+
71
+ def agency(xml)
72
+ agency, publisher = agency1(xml)
73
+ set(:agency, agency.sub(%r{/$}, ''))
74
+ set(:publisher, @i18n.multiple_and(publisher, @labels['and']))
75
+ agency_addr(xml)
76
+ end
77
+
78
+ def agency_addr(xml)
79
+ a = xml.at(ns("//bibdata/contributor[xmlns:role/@type = 'publisher'][1]/"\
80
+ "organization")) or return
81
+ n = a.at(ns("./subdivision")) and set(:subdivision, n.text)
82
+ n = a.at(ns("./address/formattedAddress")) and
83
+ set(:pub_address, n.children.to_xml)
84
+ n = a.at(ns("./phone[not(@type = 'fax')]")) and set(:pub_phone, n.text)
85
+ n = a.at(ns("./phone[@type = 'fax']")) and set(:pub_fax, n.text)
86
+ n = a.at(ns("./email")) and set(:pub_email, n.text)
87
+ n = a.at(ns("./uri")) and set(:pub_uri, n.text)
88
+ end
89
+ end
90
+ end
@@ -1,5 +1,10 @@
1
1
  module IsoDoc
2
2
  class Metadata
3
+ DATETYPES = %w{published accessed created implemented obsoleted confirmed
4
+ updated issued received transmitted copied unchanged
5
+ circulated vote-started
6
+ vote-ended}.freeze
7
+
3
8
  def months
4
9
  {
5
10
  "01": @labels["month_january"],
@@ -35,5 +40,11 @@ module IsoDoc
35
40
  Date.parse(isodate).strftime("%B %d, %Y")
36
41
  end
37
42
  end
43
+
44
+ def bibdate(isoxml, _out)
45
+ isoxml.xpath(ns('//bibdata/date')).each do |d|
46
+ set("#{d['type'].gsub(/-/, '_')}date".to_sym, Common::date_range(d))
47
+ end
48
+ end
38
49
  end
39
50
  end
@@ -0,0 +1,96 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def bibdata(docxml)
4
+ a = bibdata_current(docxml) or return
5
+ bibdata_i18n(a)
6
+ a.next =
7
+ "<localized-strings>#{i8n_name(trim_hash(@i18n.get), "").join("")}"\
8
+ "</localized-strings>"
9
+ end
10
+
11
+ def bibdata_current(docxml)
12
+ a = docxml.at(ns("//bibdata")) or return
13
+ a.xpath(ns("./language")).each do |l|
14
+ l.text == @lang and l["current"] = "true"
15
+ end
16
+ a.xpath(ns("./script")).each do |l|
17
+ l.text == @script and l["current"] = "true"
18
+ end
19
+ a
20
+ end
21
+
22
+ def bibdata_i18n(b)
23
+ hash_translate(b, @i18n.get["doctype_dict"], "./ext/doctype")
24
+ hash_translate(b, @i18n.get["stage_dict"], "./status/stage")
25
+ hash_translate(b, @i18n.get["substage_dict"], "./status/substage")
26
+ end
27
+
28
+ def hash_translate(bibdata, hash, xpath, lang = @lang)
29
+ x = bibdata.at(ns(xpath)) or return
30
+ x["language"] = ""
31
+ hash.is_a? Hash or return
32
+ hash[x.text] or return
33
+ x.next = x.dup
34
+ x.next["language"] = lang
35
+ x.next.children = hash[x.text]
36
+ end
37
+
38
+ def i18n_tag(k, v)
39
+ "<localized-string key='#{k}' language='#{@lang}'>#{v}</localized-string>"
40
+ end
41
+
42
+ def i18n_safe(k)
43
+ k.to_s.gsub(/\s|\./, "_")
44
+ end
45
+
46
+ def i8n_name(h, pref)
47
+ if h.is_a? Hash then i8n_name1(h, pref)
48
+ elsif h.is_a? Array
49
+ h.reject { |a| blank?(a) }.each_with_object([]).
50
+ with_index do |(v1, g), i|
51
+ i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
52
+ end
53
+ else [i18n_tag(pref, h)]
54
+ end
55
+ end
56
+
57
+ def i8n_name1(h, pref)
58
+ h.reject { |k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
59
+ if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
60
+ elsif v.is_a? Array
61
+ v.reject { |a| blank?(a) }.each_with_index do |v1, i|
62
+ i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
63
+ end
64
+ else
65
+ g << i18n_tag("#{pref}#{pref.empty? ? "" : "."}#{i18n_safe(k)}", v)
66
+ end
67
+ end
68
+ end
69
+
70
+ #https://stackoverflow.com/a/31822406
71
+ def blank?(v)
72
+ v.nil? || v.respond_to?(:empty?) && v.empty?
73
+ end
74
+
75
+ def trim_hash(h)
76
+ loop do
77
+ h_new = trim_hash1(h)
78
+ break h if h==h_new
79
+ h = h_new
80
+ end
81
+ end
82
+
83
+ def trim_hash1(h)
84
+ return h unless h.is_a? Hash
85
+ h.each_with_object({}) do |(k,v), g|
86
+ next if blank?(v)
87
+ g[k] = if v.is_a? Hash then trim_hash1(h[k])
88
+ elsif v.is_a? Array
89
+ h[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
90
+ else
91
+ v
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,5 +1,10 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def lower2cap(s)
4
+ return s if /^[[:upper:]][[:upper:]]/.match(s)
5
+ s.capitalize
6
+ end
7
+
3
8
  def figure(docxml)
4
9
  docxml.xpath(ns("//figure")).each do |f|
5
10
  figure1(f)
@@ -12,7 +17,7 @@ module IsoDoc
12
17
  return if labelled_ancestor(f) && f.ancestors("figure").empty?
13
18
  return if f.at(ns("./figure")) and !f.at(ns("./name"))
14
19
  lbl = @xrefs.anchor(f['id'], :label, false) or return
15
- prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.figure} #{lbl}"), "name")
20
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
16
21
  end
17
22
 
18
23
  def prefix_name(f, delim, number, elem)
@@ -36,7 +41,7 @@ module IsoDoc
36
41
  return if labelled_ancestor(f)
37
42
  return unless f.ancestors("example").empty?
38
43
  lbl = @xrefs.anchor(f['id'], :label, false) or return
39
- prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.figure} #{lbl}"), "name")
44
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
40
45
  end
41
46
 
42
47
  def formula(docxml)
@@ -65,7 +70,7 @@ module IsoDoc
65
70
 
66
71
  def example1(f)
67
72
  n = @xrefs.get[f["id"]]
68
- lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example :
73
+ lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example:
69
74
  l10n("#{@i18n.example} #{n[:label]}")
70
75
  prefix_name(f, "&nbsp;&mdash; ", lbl, "name")
71
76
  end
@@ -81,7 +86,7 @@ module IsoDoc
81
86
  return if f.parent.name == "bibitem"
82
87
  n = @xrefs.get[f["id"]]
83
88
  lbl = (@i18n.note if n.nil? || n[:label].nil? || n[:label].empty?) ?
84
- @i18n.note : l10n("#{@i18n.note} #{n[:label]}")
89
+ @i18n.note: l10n("#{@i18n.note} #{n[:label]}")
85
90
  prefix_name(f, "", lbl, "name")
86
91
  end
87
92
 
@@ -94,24 +99,24 @@ module IsoDoc
94
99
  # introduce name element
95
100
  def termnote1(f)
96
101
  lbl = l10n(@xrefs.anchor(f['id'], :label) || '???')
97
- prefix_name(f, "", lbl, "name")
102
+ prefix_name(f, "", lower2cap(lbl), "name")
98
103
  end
99
104
 
100
105
  def recommendation(docxml)
101
106
  docxml.xpath(ns("//recommendation")).each do |f|
102
- recommendation1(f, @i18n.recommendation)
107
+ recommendation1(f, lower2cap(@i18n.recommendation))
103
108
  end
104
109
  end
105
110
 
106
111
  def requirement(docxml)
107
112
  docxml.xpath(ns("//requirement")).each do |f|
108
- recommendation1(f, @i18n.requirement)
113
+ recommendation1(f, lower2cap(@i18n.requirement))
109
114
  end
110
115
  end
111
116
 
112
117
  def permission(docxml)
113
118
  docxml.xpath(ns("//permission")).each do |f|
114
- recommendation1(f, @i18n.permission)
119
+ recommendation1(f, lower2cap(@i18n.permission))
115
120
  end
116
121
  end
117
122
 
@@ -132,7 +137,7 @@ module IsoDoc
132
137
  return if labelled_ancestor(f)
133
138
  return if f["unnumbered"] && !f.at(ns("./name"))
134
139
  n = @xrefs.anchor(f['id'], :label, false)
135
- prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.table} #{n}"), "name")
140
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{lower2cap @i18n.table} #{n}"), "name")
136
141
  end
137
142
 
138
143
  # we use this to eliminate the semantic amend blocks from rendering
@@ -1,3 +1,5 @@
1
+ require "twitter_cldr"
2
+
1
3
  module IsoDoc
2
4
  class PresentationXMLConvert < ::IsoDoc::Convert
3
5
  def prefix_container(container, linkend, _target)
@@ -7,17 +9,25 @@ module IsoDoc
7
9
  def anchor_linkend(node, linkend)
8
10
  if node["citeas"].nil? && node["bibitemid"]
9
11
  return @xrefs.anchor(node["bibitemid"] ,:xref) || "???"
12
+ elsif node["target"] && node["droploc"]
13
+ return @xrefs.anchor(node["target"], :value) ||
14
+ @xrefs.anchor(node["target"], :label) ||
15
+ @xrefs.anchor(node["target"], :xref) || "???"
10
16
  elsif node["target"] && !/.#./.match(node["target"])
11
- linkend = @xrefs.anchor(node["target"], :xref)
12
- container = @xrefs.anchor(node["target"], :container, false)
13
- (container && get_note_container_id(node) != container &&
14
- @xrefs.get[node["target"]]) &&
15
- linkend = prefix_container(container, linkend, node["target"])
16
- linkend = capitalise_xref(node, linkend)
17
+ linkend = anchor_linkend1(node)
17
18
  end
18
19
  linkend || "???"
19
20
  end
20
21
 
22
+ def anchor_linkend1(node)
23
+ linkend = @xrefs.anchor(node["target"], :xref)
24
+ container = @xrefs.anchor(node["target"], :container, false)
25
+ (container && get_note_container_id(node) != container &&
26
+ @xrefs.get[node["target"]]) &&
27
+ linkend = prefix_container(container, linkend, node["target"])
28
+ capitalise_xref(node, linkend)
29
+ end
30
+
21
31
  def capitalise_xref(node, linkend)
22
32
  return linkend unless %w(Latn Cyrl Grek).include? @script
23
33
  return linkend&.capitalize if node["case"] == "capital"
@@ -30,7 +40,7 @@ module IsoDoc
30
40
  end
31
41
 
32
42
  def nearest_block_parent(node)
33
- until %w(p title td th name formula
43
+ until %w(p title td th name formula
34
44
  li dt dd sourcecode pre).include?(node.name)
35
45
  node = node.parent
36
46
  end
@@ -43,13 +53,13 @@ module IsoDoc
43
53
  end
44
54
  end
45
55
 
46
- def get_linkend(node)
47
- contents = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
56
+ def get_linkend(n)
57
+ contents = non_locality_elems(n).select { |c| !c.text? || /\S/.match(c) }
48
58
  return unless contents.empty?
49
- link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
50
- link += eref_localities(node.xpath(ns("./locality | ./localityStack")), link)
51
- non_locality_elems(node).each { |n| n.remove }
52
- node.add_child(link)
59
+ link = anchor_linkend(n, docid_l10n(n["target"] || n["citeas"]))
60
+ link += eref_localities(n.xpath(ns("./locality | ./localityStack")), link)
61
+ non_locality_elems(n).each { |n| n.remove }
62
+ n.add_child(link)
53
63
  end
54
64
  # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
55
65
  # <locality type="section"><reference>3.1</reference></locality></origin>
@@ -59,14 +69,19 @@ module IsoDoc
59
69
  refs.each_with_index do |r, i|
60
70
  delim = ","
61
71
  delim = ";" if r.name == "localityStack" && i>0
62
- if r.name == "localityStack"
63
- r.elements.each_with_index do |rr, j|
64
- ret += eref_localities0(rr, j, target, delim)
65
- delim = ","
66
- end
67
- else
68
- ret += eref_localities0(r, i, target, delim)
72
+ ret = eref_locality_stack(r, i, target, delim, ret)
73
+ end
74
+ ret
75
+ end
76
+
77
+ def eref_locality_stack(r, i, target, delim, ret)
78
+ if r.name == "localityStack"
79
+ r.elements.each_with_index do |rr, j|
80
+ ret += eref_localities0(rr, j, target, delim)
81
+ delim = ","
69
82
  end
83
+ else
84
+ ret += eref_localities0(r, i, target, delim)
70
85
  end
71
86
  ret
72
87
  end
@@ -79,7 +94,7 @@ module IsoDoc
79
94
  end
80
95
  end
81
96
 
82
- # TODO: move to localization file
97
+ # TODO: move to localization file
83
98
  def eref_localities1_zh(target, type, from, to, delim)
84
99
  ret = "#{delim} 第#{from.text}" if from
85
100
  ret += "&ndash;#{to.text}" if to
@@ -91,7 +106,8 @@ module IsoDoc
91
106
  # TODO: move to localization file
92
107
  def eref_localities1(target, type, from, to, delim, lang = "en")
93
108
  return "" if type == "anchor"
94
- return l10n(eref_localities1_zh(target, type, from, to, delim)) if lang == "zh"
109
+ lang == "zh" and
110
+ return l10n(eref_localities1_zh(target, type, from, to, delim))
95
111
  ret = delim
96
112
  loc = @i18n.locality[type] || type.sub(/^locality:/, "").capitalize
97
113
  ret += " #{loc}"
@@ -101,31 +117,132 @@ module IsoDoc
101
117
  end
102
118
 
103
119
  def xref(docxml)
104
- docxml.xpath(ns("//xref")).each do |f|
105
- xref1(f)
106
- end
120
+ docxml.xpath(ns("//xref")).each { |f| xref1(f) }
107
121
  end
108
122
 
109
123
  def eref(docxml)
110
- docxml.xpath(ns("//eref")).each do |f|
111
- xref1(f)
112
- end
124
+ docxml.xpath(ns("//eref")).each { |f| xref1(f) }
113
125
  end
114
126
 
115
127
  def origin(docxml)
116
- docxml.xpath(ns("//origin[not(termref)]")).each do |f|
117
- xref1(f)
118
- end
128
+ docxml.xpath(ns("//origin[not(termref)]")).each { |f| xref1(f) }
119
129
  end
120
130
 
121
131
  def quotesource(docxml)
122
- docxml.xpath(ns("//quote/source")).each do |f|
123
- xref1(f)
124
- end
132
+ docxml.xpath(ns("//quote/source")).each { |f| xref1(f) }
125
133
  end
126
134
 
127
135
  def xref1(f)
128
136
  get_linkend(f)
129
137
  end
138
+
139
+ def concept(docxml)
140
+ docxml.xpath(ns("//concept")).each { |f| concept1(f) }
141
+ end
142
+
143
+ def concept1(node)
144
+ content = node.first_element_child.children.select do |c|
145
+ !%w{locality localityStack}.include? c.name
146
+ end.select { |c| !c.text? || /\S/.match(c) }
147
+ node.replace content.empty? ?
148
+ @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml) :
149
+ "<em>#{node.children.to_xml}</em>"
150
+ end
151
+
152
+
153
+ MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
154
+
155
+ def mathml(docxml)
156
+ locale = twitter_cldr_localiser()
157
+ docxml.xpath("//m:math", MATHML).each do |f|
158
+ mathml1(f, locale)
159
+ end
160
+ end
161
+
162
+ # symbols is merged into
163
+ # TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols
164
+ def localize_maths(f, locale)
165
+ f.xpath(".//m:mn", MATHML).each do |x|
166
+ num = /\./.match(x.text) ? x.text.to_f : x.text.to_i
167
+ precision = /\./.match(x.text) ? x.text.sub(/^.*\./, "").size : 0
168
+ x.children = localized_number(num, locale, precision)
169
+ end
170
+ end
171
+
172
+ # By itself twiiter cldr does not support fraction part digits grouping
173
+ # and custom delimeter, will decorate fraction part manually
174
+ def localized_number(num, locale, precision)
175
+ localized = precision == 0 ? num.localize(locale).to_s :
176
+ num.localize(locale).to_decimal.to_s(:precision => precision)
177
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
178
+ return localized unless twitter_cldr_reader_symbols[:decimal]
179
+ integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal])
180
+ return localized if fraction.nil? || fraction.length.zero?
181
+ [integer, decorate_fraction_part(fraction, locale)].
182
+ join(twitter_cldr_reader_symbols[:decimal])
183
+ end
184
+
185
+ def decorate_fraction_part(fract, locale)
186
+ result = []
187
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
188
+ fract = fract.slice(0..(twitter_cldr_reader_symbols[:precision] || -1))
189
+ fr_group_digits = twitter_cldr_reader_symbols[:fraction_group_digits] || 1
190
+ until fract.empty?
191
+ result.push(fract.slice!(0, fr_group_digits))
192
+ end
193
+ result.join(twitter_cldr_reader_symbols[:fraction_group].to_s)
194
+ end
195
+
196
+ def twitter_cldr_localiser_symbols
197
+ {}
198
+ end
199
+
200
+ def twitter_cldr_reader(locale)
201
+ num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
202
+ num.symbols.merge!(twitter_cldr_localiser_symbols)
203
+ end
204
+
205
+ def twitter_cldr_localiser()
206
+ locale = TwitterCldr.supported_locale?(@lang.to_sym) ? @lang.to_sym : :en
207
+ twitter_cldr_reader(locale)
208
+ locale
209
+ end
210
+
211
+ def mathml1(f, locale)
212
+ localize_maths(f, locale)
213
+ return unless f.elements.size == 1 && f.elements.first.name == "mn"
214
+ f.replace(f.at("./m:mn", MATHML).children)
215
+ end
216
+
217
+ def variant(docxml)
218
+ docxml.xpath(ns("//variant")).each { |f| variant1(f) }
219
+ docxml.xpath(ns("//variant[@remove = 'true']")).each { |f| f.remove }
220
+ docxml.xpath(ns("//variant")).each do |v|
221
+ next unless v&.next&.name == "variant"
222
+ v.next = "/"
223
+ end
224
+ docxml.xpath(ns("//variant")).each { |f| f.replace(f.children) }
225
+ end
226
+
227
+ def variant1(node)
228
+ if (!node["lang"] || node["lang"] == @lang) &&
229
+ (!node["script"] || node["script"] == @script)
230
+ elsif found_matching_variant_sibling(node)
231
+ node["remove"] = "true"
232
+ else
233
+ #return unless !node.at("./preceding-sibling::xmlns:variant")
234
+ end
235
+ end
236
+
237
+ def found_matching_variant_sibling(node)
238
+ prev = node.xpath("./preceding-sibling::xmlns:variant")
239
+ foll = node.xpath("./following-sibling::xmlns:variant")
240
+ found = false
241
+ (prev + foll).each do |n|
242
+ found = true if n["lang"] == @lang &&
243
+ (!n["script"] || n["script"] == @script)
244
+ end
245
+ found
246
+ end
130
247
  end
131
248
  end