isodoc 1.1.4 → 1.2.4

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/isodoc-yaml/i18n-en.yaml +4 -1
  3. data/lib/isodoc-yaml/i18n-fr.yaml +4 -1
  4. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +4 -1
  5. data/lib/isodoc.rb +1 -0
  6. data/lib/isodoc/base_style/metanorma_word.css +6 -0
  7. data/lib/isodoc/base_style/metanorma_word.scss +6 -0
  8. data/lib/isodoc/common.rb +0 -2
  9. data/lib/isodoc/convert.rb +34 -28
  10. data/lib/isodoc/function/blocks.rb +11 -22
  11. data/lib/isodoc/function/blocks_example_note.rb +14 -15
  12. data/lib/isodoc/function/cleanup.rb +5 -4
  13. data/lib/isodoc/function/inline.rb +6 -76
  14. data/lib/isodoc/function/references.rb +13 -10
  15. data/lib/isodoc/function/reqt.rb +12 -11
  16. data/lib/isodoc/function/section.rb +51 -54
  17. data/lib/isodoc/function/table.rb +2 -6
  18. data/lib/isodoc/function/terms.rb +13 -6
  19. data/lib/isodoc/function/to_word_html.rb +3 -0
  20. data/lib/isodoc/function/utils.rb +6 -5
  21. data/lib/isodoc/html_function/html.rb +1 -1
  22. data/lib/isodoc/{function/i18n.rb → i18n.rb} +37 -37
  23. data/lib/isodoc/metadata.rb +4 -3
  24. data/lib/isodoc/metadata_date.rb +1 -1
  25. data/lib/isodoc/presentation_function/block.rb +152 -0
  26. data/lib/isodoc/presentation_function/inline.rb +131 -0
  27. data/lib/isodoc/presentation_function/section.rb +46 -0
  28. data/lib/isodoc/presentation_xml_convert.rb +39 -5
  29. data/lib/isodoc/version.rb +1 -1
  30. data/lib/isodoc/word_function/body.rb +13 -8
  31. data/lib/isodoc/word_function/inline.rb +3 -1
  32. data/lib/isodoc/word_function/postprocess.rb +1 -1
  33. data/lib/isodoc/word_function/table.rb +3 -2
  34. data/lib/isodoc/xref.rb +6 -3
  35. data/lib/isodoc/xref/xref_counter.rb +21 -7
  36. data/lib/isodoc/xref/xref_gen.rb +27 -4
  37. data/lib/isodoc/xref/xref_sect_gen.rb +3 -3
  38. data/spec/assets/i18n.yaml +12 -1
  39. data/spec/isodoc/blocks_spec.rb +1338 -147
  40. data/spec/isodoc/cleanup_spec.rb +5 -3
  41. data/spec/isodoc/footnotes_spec.rb +2 -2
  42. data/spec/isodoc/i18n_spec.rb +679 -110
  43. data/spec/isodoc/inline_spec.rb +323 -142
  44. data/spec/isodoc/lists_spec.rb +2 -2
  45. data/spec/isodoc/postproc_spec.rb +1347 -1333
  46. data/spec/isodoc/ref_spec.rb +181 -3
  47. data/spec/isodoc/section_spec.rb +633 -681
  48. data/spec/isodoc/table_spec.rb +386 -136
  49. data/spec/isodoc/terms_spec.rb +111 -79
  50. data/spec/isodoc/xref_spec.rb +1597 -1186
  51. metadata +6 -3
@@ -4,7 +4,6 @@ require "base64"
4
4
  module IsoDoc::HtmlFunction
5
5
  module Html
6
6
  def convert1(docxml, filename, dir)
7
- @xrefs.parse docxml
8
7
  noko do |xml|
9
8
  xml.html **{ lang: "#{@lang}" } do |html|
10
9
  info docxml, nil
@@ -32,6 +31,7 @@ module IsoDoc::HtmlFunction
32
31
  def make_body3(body, docxml)
33
32
  body.div **{ class: "main-section" } do |div3|
34
33
  boilerplate docxml, div3
34
+ preface_block docxml, div3
35
35
  abstract docxml, div3
36
36
  foreword docxml, div3
37
37
  introduction docxml, div3
@@ -1,29 +1,48 @@
1
1
  require "yaml"
2
2
 
