isodoc 2.0.3 → 2.0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isodoc/convert.rb +36 -18
  3. data/lib/isodoc/function/inline.rb +24 -13
  4. data/lib/isodoc/function/references.rb +1 -1
  5. data/lib/isodoc/i18n.rb +20 -7
  6. data/lib/isodoc/metadata_contributor.rb +1 -1
  7. data/lib/isodoc/presentation_function/bibdata.rb +26 -9
  8. data/lib/isodoc/presentation_function/image.rb +3 -4
  9. data/lib/isodoc/presentation_function/inline.rb +119 -76
  10. data/lib/isodoc/presentation_function/math.rb +1 -0
  11. data/lib/isodoc/presentation_function/xrefs.rb +100 -0
  12. data/lib/isodoc/version.rb +1 -1
  13. data/lib/isodoc/word_function/body.rb +11 -1
  14. data/lib/isodoc/word_function/postprocess.rb +4 -6
  15. data/lib/isodoc/word_function/postprocess_cover.rb +82 -1
  16. data/lib/isodoc/xref/xref_anchor.rb +1 -0
  17. data/lib/isodoc/xref/xref_gen.rb +2 -1
  18. data/lib/isodoc/xref/xref_sect_gen.rb +14 -8
  19. data/lib/isodoc/xslfo_convert.rb +19 -19
  20. data/lib/isodoc-yaml/i18n-ar.yaml +11 -0
  21. data/lib/isodoc-yaml/i18n-de.yaml +11 -0
  22. data/lib/isodoc-yaml/i18n-en.yaml +11 -0
  23. data/lib/isodoc-yaml/i18n-es.yaml +11 -0
  24. data/lib/isodoc-yaml/i18n-fr.yaml +11 -0
  25. data/lib/isodoc-yaml/i18n-ru.yaml +11 -0
  26. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +11 -0
  27. data/spec/isodoc/blocks_spec.rb +13 -77
  28. data/spec/isodoc/inline_spec.rb +564 -22
  29. data/spec/isodoc/metadata_spec.rb +1 -1
  30. data/spec/isodoc/postproc_spec.rb +466 -2
  31. data/spec/isodoc/presentation_xml_spec.rb +139 -0
  32. data/spec/isodoc/ref_spec.rb +7 -7
  33. data/spec/isodoc/section_spec.rb +1 -2
  34. data/spec/isodoc/terms_spec.rb +8 -8
  35. data/spec/isodoc/xref_spec.rb +60 -1188
  36. data/spec/isodoc/xslfo_convert_spec.rb +12 -7
  37. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 645650786b21ed611b894e1e0f2be09efbb300f62997e021d331168b32488699
4
- data.tar.gz: 9dc2ae2007b764bf33f2d406c55a666533f411e057a22eb58bb9b90cb279fe09
3
+ metadata.gz: 7eac37329d91f52ffb48b04b35a58e9d5966ba1ef79492c7e1fd14f77490b81a
4
+ data.tar.gz: e4e1fffbadb350529b5b8bcc4e3f8b13604fd9ceb982d935da33f61722ab1984
5
5
  SHA512:
6
- metadata.gz: f70dccf7ad11c7563a0ed9dad4d7c90b9ca104ca3c46ffbd290544cc31206a9dce2597acafd01a4a5f8ff84c433d430d06c27b96b5b961a76cbe22d204fbc629
7
- data.tar.gz: e000fe9d824d2e8825d1656d52395120373a6e6d40386ca67802337174e3dfaa762d8a3573b21f3418efeaecc81cc9350e0f6ac84024e6b235a8aebb4324f3d5
6
+ metadata.gz: 7f64dbf601952d1e7141ddca015d6fe61e989efd1d751ee9e42575a78e818a3551c4cbb26f5890dc53a1a50c1e75c02deca03e26c64b3568e1f49b76985027c0
7
+ data.tar.gz: fe336da69b2efe89d21299708b62f968109f4ff7be2973cdd6d4f92e56616ff79ee71c024a222794dfdabb7d67b8b50b7d7065f448704d6383f93639846fea20
@@ -40,6 +40,9 @@ module IsoDoc
40
40
  # every 40-odd chars
