isodoc 1.2.7 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +14 -9
- data/README.adoc +1 -3
- data/isodoc.gemspec +1 -1
- data/lib/isodoc-yaml/i18n-en.yaml +1 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +8 -7
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/isodoc/function/inline.rb +0 -33
- data/lib/isodoc/function/references.rb +1 -1
- data/lib/isodoc/function/to_word_html.rb +0 -2
- data/lib/isodoc/html_function/postprocess.rb +1 -0
- data/lib/isodoc/i18n.rb +15 -2
- data/lib/isodoc/presentation_function/block.rb +14 -9
- data/lib/isodoc/presentation_function/inline.rb +124 -22
- data/lib/isodoc/presentation_xml_convert.rb +3 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/body.rb +12 -0
- data/spec/assets/i18n.yaml +7 -6
- data/spec/isodoc/blocks_spec.rb +1 -0
- data/spec/isodoc/footnotes_spec.rb +4 -5
- data/spec/isodoc/i18n_spec.rb +23 -2
- data/spec/isodoc/inline_spec.rb +168 -188
- data/spec/isodoc/postproc_spec.rb +1 -0
- data/spec/isodoc/presentation_xml_spec.rb +584 -1
- data/spec/isodoc/ref_spec.rb +2 -2
- metadata +16 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 491a322b0df2e6b1c8b4f12e520ca349657a009058b416067acdd5437a16085c
|
4
|
+
data.tar.gz: 1f52844ffdc37875d2b40f8d46f52263abcbe5101c99adaf88d839a28a18ed49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce472eadec9ab44d5739f0e506813cb89cf7de6def2909e8ffd0788cf4fe246bf3433b75c22490528b0287bbfad1e2cc5ca50eeaacdd4156fe9bb32a36e912df
|
7
|
+
data.tar.gz: efb30d195c6a15f97133b76d1d4cac762800fe7620d11a58a2655e7ccd3bc972827d419337cbff13fb7d1c4b96004da7b9d95323ae7d8f6c1eaa07d784f67834
|
data/.github/workflows/rake.yml
CHANGED
@@ -4,7 +4,8 @@ name: rake
|
|
4
4
|
|
5
5
|
on:
|
6
6
|
push:
|
7
|
-
branches: [ master ]
|
7
|
+
branches: [ master, main ]
|
8
|
+
tags: [ v* ]
|
8
9
|
pull_request:
|
9
10
|
|
10
11
|
jobs:
|
@@ -31,11 +32,19 @@ jobs:
|
|
31
32
|
steps:
|
32
33
|
- uses: actions/checkout@master
|
33
34
|
|
34
|
-
-
|
35
|
-
uses: ruby/setup-ruby@v1
|
35
|
+
- uses: ruby/setup-ruby@v1
|
36
36
|
with:
|
37
37
|
ruby-version: ${{ matrix.ruby }}
|
38
|
-
|
38
|
+
|
39
|
+
- uses: actions/cache@v1
|
40
|
+
with:
|
41
|
+
path: vendor/bundle
|
42
|
+
key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
|
43
|
+
restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
|
44
|
+
|
45
|
+
- run: bundle config set path 'vendor/bundle'
|
46
|
+
|
47
|
+
- run: bundle install --jobs 4 --retry 3
|
39
48
|
|
40
49
|
- name: Install Inkscape macOS
|
41
50
|
if: matrix.os == 'macos-latest'
|
@@ -57,8 +66,4 @@ jobs:
|
|
57
66
|
choco install --no-progress -y inkscape
|
58
67
|
inkscape --version
|
59
68
|
|
60
|
-
-
|
61
|
-
run: bundle install --jobs 4 --retry 3
|
62
|
-
|
63
|
-
- name: Run specs
|
64
|
-
run: bundle exec rake
|
69
|
+
- run: bundle exec rake
|
data/README.adoc
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
= isodoc: Processor to generate HTML/Word from Metanorma XML
|
2
2
|
|
3
3
|
image:https://img.shields.io/gem/v/isodoc.svg["Gem Version", link="https://rubygems.org/gems/isodoc"]
|
4
|
-
image:https://github.com/metanorma/isodoc/workflows/
|
5
|
-
image:https://github.com/metanorma/isodoc/workflows/macos/badge.svg["OSX Build Status", link="https://github.com/metanorma/isodoc/actions?query=workflow%3Amacos"]
|
6
|
-
image:https://github.com/metanorma/isodoc/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/metanorma/isodoc/actions?query=workflow%3Awindows"]
|
4
|
+
image:https://github.com/metanorma/isodoc/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/isodoc/actions?query=workflow%3Arake"]
|
7
5
|
image:https://codeclimate.com/github/metanorma/isodoc/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/isodoc"]
|
8
6
|
image:https://img.shields.io/github/issues-pr-raw/metanorma/isodoc.svg["Pull Requests", link="https://github.com/metanorma/isodoc/pulls"]
|
9
7
|
image:https://img.shields.io/github/commits-since/metanorma/isodoc/latest.svg["Commits since latest",link="https://github.com/metanorma/isodoc/releases"]
|
data/isodoc.gemspec
CHANGED
@@ -35,10 +35,10 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.add_dependency "uuidtools"
|
36
36
|
spec.add_dependency "html2doc", "~> 1.0.0"
|
37
37
|
spec.add_dependency "liquid"
|
38
|
+
spec.add_dependency "twitter_cldr"
|
38
39
|
spec.add_dependency "roman-numerals"
|
39
40
|
spec.add_dependency "metanorma", "~> 1.2.0"
|
40
41
|
spec.add_dependency "relaton-cli"
|
41
|
-
spec.add_dependency "gyoku", "~> 1.3"
|
42
42
|
|
43
43
|
spec.add_development_dependency "rake", "~> 13.0"
|
44
44
|
spec.add_development_dependency "byebug", "~> 9.1"
|
@@ -36,6 +36,7 @@ external_terms_boilerplate: |
|
|
36
36
|
internal_external_terms_boilerplate: |
|
37
37
|
<p>For the purposes of this document, the terms and definitions
|
38
38
|
given in % and the following apply.</p>
|
39
|
+
term_defined_in: "[term defined in %]"
|
39
40
|
note: NOTE
|
40
41
|
note_xref: Note
|
41
42
|
termnote: Note % to entry
|
@@ -1,5 +1,5 @@
|
|
1
1
|
term_def_boilerplate:
|
2
|
-
scope: Domaine d
|
2
|
+
scope: Domaine d’application
|
3
3
|
symbolsabbrev: Symboles et termes abrégés
|
4
4
|
abbrev: Termes abrégés
|
5
5
|
symbols: Symboles
|
@@ -18,20 +18,21 @@ clause: Article
|
|
18
18
|
annex: Annexe
|
19
19
|
appendix: Appendice
|
20
20
|
no_terms_boilerplate: |
|
21
|
-
<p>Aucun terme n
|
21
|
+
<p>Aucun terme n’est defini dans le présent document.</p>
|
22
22
|
internal_terms_boilerplate: |
|
23
|
-
<p>Pour les besoins du présent document, les termes et définitions suivants s
|
23
|
+
<p>Pour les besoins du présent document, les termes et définitions suivants s’appliquent.</p>
|
24
24
|
norm_with_refs_pref:
|
25
|
-
Les documents suivants
|
25
|
+
Les documents suivants cités dans le texte constituent, pour tout ou partie de leur contenu, des exigences du présent document. Pour les références datées, seule l’édition citée s’applique. Pour les références non datées, la dernière édition du document de référence s’applique (y compris les éventuels amendements).
|
26
26
|
norm_empty_pref:
|
27
27
|
Le présent document ne contient aucune référence normative.
|
28
28
|
external_terms_boilerplate: |
|
29
|
-
<p>Pour les besoins du présent document, les termes et définitions de % s
|
29
|
+
<p>Pour les besoins du présent document, les termes et définitions de % s’appliquent.</p>
|
30
30
|
internal_external_terms_boilerplate: |
|
31
|
-
<p>Pour les besoins du présent document, les termes et définitions de % ainsi que les suivants, s
|
31
|
+
<p>Pour les besoins du présent document, les termes et définitions de % ainsi que les suivants, s’appliquent.</p>
|
32
|
+
term_defined_in: "[terme défini dans %]"
|
32
33
|
note: NOTE
|
33
34
|
note_xref: Note
|
34
|
-
termnote: Note % à l
|
35
|
+
termnote: Note % à l’article
|
35
36
|
figure: Figure
|
36
37
|
formula: Formule
|
37
38
|
inequality: Formule
|
@@ -67,19 +67,6 @@ module IsoDoc::Function
|
|
67
67
|
out << "Termbase #{node['base']}, term ID #{node['target']}"
|
68
68
|
end
|
69
69
|
|
70
|
-
def concept_parse(node, out)
|
71
|
-
content = node.first_element_child.children.select do |c|
|
72
|
-
!%w{locality localityStack}.include? c.name
|
73
|
-
end.select { |c| !c.text? || /\S/.match(c) }
|
74
|
-
if content.empty?
|
75
|
-
out << "[Term defined in "
|
76
|
-
parse(node.first_element_child, out)
|
77
|
-
out << "]"
|
78
|
-
else
|
79
|
-
content.each { |n| parse(n, out) }
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
70
|
def stem_parse(node, out)
|
84
71
|
ooml = if node["type"] == "AsciiMath"
|
85
72
|
"#{@openmathdelim}#{HTMLEntities.new.encode(node.text)}"\
|
@@ -131,25 +118,5 @@ module IsoDoc::Function
|
|
131
118
|
p.b(**{ role: "strong" }) { |e| e << text }
|
132
119
|
end
|
133
120
|
end
|
134
|
-
|
135
|
-
def variant_parse(node, out)
|
136
|
-
if node["lang"] == @lang && node["script"] == @script
|
137
|
-
node.children.each { |n| parse(n, out) }
|
138
|
-
else
|
139
|
-
return if found_matching_variant_sibling(node)
|
140
|
-
return unless !node.at("./preceding-sibling::xmlns:variant")
|
141
|
-
node.children.each { |n| parse(n, out) }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def found_matching_variant_sibling(node)
|
146
|
-
prev = node.xpath("./preceding-sibling::xmlns:variant")
|
147
|
-
foll = node.xpath("./following-sibling::xmlns:variant")
|
148
|
-
found = false
|
149
|
-
(prev + foll).each do |n|
|
150
|
-
found = true if n["lang"] == @lang && n["script"] == @script
|
151
|
-
end
|
152
|
-
found
|
153
|
-
end
|
154
121
|
end
|
155
122
|
end
|
@@ -90,7 +90,7 @@ module IsoDoc::Function
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def date_note_process(b, ref)
|
93
|
-
date_note = b.at(ns("./note[@type = '
|
93
|
+
date_note = b.at(ns("./note[@type = 'Unpublished-Status']"))
|
94
94
|
return if date_note.nil?
|
95
95
|
date_note.children.first.replace("<p>#{date_note.content}</p>")
|
96
96
|
footnote_parse(date_note, ref)
|
@@ -215,14 +215,12 @@ module IsoDoc::Function
|
|
215
215
|
when "verification" then requirement_component_parse(node, out)
|
216
216
|
when "import" then requirement_component_parse(node, out)
|
217
217
|
when "index" then index_parse(node, out)
|
218
|
-
when "concept" then concept_parse(node, out)
|
219
218
|
when "termref" then termrefelem_parse(node, out)
|
220
219
|
when "copyright-statement" then copyright_parse(node, out)
|
221
220
|
when "license-statement" then license_parse(node, out)
|
222
221
|
when "legal-statement" then legal_parse(node, out)
|
223
222
|
when "feedback-statement" then feedback_parse(node, out)
|
224
223
|
when "passthrough" then passthrough_parse(node, out)
|
225
|
-
when "variant" then variant_parse(node, out)
|
226
224
|
when "amend" then amend_parse(node, out)
|
227
225
|
when "tab" then clausedelimspace(out) # in Presentation XML only
|
228
226
|
else
|
data/lib/isodoc/i18n.rb
CHANGED
@@ -4,8 +4,21 @@ module IsoDoc
|
|
4
4
|
class I18n
|
5
5
|
def load_yaml(lang, script, i18nyaml = nil)
|
6
6
|
ret = load_yaml1(lang, script)
|
7
|
-
return ret.merge(YAML.load_file(i18nyaml)) if i18nyaml
|
8
|
-
ret
|
7
|
+
return normalise_hash(ret.merge(YAML.load_file(i18nyaml))) if i18nyaml
|
8
|
+
normalise_hash(ret)
|
9
|
+
end
|
10
|
+
|
11
|
+
def normalise_hash(ret)
|
12
|
+
if ret.is_a? Hash
|
13
|
+
ret.each do |k, v|
|
14
|
+
ret[k] = normalise_hash(v)
|
15
|
+
end
|
16
|
+
ret
|
17
|
+
elsif ret.is_a? Array then ret.map { |n| normalise_hash(n) }
|
18
|
+
elsif ret.is_a? String then ret.unicode_normalize(:nfc)
|
19
|
+
else
|
20
|
+
ret
|
21
|
+
end
|
9
22
|
end
|
10
23
|
|
11
24
|
def load_yaml1(lang, script)
|
@@ -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, " — ", l10n("#{@i18n.figure} #{lbl}"), "name")
|
20
|
+
prefix_name(f, " — ", 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, " — ", l10n("#{@i18n.figure} #{lbl}"), "name")
|
44
|
+
prefix_name(f, " — ", 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, " — ", 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
|
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, " — ", l10n("#{@i18n.table} #{n}"), "name")
|
140
|
+
prefix_name(f, " — ", 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)
|
@@ -8,8 +10,8 @@ module IsoDoc
|
|
8
10
|
if node["citeas"].nil? && node["bibitemid"]
|
9
11
|
return @xrefs.anchor(node["bibitemid"] ,:xref) || "???"
|
10
12
|
elsif node["target"] && node["droploc"]
|
11
|
-
return @xrefs.anchor(node["target"], :value) ||
|
12
|
-
@xrefs.anchor(node["target"], :label) ||
|
13
|
+
return @xrefs.anchor(node["target"], :value) ||
|
14
|
+
@xrefs.anchor(node["target"], :label) ||
|
13
15
|
@xrefs.anchor(node["target"], :xref) || "???"
|
14
16
|
elsif node["target"] && !/.#./.match(node["target"])
|
15
17
|
linkend = anchor_linkend1(node)
|
@@ -38,7 +40,7 @@ module IsoDoc
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def nearest_block_parent(node)
|
41
|
-
until %w(p title td th name formula
|
43
|
+
until %w(p title td th name formula
|
42
44
|
li dt dd sourcecode pre).include?(node.name)
|
43
45
|
node = node.parent
|
44
46
|
end
|
@@ -51,13 +53,13 @@ module IsoDoc
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
def get_linkend(
|
55
|
-
contents = non_locality_elems(
|
56
|
+
def get_linkend(n)
|
57
|
+
contents = non_locality_elems(n).select { |c| !c.text? || /\S/.match(c) }
|
56
58
|
return unless contents.empty?
|
57
|
-
link = anchor_linkend(
|
58
|
-
link += eref_localities(
|
59
|
-
non_locality_elems(
|
60
|
-
|
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)
|
61
63
|
end
|
62
64
|
# so not <origin bibitemid="ISO7301" citeas="ISO 7301">
|
63
65
|
# <locality type="section"><reference>3.1</reference></locality></origin>
|
@@ -104,7 +106,8 @@ module IsoDoc
|
|
104
106
|
# TODO: move to localization file
|
105
107
|
def eref_localities1(target, type, from, to, delim, lang = "en")
|
106
108
|
return "" if type == "anchor"
|
107
|
-
|
109
|
+
lang == "zh" and
|
110
|
+
return l10n(eref_localities1_zh(target, type, from, to, delim))
|
108
111
|
ret = delim
|
109
112
|
loc = @i18n.locality[type] || type.sub(/^locality:/, "").capitalize
|
110
113
|
ret += " #{loc}"
|
@@ -114,31 +117,130 @@ module IsoDoc
|
|
114
117
|
end
|
115
118
|
|
116
119
|
def xref(docxml)
|
117
|
-
docxml.xpath(ns("//xref")).each
|
118
|
-
xref1(f)
|
119
|
-
end
|
120
|
+
docxml.xpath(ns("//xref")).each { |f| xref1(f) }
|
120
121
|
end
|
121
122
|
|
122
123
|
def eref(docxml)
|
123
|
-
docxml.xpath(ns("//eref")).each
|
124
|
-
xref1(f)
|
125
|
-
end
|
124
|
+
docxml.xpath(ns("//eref")).each { |f| xref1(f) }
|
126
125
|
end
|
127
126
|
|
128
127
|
def origin(docxml)
|
129
|
-
docxml.xpath(ns("//origin[not(termref)]")).each
|
130
|
-
xref1(f)
|
131
|
-
end
|
128
|
+
docxml.xpath(ns("//origin[not(termref)]")).each { |f| xref1(f) }
|
132
129
|
end
|
133
130
|
|
134
131
|
def quotesource(docxml)
|
135
|
-
docxml.xpath(ns("//quote/source")).each
|
136
|
-
xref1(f)
|
137
|
-
end
|
132
|
+
docxml.xpath(ns("//quote/source")).each { |f| xref1(f) }
|
138
133
|
end
|
139
134
|
|
140
135
|
def xref1(f)
|
141
136
|
get_linkend(f)
|
142
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
|
+
x.children = localized_number(num, locale)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# By itself twiiter cldr does not support fraction part digits grouping
|
172
|
+
# and custom delimeter, will decorate fraction part manually
|
173
|
+
def localized_number(num, locale)
|
174
|
+
localized = num.localize(locale).to_s
|
175
|
+
twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
|
176
|
+
return localized unless twitter_cldr_reader_symbols[:decimal]
|
177
|
+
integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal])
|
178
|
+
return localized if fraction.nil? || fraction.length.zero?
|
179
|
+
[integer, decorate_fraction_part(fraction, locale)].
|
180
|
+
join(twitter_cldr_reader_symbols[:decimal])
|
181
|
+
end
|
182
|
+
|
183
|
+
def decorate_fraction_part(fract, locale)
|
184
|
+
result = []
|
185
|
+
twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
|
186
|
+
fract = fract.slice(0..(twitter_cldr_reader_symbols[:precision] || -1))
|
187
|
+
fr_group_digits = twitter_cldr_reader_symbols[:fraction_group_digits] || 1
|
188
|
+
until fract.empty?
|
189
|
+
result.push(fract.slice!(0, fr_group_digits))
|
190
|
+
end
|
191
|
+
result.join(twitter_cldr_reader_symbols[:fraction_group].to_s)
|
192
|
+
end
|
193
|
+
|
194
|
+
def twitter_cldr_localiser_symbols
|
195
|
+
{}
|
196
|
+
end
|
197
|
+
|
198
|
+
def twitter_cldr_reader(locale)
|
199
|
+
num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
|
200
|
+
num.symbols.merge!(twitter_cldr_localiser_symbols)
|
201
|
+
end
|
202
|
+
|
203
|
+
def twitter_cldr_localiser()
|
204
|
+
locale = TwitterCldr.supported_locale?(@lang.to_sym) ? @lang.to_sym : :en
|
205
|
+
twitter_cldr_reader(locale)
|
206
|
+
locale
|
207
|
+
end
|
208
|
+
|
209
|
+
def mathml1(f, locale)
|
210
|
+
localize_maths(f, locale)
|
211
|
+
return unless f.elements.size == 1 && f.elements.first.name == "mn"
|
212
|
+
f.replace(f.at("./m:mn", MATHML).children)
|
213
|
+
end
|
214
|
+
|
215
|
+
def variant(docxml)
|
216
|
+
docxml.xpath(ns("//variant")).each { |f| variant1(f) }
|
217
|
+
docxml.xpath(ns("//variant[@remove = 'true']")).each { |f| f.remove }
|
218
|
+
docxml.xpath(ns("//variant")).each do |v|
|
219
|
+
next unless v&.next&.name == "variant"
|
220
|
+
v.next = "/"
|
221
|
+
end
|
222
|
+
docxml.xpath(ns("//variant")).each { |f| f.replace(f.children) }
|
223
|
+
end
|
224
|
+
|
225
|
+
def variant1(node)
|
226
|
+
if (!node["lang"] || node["lang"] == @lang) &&
|
227
|
+
(!node["script"] || node["script"] == @script)
|
228
|
+
elsif found_matching_variant_sibling(node)
|
229
|
+
node["remove"] = "true"
|
230
|
+
else
|
231
|
+
#return unless !node.at("./preceding-sibling::xmlns:variant")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def found_matching_variant_sibling(node)
|
236
|
+
prev = node.xpath("./preceding-sibling::xmlns:variant")
|
237
|
+
foll = node.xpath("./following-sibling::xmlns:variant")
|
238
|
+
found = false
|
239
|
+
(prev + foll).each do |n|
|
240
|
+
found = true if n["lang"] == @lang &&
|
241
|
+
(!n["script"] || n["script"] == @script)
|
242
|
+
end
|
243
|
+
found
|
244
|
+
end
|
143
245
|
end
|
144
246
|
end
|