isodoc 1.2.4 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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