3
- # TODO: Cleanup and generalize
4
- module IsoDoc::Function
5
- module I18n
6
- def load_yaml(lang, script)
7
- if @i18nyaml then YAML.load_file(@i18nyaml)
8
- elsif lang == "en"
3
+ module IsoDoc
4
+ class I18n
5
+ def load_yaml(lang, script, i18nyaml = nil)
6
+ ret = load_yaml1(lang, script)
7
+ return ret.merge(YAML.load_file(i18nyaml)) if i18nyaml
8
+ ret
9
+ end
10
+
11
+ def load_yaml1(lang, script)
12
+ if lang == "en"
9
13
  YAML.load_file(File.join(File.dirname(__FILE__),
10
- "../../isodoc-yaml/i18n-en.yaml"))
14
+ "../isodoc-yaml/i18n-en.yaml"))
11
15
  elsif lang == "fr"
12
16
  YAML.load_file(File.join(File.dirname(__FILE__),
13
- "../../isodoc-yaml/i18n-fr.yaml"))
17
+ "../isodoc-yaml/i18n-fr.yaml"))
14
18
  elsif lang == "zh" && script == "Hans"
15
19
  YAML.load_file(File.join(File.dirname(__FILE__),
16
- "../../isodoc-yaml/i18n-zh-Hans.yaml"))
20
+ "../isodoc-yaml/i18n-zh-Hans.yaml"))
17
21
  else
18
22
  YAML.load_file(File.join(File.dirname(__FILE__),
19
- "../../isodoc-yaml/i18n-en.yaml"))
23
+ "../isodoc-yaml/i18n-en.yaml"))
20
24
  end
21
25
  end
22
26
 
23
- def i18n_init(lang, script)
27
+ def get
28
+ @labels
29
+ end
30
+
31
+ def set(x, y)
32
+ @labels[x] = y
33
+ end
34
+
35
+ def initialize(lang, script, i18nyaml = nil)
24
36
  @lang = lang
25
37
  @script = script
26
- y = load_yaml(lang, script)
38
+ y = load_yaml(lang, script, i18nyaml)
39
+ @labels = y
40
+ @labels["language"] = @lang
41
+ @labels["script"] = @script
42
+ @labels.each do |k, v|
43
+ self.class.send(:define_method, k.downcase) { v }
44
+ end
45
+ =begin
27
46
  @term_def_boilerplate = y["term_def_boilerplate"]
28
47
  @scope_lbl = y["scope"]
29
48
  @symbols_lbl = y["symbols"]
@@ -71,30 +90,11 @@ module IsoDoc::Function
71
90
  @requirement_lbl = y["requirement"]
72
91
  @locality = y["locality"]
73
92
  @admonition = y["admonition"]
74
- @labels = y
75
- @labels["language"] = @lang
76
- @labels["script"] = @script
93
+ =end
77
94
  end
78
95
 
79
- # TODO: move to localization file
80
- def eref_localities1_zh(target, type, from, to, delim)
81
- ret = "#{delim} 第#{from.text}" if from
82
- ret += "–#{to}" if to
83
- loc = (@locality[type] || type.sub(/^locality:/, "").capitalize )
84
- ret += " #{loc}"
85
- ret
86
- end
87
-
88
- # TODO: move to localization file
89
- def eref_localities1(target, type, from, to, delim, lang = "en")
90
- return "" if type == "anchor"
91
- return l10n(eref_localities1_zh(target, type, from, to, delim)) if lang == "zh"
92
- ret = delim
93
- loc = @locality[type] || type.sub(/^locality:/, "").capitalize
94
- ret += " #{loc}"
95
- ret += " #{from.text}" if from
96
- ret += "–#{to.text}" if to
97
- l10n(ret)
96
+ def self.l10n(x, lang = @lang, script = @script)
97
+ l10n(x, lang, script)
98
98
  end
99
99
 
100
100
  # TODO: move to localization file
@@ -106,8 +106,8 @@ module IsoDoc::Function
106
106
  xml.traverse do |n|
107
107
  next unless n.text?
108
108
  n.replace(n.text.gsub(/ /, "").gsub(/:/, ":").gsub(/,/, "、").
109
- gsub(/\(/, "(").gsub(/\)/, ")").
110
- gsub(/\[/, "【").gsub(/\]/, "】"))
109
+ gsub(/\(/, "(").gsub(/\)/, ")").
110
+ gsub(/\[/, "【").gsub(/\]/, "】"))
111
111
  end