41
41
  # sectionsplit: split up HTML output on sections
42
42
  # bare: do not insert any prefatory material (coverpage, boilerplate)
43
+ # tocfigures: add ToC for figures
44
+ # toctables: add ToC for tables
45
+ # tocrecommendations: add ToC for rcommendations
43
46
  def initialize(options)
44
47
  @libdir ||= File.dirname(__FILE__) # rubocop:disable Lint/DisjunctiveAssignmentInConstructor
45
48
  options.merge!(default_fonts(options)) do |_, old, new|
@@ -50,25 +53,14 @@ module IsoDoc
50
53
  @options = options
51
54
  @files_to_delete = []
52
55
  @tempfile_cache = []
53
- @htmlstylesheet_name = options[:htmlstylesheet]
54
- @wordstylesheet_name = options[:wordstylesheet]
55
- @htmlstylesheet_override_name = options[:htmlstylesheet_override]
56
- @wordstylesheet_override_name = options[:wordstylesheet_override]
57
- @standardstylesheet_name = options[:standardstylesheet]
58
56
  @sourcefilename = options[:sourcefilename]
59
- @header = options[:header]
60
- @htmlcoverpage = options[:htmlcoverpage]
61
- @wordcoverpage = options[:wordcoverpage]
62
- @htmlintropage = options[:htmlintropage]
63
- @wordintropage = options[:wordintropage]
57
+ init_stylesheets(options)
58
+ init_covers(options)
59
+ init_toc(options)
64
60
  @normalfontsize = options[:normalfontsize]
65
61
  @smallerfontsize = options[:smallerfontsize]
66
62
  @monospacefontsize = options[:monospacefontsize]
67
63
  @footnotefontsize = options[:footnotefontsize]
68
- @scripts = options[:scripts] ||
69
- File.join(File.dirname(__FILE__), "base_style", "scripts.html")
70
- @scripts_pdf = options[:scripts_pdf]
71
- @scripts_override = options[:scripts_override]
72
64
  @i18nyaml = options[:i18nyaml]
73
65
  @ulstyle = options[:ulstyle]
74
66
  @olstyle = options[:olstyle]
@@ -96,10 +88,6 @@ module IsoDoc
96
88
  @script = options[:script] || "Latn"
97
89
  @maxwidth = 1200
98
90
  @maxheight = 800
99
- @wordToClevels = options[:doctoclevels].to_i
100
- @wordToClevels = 2 if @wordToClevels.zero?
101
- @htmlToClevels = options[:htmltoclevels].to_i
102
- @htmlToClevels = 2 if @htmlToClevels.zero?
103
91
  @bookmarks_allocated = { "X" => true }
104
92
  @fn_bookmarks = {}
105
93
  @baseassetpath = options[:baseassetpath]
@@ -108,6 +96,36 @@ module IsoDoc
108
96
  @tmpfilesdir_suffix = tmpfilesdir_suffix
109
97
  end
110
98
 
99
+ def init_covers(options)
100
+ @header = options[:header]
101
+ @htmlcoverpage = options[:htmlcoverpage]
102
+ @wordcoverpage = options[:wordcoverpage]
103
+ @htmlintropage = options[:htmlintropage]
104
+ @wordintropage = options[:wordintropage]
105
+ @scripts = options[:scripts] ||
106
+ File.join(File.dirname(__FILE__), "base_style", "scripts.html")
107
+ @scripts_pdf = options[:scripts_pdf]
108
+ @scripts_override = options[:scripts_override]
109
+ end
110
+
111
+ def init_stylesheets(options)
112
+ @htmlstylesheet_name = options[:htmlstylesheet]
113
+ @wordstylesheet_name = options[:wordstylesheet]
114
+ @htmlstylesheet_override_name = options[:htmlstylesheet_override]
115
+ @wordstylesheet_override_name = options[:wordstylesheet_override]
116
+ @standardstylesheet_name = options[:standardstylesheet]
117
+ end
118
+
119
+ def init_toc(options)
120
+ @wordToClevels = options[:doctoclevels].to_i
121
+ @wordToClevels = 2 if @wordToClevels.zero?
122
+ @htmlToClevels = options[:htmltoclevels].to_i
123
+ @htmlToClevels = 2 if @htmlToClevels.zero?
124
+ @tocfigures = options[:tocfigures]
125
+ @toctables = options[:toctables]
126
+ @tocrecommendations = options[:tocrecommendations]
127
+ end
128
+
111
129
  def tmpimagedir_suffix
