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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1a16a6af5cb8621eb1dd8e14a2680e7858476d5ffc1007e45566928e9ebaef7
4
- data.tar.gz: ef5696d693f602b825457939bfab6f1ccfd827a9f24cbfa975ee6120c603b264
3
+ metadata.gz: 491a322b0df2e6b1c8b4f12e520ca349657a009058b416067acdd5437a16085c
4
+ data.tar.gz: 1f52844ffdc37875d2b40f8d46f52263abcbe5101c99adaf88d839a28a18ed49
5
5
  SHA512:
6
- metadata.gz: f3f8718e404915ce3d9d7ad8de1b4f6c0eb6442c930ced3e05c6f1db25ee23324de1783c3fe96e41e86d765a705b7b41df78bd159ff1333f3809ed2682188cc6
7
- data.tar.gz: 0ba52d047fb5b1119d1cf485eea60511066f5fec0152222123cedea05f346a7f2276a9ac90aede713d6ae14b3a2be4c5e41267ffdb4ccdff285b5d13350cd26c
6
+ metadata.gz: ce472eadec9ab44d5739f0e506813cb89cf7de6def2909e8ffd0788cf4fe246bf3433b75c22490528b0287bbfad1e2cc5ca50eeaacdd4156fe9bb32a36e912df
7
+ data.tar.gz: efb30d195c6a15f97133b76d1d4cac762800fe7620d11a58a2655e7ccd3bc972827d419337cbff13fb7d1c4b96004da7b9d95323ae7d8f6c1eaa07d784f67834
@@ -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
- - name: Use Ruby
35
- uses: ruby/setup-ruby@v1
35
+ - uses: ruby/setup-ruby@v1
36
36
  with:
37
37
  ruby-version: ${{ matrix.ruby }}
38
- bundler-cache: true
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
- - name: Update gems
61
- run: bundle install --jobs 4 --retry 3
62
-
63
- - name: Run specs
64
- run: bundle exec rake
69
+ - run: bundle exec rake
@@ -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/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/metanorma/isodoc/actions?query=workflow%3Aubuntu"]
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"]
@@ -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'application
2
+ scope: Domaine dapplication
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'est defini dans le présent document.</p>
21
+ <p>Aucun terme nest 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'appliquent.</p>
23
+ <p>Pour les besoins du présent document, les termes et définitions suivants sappliquent.</p>
24
24
  norm_with_refs_pref:
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).
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 sapplique. Pour les références non datées, la dernière édition du document de référence sapplique (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'appliquent.</p>
29
+ <p>Pour les besoins du présent document, les termes et définitions de % sappliquent.</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'appliquent.</p>
31
+ <p>Pour les besoins du présent document, les termes et définitions de % ainsi que les suivants, sappliquent.</p>
32
+ term_defined_in: "[terme défini dans %]"
32
33
  note: NOTE
33
34
  note_xref: Note
34
- termnote: Note % à l'article
35
+ termnote: Note % à larticle
35
36
  figure: Figure
36
37
  formula: Formule
37
38
  inequality: Formule
@@ -31,6 +31,7 @@ external_terms_boilerplate: |
31
31
  <p>% 界定的术语和定义适用于本文件。</p>
32
32
  internal_external_terms_boilerplate: |
33
33
  <p>% 界定的以及下列术语和定义适用于本文件。</p>
34
+ term_defined_in: "〖术语于%中定义〗"
34
35
  note: 注
35
36
  note_xref: 注
36
37
  termnote: 注%
@@ -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 = 'ISO DATE']"))
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
@@ -221,6 +221,7 @@ module IsoDoc::HtmlFunction
221
221
  MATHJAX = <<~"MATHJAX".freeze
222
222
  <script type="text/x-mathjax-config">
223
223
  MathJax.Hub.Config({
224
+ "HTML-CSS": { preferredFont: "STIX" },
224
225
  asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
225
226
  });
226
227
  </script>
@@ -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, "&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)
@@ -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(node)
55
- 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) }
56
58
  return unless contents.empty?
57
- link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
58
- link += eref_localities(node.xpath(ns("./locality | ./localityStack")), link)
59
- non_locality_elems(node).each { |n| n.remove }
60
- 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)
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
- 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))
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 do |f|
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 do |f|
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 do |f|
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 do |f|
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