112
112
  xml.to_xml.gsub(/<b>/, "").gsub("</b>", "").gsub(/<\?[^>]+>/, "")
113
113
  else
@@ -115,7 +115,7 @@ module IsoDoc::Function
115
115
  end
116
116
  end
117
117
 
118
- module_function :l10n
118
+ #module_function :l10n
119
119
 
120
120
  end
121
121
  end
@@ -16,16 +16,17 @@ module IsoDoc
16
16
  end
17
17
 
18
18
  def l10n(a, b, c)
19
- IsoDoc::Function::I18n::l10n(a, b, c)
19
+ @i18n.l10n(a, b, c)
20
20
  end
21
21
 
22
- def initialize(lang, script, labels, fonts_options = {})
22
+ def initialize(lang, script, i18n, fonts_options = {})
23
23
  @metadata = {}
24
24
  DATETYPES.each { |w| @metadata["#{w.gsub(/-/, '_')}date".to_sym] = 'XXX' }
25
25
  @lang = lang
26
26
  @script = script
27
27
  @c = HTMLEntities.new
28
- @labels = labels
28
+ @i18n = i18n
29
+ @labels = @i18n.get
29
30
  @fonts_options = fonts_options
30
31
  end
31
32
 
@@ -20,7 +20,7 @@ module IsoDoc
20
20
  def monthyr(isodate)
21
21
  m = /(?<yr>\d\d\d\d)-(?<mo>\d\d)/.match isodate
22
22
  return isodate unless m && m[:yr] && m[:mo]