112
130
  "_#{SecureRandom.hex(8)}_images"
113
131
  end
@@ -34,30 +34,41 @@ module IsoDoc
34
34
  end
35
35
 
36
36
  def suffix_url(url)
37
- return url if %r{^https?://}.match?(url)
37
+ return url if url.nil? || %r{^https?://|^#}.match?(url)
38
38
  return url unless File.extname(url).empty?
39
39
 
40
40
  url.sub(/#{File.extname(url)}$/, ".html")
41
41
  end
42
42
 
43
43
  def eref_target(node)
44
- return "##{node['bibitemid']}" unless (!@bibitems.nil? &&
45
- url = @bibitems[node["bibitemid"]]&.at(ns("./uri[@type = 'citation']")))
44
+ url = suffix_url(eref_url(node["bibitemid"]))
45
+ anchor = node&.at(ns(".//locality[@type = 'anchor']"))
46
+ return url if url.nil? || /^#/.match?(url) || !anchor
46
47
 
47
- href = suffix_url(url.text)
48
- anchor = node&.at(ns(".//locality[@type = 'anchor']"))&.text&.strip
49
- anchor and href += "##{anchor}"
50
- href
48
+ "#{url}##{anchor.text.strip}"
49
+ end
50
+
51
+ def eref_url(bibitemid)
52
+ return nil if @bibitems.nil? || @bibitems[bibitemid].nil?
53
+
54
+ if url = @bibitems[bibitemid].at(ns("./uri[@type = 'citation']"))
55
+ url.text
56
+ elsif @bibitems[bibitemid]["hidden"] == "true"
57
+ @bibitems[bibitemid]&.at(ns("./uri"))&.text
58
+ else "##{bibitemid}"
59
+ end
51
60
  end
52
61
 
53
62
  def eref_parse(node, out)
54
- href = eref_target(node)
55
- if node["type"] == "footnote"
56
- out.sup do |s|
57
- s.a(**{ href: href }) { |l| no_locality_parse(node, l) }
63
+ if href = eref_target(node)
64
+ if node["type"] == "footnote"
65
+ out.sup do |s|
66
+ s.a(**{ href: href }) { |l| no_locality_parse(node, l) }
67
+ end
68
+ else
69
+ out.a(**{ href: href }) { |l| no_locality_parse(node, l) }
58
70
  end
59
- else
60
- out.a(**{ href: href }) { |l| no_locality_parse(node, l) }
71
+ else no_locality_parse(node, out)
61
72
  end
62
73
  end
63
74
 
@@ -118,7 +118,7 @@ module IsoDoc
118
118
  date_note = bib.at(ns("./note[@type = 'Unpublished-Status']"))
119
119
  return if date_note.nil?
120
120
 
121
- date_note.children.first.replace("<p>#{date_note.content}</p>")
121
+ date_note.children = "<p>#{date_note.content}</p>"
122
122
  footnote_parse(date_note, ref)
123
123
  end
124
124
 
data/lib/isodoc/i18n.rb CHANGED
@@ -104,15 +104,28 @@ module IsoDoc
104
104
  xml.to_xml.gsub(/<b>/, "").gsub("</b>", "").gsub(/<\?[^>]+>/, "")
105
105
  end
106
106
 
107
- def multiple_and(names, andword)
108
- return "" if names.empty?
109
- return names[0] if names.length == 1
110
-
111
- (names.length == 2) &&
112
- (return l10n("#{names[0]} #{andword} #{names[1]}", @lang, @script))
113
- l10n(names[0..-2].join(", ") + " #{andword} #{names[-1]}", @lang, @script)
107
+ def boolean_conj(list, conn)
108
+ case list.size
109
+ when 0 then ""
110
+ when 1 then list.first
111
+ when 2 then @labels["binary_#{conn}"].sub(/%1/, list[0])
112
+ .sub(/%2/, list[1])
113
+ else
114
+ @labels["multiple_#{conn}"]
115
+ .sub(/%1/, l10n(list[0..-2].join(", "), @lang, @script))
116
+ .sub(/%2/, list[-1])
117
+ end
114
118
  end
115
119
 
120
+ # def multiple_and(names, andword)
121
+ # return "" if names.empty?
122
+ # return names[0] if names.length == 1
123
+ #
124
+ # (names.length == 2) &&
125
+ # (return l10n("#{names[0]} #{andword} #{names[1]}", @lang, @script))
126
+ # l10n(names[0..-2].join(", ") + " #{andword} #{names[-1]}", @lang, @script)
127
+ # end
128
+
116
129
  include Function::Utils
117
130
  # module_function :l10n
118
131
  end
@@ -75,7 +75,7 @@ module IsoDoc
75
75
  def agency(xml)
76
76
  agency, publisher = agency1(xml)
77
77
  set(:agency, agency.sub(%r{/$}, ""))
78
- set(:publisher, @i18n.multiple_and(publisher, @labels["and"]))
78
+ set(:publisher, @i18n.boolean_conj(publisher, "and"))
79
79
  agency_addr(xml)
80
80
  end
81
81
 
@@ -1,15 +1,30 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def bibdata(docxml)
4
+ toc_metadata(docxml)
4
5
  docid_prefixes(docxml)
5
6
  a = bibdata_current(docxml) or return
6
7
  address_precompose(a)
7
8
  bibdata_i18n(a)
8
9
  a.next =
9
- "<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join('')}"\
10
+ "<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join}"\
10
11
  "</localized-strings>"
11
12
  end
12
13
 
14
+ def toc_metadata(docxml)
15
+ return unless @tocfigures || @toctables || @tocrecommendations
16
+
17
+ ins = docxml.at(ns("//misc-container")) ||
18
+ docxml.at(ns("//bibdata")).after("<misc-container/>").next_element
19
+ @tocfigures and
20
+ ins << "<toc type='figure'><title>#{@i18n.toc_figures}</title></toc>"
21
+ @toctables and
22
+ ins << "<toc type='table'><title>#{@i18n.toc_tables}</title></toc>"
23
+ @tocfigures and
24
+ ins << "<toc type='recommendation'><title>#{@i18n.toc_recommendations}"\
25
+ "</title></toc>"
26
+ end
27
+
13
28
  def address_precompose(bib)
14
29
  bib.xpath(ns("//bibdata//address")).each do |b|
15
30
  next if b.at(ns("./formattedAddress"))
@@ -66,8 +81,9 @@ module IsoDoc
66
81
  end
67
82
 
68
83
  def i8n_name(hash, pref)
69
- if hash.is_a? Hash then i8n_name1(hash, pref)
70
- elsif hash.is_a? Array
84
+ case hash
85
+ when Hash then i8n_name1(hash, pref)
86
+ when Array
71
87
  hash.reject { |a| blank?(a) }.each_with_object([])
72
88
  .with_index do |(v1, g), i|
73
89
  i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
@@ -78,8 +94,9 @@ module IsoDoc
78
94
 
79
95
  def i8n_name1(hash, pref)
80
96
  hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
81
- if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
82
- elsif v.is_a? Array
97
+ case v
98
+ when Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
99
+ when Array
83
100
  v.reject { |a| blank?(a) }.each_with_index do |v1, i|
84
101
  i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
85
102
  end
@@ -109,11 +126,11 @@ module IsoDoc
109
126
  hash.each_with_object({}) do |(k, v), g|
110
127
  next if blank?(v)
111
128
 
112
- g[k] = if v.is_a? Hash then trim_hash1(hash[k])
113
- elsif v.is_a? Array
129
+ g[k] = case v
130
+ when Hash then trim_hash1(hash[k])
131
+ when Array
114
132
  hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
115
- else
116
- v
133
+ else v
117
134
  end
118
135
  end
119
136
  end
@@ -65,15 +65,14 @@ module IsoDoc
65
65
  uri = svg_to_emf_uri(node)
66
66
  ret = svg_to_emf_filename(uri)
67
67
  File.exists?(ret) and return ret
68
- exe = inkscape_installed? or return nil
68
+ exe = inkscape_installed? or raise "Inkscape missing in PATH, unable" \
69
+ "to convert EMF to SVG. Aborting."
69
70
  uri = Metanorma::Utils::external_path uri
70
71
  exe = Metanorma::Utils::external_path exe
71
72
  system(%(#{exe} --export-type="emf" #{uri})) and
72
73
  return Metanorma::Utils::datauri(ret)
73
74
 
74
- warn %(Fail on #{exe} --export-type="emf" #{uri})
75
-
76
- nil
75
+ raise %(Fail on #{exe} --export-type="emf" #{uri})
77
76
  end
78
77
 
79
78
  def svg_to_emf_uri(node)
@@ -1,56 +1,8 @@
1
1
  require "metanorma-utils"
2
+ require_relative "xrefs"
2
3
 
3
4
  module IsoDoc
4
5
  class PresentationXMLConvert < ::IsoDoc::Convert
5
- def prefix_container(container, linkend, _target)
6
- l10n("#{@xrefs.anchor(container, :xref)}, #{linkend}")
7
- end
8
-
9
- def anchor_value(id)
10
- @xrefs.anchor(id, :value) || @xrefs.anchor(id, :label) ||
11
- @xrefs.anchor(id, :xref)
12
- end
13
-
14
- def anchor_linkend(node, linkend)
15
- if node["citeas"].nil? && node["bibitemid"]
16
- return @xrefs.anchor(node["bibitemid"], :xref) || "???"
17
- elsif node["target"] && node["droploc"]
18
- return anchor_value(node["target"]) || "???"
19
- elsif node["target"] && !/.#./.match(node["target"])
20
- linkend = anchor_linkend1(node)
21
- end
22
-
23
- linkend || "???"
24
- end
25
-
26
- def anchor_linkend1(node)
27
- linkend = @xrefs.anchor(node["target"], :xref)
28
- container = @xrefs.anchor(node["target"], :container, false)
29
- (container && get_note_container_id(node) != container &&
30
- @xrefs.get[node["target"]]) and
31
- linkend = prefix_container(container, linkend, node["target"])
32
- capitalise_xref(node, linkend, anchor_value(node["target"]))
33
- end
34
-
35
- def capitalise_xref(node, linkend, label)
36
- linktext = linkend.gsub(/<[^>]+>/, "")
37
- (label && !label.empty? && /^#{Regexp.escape(label)}/.match?(linktext)) ||
38
- linktext[0, 1].match?(/\p{Upper}/) and return linkend
39
- node["case"] and
40
- return Common::case_with_markup(linkend, node["case"], @script)
41
-
42
- capitalise_xref1(node, linkend)
43
- end
44
-
45
- def capitalise_xref1(node, linkend)
46
- prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
47
- node.xpath("./preceding::text()")
48
- if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
49
- Common::case_with_markup(linkend, "capital", @script)
50
- else linkend
51
- end
52
- end
53
-
54
6
  def nearest_block_parent(node)
55
7
  until %w(p title td th name formula li dt dd sourcecode pre)
56
8
  .include?(node.name)
@@ -61,7 +13,7 @@ module IsoDoc
61
13
 
62
14
  def non_locality_elems(node)
63
15
  node.children.reject do |c|
64
- %w{locality localityStack}.include? c.name
16
+ %w{locality localityStack location}.include? c.name
65
17
  end
66
18
  end
67
19
 
@@ -69,7 +21,8 @@ module IsoDoc
69
21
  c1 = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
70
22
  return unless c1.empty?
71
23
 
72
- link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
24
+ link = anchor_linkend(node, docid_l10n(node["target"] ||
25
+ expand_citeas(node["citeas"])))
73
26
  link += eref_localities(node.xpath(ns("./locality | ./localityStack")),
74
27
  link, node)
75
28
  non_locality_elems(node).each(&:remove)
@@ -78,54 +31,144 @@ module IsoDoc
78
31
  # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
79
32
  # <locality type="section"><reference>3.1</reference></locality></origin>
80
33
 
34
+ def expand_citeas(text)
35
+ text.nil? and return text
36
+ HTMLEntities.new.decode(text.gsub(/&amp;#x/, "&#"))
37
+ end
38
+
81
39
  def eref_localities(refs, target, node)
82
- ret = ""
83
- refs.each_with_index do |r, i|
84
- delim = ","
85
- delim = ";" if r.name == "localityStack" && i.positive?
86
- ret = eref_locality_stack(r, i, target, delim, ret, node)
40
+ if can_conflate_eref_rendering?(refs)
41
+ l10n(", #{eref_localities_conflated(refs, target, node)}")
42
+ else
43
+ ret = resolve_eref_connectives(eref_locality_stacks(refs, target, node))
44
+ l10n(ret.join)
87
45
  end
88
- ret
89
46
  end
90
47
 
91
- def eref_locality_stack(ref, idx, target, delim, ret, node)
48
+ def eref_localities_conflated(refs, target, node)
49
+ droploc = node["droploc"]
50
+ node["droploc"] = true
51
+ ret = resolve_eref_connectives(eref_locality_stacks(refs, target,
52
+ node))
53
+ node["droploc"] = droploc
54
+ eref_localities1(target,
55
+ refs.first.at(ns("./locality/@type")).text,
56
+ l10n(ret[1..-1].join), nil, node, @lang)
57
+ end
58
+
59
+ def can_conflate_eref_rendering?(refs)
60
+ (refs.size > 1 &&
61
+ refs.all? { |r| r.name == "localityStack" } &&
62
+ refs.all? { |r| r.xpath(ns("./locality")).size == 1 }) or return false
63
+
64
+ first = refs.first.at(ns("./locality/@type")).text
65
+ refs.all? do |r|
66
+ r.at(ns("./locality/@type")).text == first
67
+ end
68
+ end
69
+
70
+ def resolve_eref_connectives(locs)
71
+ locs = resolve_comma_connectives(locs)
72
+ locs = resolve_to_connectives(locs)
73
+ return locs if locs.size < 3
74
+
75
+ locs = locs.each_slice(2).with_object([]) do |a, m|
76
+ m << { conn: a[0], target: a[1] }
77
+ end
78
+ [", ", combine_conn(locs)]
79
+ end
80
+
81
+ def resolve_comma_connectives(locs)
82
+ locs1 = []
83
+ add = ""
84
+ until locs.empty?
85
+ if [", ", " "].include?(locs[1])
86
+ add += locs[0..2].join
87
+ locs.shift(3)
88
+ else
89
+ locs1 << add unless add.empty?
90
+ add = ""
91
+ locs1 << locs.shift
92
+ end
93
+ end
94
+ locs1 << add unless add.empty?
95
+ locs1
96
+ end
97
+
98
+ def resolve_to_connectives(locs)
99
+ locs1 = []
100
+ until locs.empty?
101
+ if locs[1] == "to"
102
+ locs1 << @i18n.chain_to.sub(/%1/, locs[0]).sub(/%2/, locs[2])
103
+ locs.shift(3)
104
+ else locs1 << locs.shift
105
+ end
106
+ end
107
+ locs1
108
+ end
109
+
110
+ def eref_locality_stacks(refs, target, node)
111
+ ret = refs.each_with_index.with_object([]) do |(r, i), m|
112
+ added = eref_locality_stack(r, i, target, node)
113
+ added.empty? and next
114
+ added.each { |a| m << a }
115
+ next if i == refs.size - 1
116
+
117
+ m << if r&.next_element&.name == "localityStack"
118
+ r.next_element["connective"]
119
+ else locality_delimiter(r)
120
+ end
121
+ end
122
+ ret.empty? ? ret : [", "] + ret
123
+ end
124
+
125
+ def eref_locality_stack(ref, idx, target, node)
126
+ ret = []
92
127
  if ref.name == "localityStack"
93
128
  ref.elements.each_with_index do |rr, j|
94
- ret += eref_localities0(rr, j, target, delim, node)
95
- delim = ","
129
+ l = eref_localities0(rr, j, target, node) or next
130
+
131
+ ret << l
132
+ ret << locality_delimiter(rr) unless j == ref.elements.size - 1
96
133
  end
97
- else ret += eref_localities0(ref, idx, target, delim, node)
134
+ else
135
+ l = eref_localities0(ref, idx, target, node) and ret << l
98
136
  end
137
+ ret[-1] == ", " and ret.pop
99
138
  ret
100
139
  end
101
140
 
102
- def eref_localities0(ref, _idx, target, delim, node)
103
- if ref["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
141
+ def locality_delimiter(_loc)
142
+ ", "
143
+ end
144
+
145
+ def eref_localities0(ref, _idx, target, node)
146
+ if ref["type"] == "whole" then @i18n.wholeoftext
104
147
  else
105
- eref_localities1(target, ref["type"], ref.at(ns("./referenceFrom")),
106
- ref.at(ns("./referenceTo")), delim, node, @lang)
148
+ eref_localities1(target, ref["type"],
149
+ ref&.at(ns("./referenceFrom"))&.text,
150
+ ref&.at(ns("./referenceTo"))&.text, node, @lang)
107
151
  end
108
152
  end
109
153
 
110
154
  # TODO: move to localization file
111
- def eref_localities1_zh(_target, type, from, upto, node, delim)
112
- ret = "#{delim} 第#{from.text}" if from
113
- ret += "&ndash;#{upto.text}" if upto
114
- loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
155
+ def eref_localities1_zh(_target, type, from, upto, node)
156
+ ret = "第#{from}" if from
157
+ ret += "&ndash;#{upto}" if upto
158
+ loc = eref_locality_populate(type, node)
115
159
  ret += " #{loc}" unless node["droploc"] == "true"
116
160
  ret
117
161
  end
118
162
 
119
163
  # TODO: move to localization file
120
- def eref_localities1(target, type, from, upto, delim, node, lang = "en")
121
- return "" if type == "anchor"
164
+ def eref_localities1(target, type, from, upto, node, lang = "en")
165
+ return nil if type == "anchor"
122
166
 
123
167
  lang == "zh" and
124
- return l10n(eref_localities1_zh(target, type, from, upto, node, delim))
125
- ret = delim
126
- ret += eref_locality_populate(type, node)
127
- ret += " #{from.text}" if from
128
- ret += "&ndash;#{upto.text}" if upto
168
+ return l10n(eref_localities1_zh(target, type, from, upto, node))
169
+ ret = eref_locality_populate(type, node)
170
+ ret += " #{from}" if from
171
+ ret += "&ndash;#{upto}" if upto
129
172
  l10n(ret)
130
173
  end
131
174
 
@@ -20,6 +20,7 @@ module IsoDoc
20
20
  num = BigDecimal(x.text)
21
21
  precision = /\./.match?(x.text) ? x.text.sub(/^.*\./, "").size : 0
22
22
  x.children = localized_number(num, locale, precision)
23
+ rescue ArgumentError => e
23
24
  end
24
25
  end
25
26
 
@@ -0,0 +1,100 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def prefix_container(container, linkend, _target)
4
+ l10n("#{@xrefs.anchor(container, :xref)}, #{linkend}")
5
+ end
6
+
7
+ def anchor_value(id)
8
+ @xrefs.anchor(id, :value) || @xrefs.anchor(id, :label) ||
9
+ @xrefs.anchor(id, :xref)
10
+ end
11
+
12
+ def anchor_linkend(node, linkend)
13
+ if node["citeas"].nil? && node["bibitemid"]
14
+ return @xrefs.anchor(node["bibitemid"], :xref) || "???"
15
+ elsif node.at(ns("./location"))
16
+ linkend = combine_xref_locations(node)
17
+ elsif node["target"] && node["droploc"]
18
+ return anchor_value(node["target"]) || "???"
19
+ elsif node["target"] && !/.#./.match(node["target"])
20
+ linkend = anchor_linkend1(node)
21
+ end
22
+
23
+ linkend || "???"
24
+ end
25
+
26
+ def anchor_linkend1(node)
27
+ linkend = @xrefs.anchor(node["target"], :xref)
28
+ container = @xrefs.anchor(node["target"], :container, false)
29
+ (container && get_note_container_id(node) != container &&
30
+ @xrefs.get[node["target"]]) and
31
+ linkend = prefix_container(container, linkend, node["target"])
32
+ capitalise_xref(node, linkend, anchor_value(node["target"]))
33
+ end
34
+
35
+ def combine_xref_locations(node)
36
+ locs = gather_xref_locations(node)
37
+ linkend = if can_conflate_xref_rendering?(locs)
38
+ out = locs.each { |l| l[:target] = anchor_value(l[:target]) }
39
+ l10n("#{locs.first[:elem]} #{combine_conn(out)}")
40
+ else
41
+ out = locs.each { |l| l[:target] = anchor_linked1(l[:node]) }
42
+ l10n(combine_conn(out))
43
+ end
44
+ capitalise_xref(node, linkend, anchor_value(node["target"]))
45
+ end
46
+
47
+ def gather_xref_locations(node)
48
+ node.xpath(ns("./location")).each_with_object([]) do |l, m|
49
+ type = @xrefs.anchor(l["target"], :type)
50
+ m << { conn: l["connective"], target: l["target"],
51
+ type: type, node: l, elem: @xrefs.anchor(l["target"], :elem),
52
+ container: @xrefs.anchor(node["target"], :container, false) ||
53
+ %w(termnote).include?(type) }
54
+ end
55
+ end
56
+
57
+ def combine_conn(list)
58
+ return list.first[:target] if list.size == 1
59
+
60
+ if list[1..-1].all? { |l| l[:conn] == "and" }
61
+ @i18n.boolean_conj(list.map { |l| l[:target] }, "and")
62
+ elsif list[1..-1].all? { |l| l[:conn] == "or" }
63
+ @i18n.boolean_conj(list.map { |l| l[:target] }, "or")
64
+ else
65
+ ret = list[0][:target]
66
+ list[1..-1].each { |l| ret = i18n_chain_boolean(ret, l) }
67
+ ret
68
+ end
69
+ end
70
+
71
+ def i18n_chain_boolean(value, entry)
72
+ @i18n.send("chain_#{entry[:conn]}").sub(/%1/, value)
73
+ .sub(/%2/, entry[:target])
74
+ end
75
+
76
+ def can_conflate_xref_rendering?(locs)
77
+ !locs.all? { |l| l[:container].nil? } &&
78
+ locs.all? { |l| l[:type] == locs[0][:type] }
79
+ end
80
+
81
+ def capitalise_xref(node, linkend, label)
82
+ linktext = linkend.gsub(/<[^>]+>/, "")
83
+ (label && !label.empty? && /^#{Regexp.escape(label)}/.match?(linktext)) ||
84
+ linktext[0, 1].match?(/\p{Upper}/) and return linkend
85
+ node["case"] and
86
+ return Common::case_with_markup(linkend, node["case"], @script)
87
+
88
+ capitalise_xref1(node, linkend)
89
+ end
90
+
91
+ def capitalise_xref1(node, linkend)
92
+ prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
93
+ node.xpath("./preceding::text()")
94
+ if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
95
+ Common::case_with_markup(linkend, "capital", @script)
96
+ else linkend
97
+ end
98
+ end
99
+ end
100
+ end
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "2.0.3".freeze
2
+ VERSION = "2.0.5.1".freeze
3
3
  end