23
- IsoDoc::Function::I18n::l10n("#{months[m[:mo].to_sym]} #{m[:yr]}",
23
+ l10n("#{months[m[:mo].to_sym]} #{m[:yr]}",
24
24
  @lang, @script)
25
25
  end
26
26
 
@@ -0,0 +1,152 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def figure(docxml)
4
+ docxml.xpath(ns("//figure")).each do |f|
5
+ figure1(f)
6
+ end
7
+ end
8
+
9
+ def figure1(f)
10
+ return sourcecode1(f) if f["class"] == "pseudocode" ||
11
+ f["type"] == "pseudocode"
12
+ return if labelled_ancestor(f) && f.ancestors("figure").empty?
13
+ return if f.at(ns("./figure")) and !f.at(ns("./name"))
14
+ lbl = @xrefs.anchor(f['id'], :label, false) or return
15
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.figure} #{lbl}"), "name")
16
+ end
17
+
18
+ def prefix_name(f, delim, number, elem)
19
+ return if number.nil? || number.empty?
20
+ unless name = f.at(ns("./#{elem}"))
21
+ f.children.empty? and f.add_child("<#{elem}></#{elem}>") or
22
+ f.children.first.previous = "<#{elem}></#{elem}>"
23
+ name = f.children.first
24
+ end
25
+ name.children.empty? ? name.add_child(number) :
26
+ ( name.children.first.previous = "#{number}#{delim}" )
27
+ end
28
+
29
+ def sourcecode(docxml)
30
+ docxml.xpath(ns("//sourcecode")).each do |f|
31
+ sourcecode1(f)
32
+ end
33
+ end
34
+
35
+ def sourcecode1(f)
36
+ return if labelled_ancestor(f)
37
+ return unless f.ancestors("example").empty?
38
+ lbl = @xrefs.anchor(f['id'], :label, false) or return
39
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.figure} #{lbl}"), "name")
40
+ end
41
+
42
+ def formula(docxml)
43
+ docxml.xpath(ns("//formula")).each do |f|
44
+ formula1(f)
45
+ end
46
+ end
47
+
48
+ # introduce name element
49
+ def formula1(f)
50
+ lbl = @xrefs.anchor(f['id'], :label, false)
51
+ prefix_name(f, "", lbl, "name")
52
+ end
53
+
54
+ def example(docxml)
55
+ docxml.xpath(ns("//example")).each do |f|
56
+ example1(f)
57
+ end
58
+ end
59
+
60
+ def termexample(docxml)
61
+ docxml.xpath(ns("//termexample")).each do |f|
62
+ example1(f)
63
+ end
64
+ end
65
+
66
+ def example1(f)
67
+ n = @xrefs.get[f["id"]]
68
+ lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example :
69
+ l10n("#{@i18n.example} #{n[:label]}")
70
+ prefix_name(f, "&nbsp;&mdash; ", lbl, "name")
71
+ end
72
+
73
+ def note(docxml)
74
+ docxml.xpath(ns("//note")).each do |f|
75
+ note1(f)
76
+ end
77
+ end
78
+
79
+ # introduce name element
80
+ def note1(f)
81
+ return if f.parent.name == "bibitem"
82
+ n = @xrefs.get[f["id"]]
83
+ lbl = (@i18n.note if n.nil? || n[:label].nil? || n[:label].empty?) ?
84
+ @i18n.note : l10n("#{@i18n.note} #{n[:label]}")
85
+ prefix_name(f, "", lbl, "name")
86
+ end
87
+
88
+ def termnote(docxml)
89
+ docxml.xpath(ns("//termnote")).each do |f|
90
+ termnote1(f)
91
+ end
92
+ end
93
+
94
+ # introduce name element
95
+ def termnote1(f)
96
+ lbl = l10n(@xrefs.anchor(f['id'], :label) || '???')
97
+ prefix_name(f, "", lbl, "name")
98
+ end
99
+
100
+ def recommendation(docxml)
101
+ docxml.xpath(ns("//recommendation")).each do |f|
102
+ recommendation1(f, @i18n.recommendation)
103
+ end
104
+ end
105
+
106
+ def requirement(docxml)
107
+ docxml.xpath(ns("//requirement")).each do |f|
108
+ recommendation1(f, @i18n.requirement)
109
+ end
110
+ end
111
+
112
+ def permission(docxml)
113
+ docxml.xpath(ns("//permission")).each do |f|
114
+ recommendation1(f, @i18n.permission)
115
+ end
116
+ end
117
+
118
+ # introduce name element
119
+ def recommendation1(f, type)
120
+ n = @xrefs.anchor(f['id'], :label, false)
121
+ lbl = (n.nil? ? type : l10n("#{type} #{n}"))
122
+ prefix_name(f, "", lbl, "name")
123
+ end
124
+
125
+ def table(docxml)
126
+ docxml.xpath(ns("//table")).each do |f|
127
+ table1(f)
128
+ end
129
+ end
130
+
131
+ def table1(f)
132
+ return if labelled_ancestor(f)
133
+ return if f["unnumbered"] && !f.at(ns("./name"))
134
+ n = @xrefs.anchor(f['id'], :label, false)
135
+ prefix_name(f, "&nbsp;&mdash; ", l10n("#{@i18n.table} #{n}"), "name")
136
+ end
137
+
138
+ # we use this to eliminate the semantic amend blocks from rendering
139
+ def amend(docxml)
140
+ docxml.xpath(ns("//amend")).each do |f|
141
+ amend1(f)
142
+ end
143
+ end
144
+
145
+ def amend1(f)
146
+ f.xpath(ns("./autonumber")).each { |a| a.remove }
147
+ f.xpath(ns("./newcontent")).each { |a| a.name = "quote" }
148
+ f.xpath(ns("./description")).each { |a| a.replace(a.children) }
149
+ f.replace(f.children)
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,131 @@
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_linkend(node, linkend)
8
+ if node["citeas"].nil? && node["bibitemid"]
9
+ return @xrefs.anchor(node["bibitemid"] ,:xref) || "???"
10
+ 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
+ end
18
+ linkend || "???"
19
+ end
20
+
21
+ def capitalise_xref(node, linkend)
22
+ return linkend unless %w(Latn Cyrl Grek).include? @script
23
+ return linkend&.capitalize if node["case"] == "capital"
24
+ return linkend&.downcase if node["case"] == "lowercase"
25
+ return linkend if linkend[0,1].match(/\p{Upper}/)
26
+ prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
27
+ node.xpath("./preceding::text()")
28
+ (prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map { |p| p.text }.join)) ?
29
+ linkend&.capitalize : linkend
30
+ end
31
+
32
+ def nearest_block_parent(node)
33
+ until %w(p title td th name formula
34
+ li dt dd sourcecode pre).include?(node.name)
35
+ node = node.parent
36
+ end
37
+ node
38
+ end
39
+
40
+ def non_locality_elems(node)
41
+ node.children.select do |c|
42
+ !%w{locality localityStack}.include? c.name
43
+ end
44
+ end
45
+
46
+ def get_linkend(node)
47
+ contents = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
48
+ 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)
53
+ end
54
+ # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
55
+ # <locality type="section"><reference>3.1</reference></locality></origin>
56
+
57
+ def eref_localities(refs, target)
58
+ ret = ""
59
+ refs.each_with_index do |r, i|
60
+ delim = ","
61
+ 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)
69
+ end
70
+ end
71
+ ret
72
+ end
73
+
74
+ def eref_localities0(r, i, target, delim)
75
+ if r["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
76
+ else
77
+ eref_localities1(target, r["type"], r.at(ns("./referenceFrom")),
78
+ r.at(ns("./referenceTo")), delim, @lang)
79
+ end
80
+ end
81
+
82
+ # TODO: move to localization file
83
+ def eref_localities1_zh(target, type, from, to, delim)
84
+ ret = "#{delim} 第#{from.text}" if from
85
+ ret += "&ndash;#{to.text}" if to
86
+ loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize )
87
+ ret += " #{loc}"
88
+ ret
89
+ end
90
+
91
+ # TODO: move to localization file
92
+ def eref_localities1(target, type, from, to, delim, lang = "en")
93
+ return "" if type == "anchor"
94
+ return l10n(eref_localities1_zh(target, type, from, to, delim)) if lang == "zh"
95
+ ret = delim
96
+ loc = @i18n.locality[type] || type.sub(/^locality:/, "").capitalize
97
+ ret += " #{loc}"
98
+ ret += " #{from.text}" if from
99
+ ret += "&ndash;#{to.text}" if to
100
+ l10n(ret)
101
+ end
102
+
103
+ def xref(docxml)
104
+ docxml.xpath(ns("//xref")).each do |f|
105
+ xref1(f)
106
+ end
107
+ end
108
+
109
+ def eref(docxml)
110
+ docxml.xpath(ns("//eref")).each do |f|
111
+ xref1(f)
112
+ end
113
+ end
114
+
115
+ def origin(docxml)
116
+ docxml.xpath(ns("//origin[not(termref)]")).each do |f|
117
+ xref1(f)
118
+ end
119
+ end
120
+
121
+ def quotesource(docxml)
122
+ docxml.xpath(ns("//quote/source")).each do |f|
123
+ xref1(f)
124
+ end
125
+ end
126
+
127
+ def xref1(f)
128
+ get_linkend(f)
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,46 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def clause(docxml)
4
+ docxml.xpath(ns("//clause | "\
5
+ "//terms | //definitions | //references")).
6
+ each do |f|
7
+ clause1(f)
8
+ end
9
+ end
10
+
11
+ def clause1(f)
12
+ level = @xrefs.anchor(f['id'], :level, false) || "1"
13
+ t = f.at(ns("./title")) and t["depth"] = level
14
+ return if !f.ancestors("boilerplate").empty?
15
+ return if @suppressheadingnumbers || f["unnumbered"]
16
+ lbl = @xrefs.anchor(f['id'], :label,
17
+ f.parent.name != "sections") or return
18
+ prefix_name(f, "<tab/>", "#{lbl}#{clausedelim}", "title")
19
+ end
20
+
21
+ def annex(docxml)
22
+ docxml.xpath(ns("//annex")).each do |f|
23
+ annex1(f)
24
+ end
25
+ end
26
+
27
+ def annex1(f)
28
+ lbl = @xrefs.anchor(f['id'], :label)
29
+ if t = f.at(ns("./title"))
30
+ t.children = "<strong>#{t.children.to_xml}</strong>"
31
+ end
32
+ prefix_name(f, "<br/><br/>", lbl, "title")
33
+ end
34
+
35
+ def term(docxml)
36
+ docxml.xpath(ns("//term")).each do |f|
37
+ term1(f)
38
+ end
39
+ end
40
+
41
+ def term1(f)
42
+ lbl = @xrefs.get[f["id"]][:label] or return
43
+ prefix_name(f, "", "#{lbl}#{clausedelim}", "name")
44
+ end
45
+ end
46
+ end