isodoc 1.7.3 → 1.7.6

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/isodoc.gemspec +7 -4
  3. data/lib/isodoc/class_utils.rb +2 -2
  4. data/lib/isodoc/convert.rb +2 -0
  5. data/lib/isodoc/function/blocks_example_note.rb +85 -79
  6. data/lib/isodoc/function/cleanup.rb +181 -175
  7. data/lib/isodoc/function/inline.rb +110 -108
  8. data/lib/isodoc/function/inline_simple.rb +55 -55
  9. data/lib/isodoc/function/lists.rb +75 -71
  10. data/lib/isodoc/function/references.rb +165 -160
  11. data/lib/isodoc/function/section.rb +140 -190
  12. data/lib/isodoc/function/section_titles.rb +82 -0
  13. data/lib/isodoc/function/table.rb +90 -87
  14. data/lib/isodoc/function/terms.rb +58 -56
  15. data/lib/isodoc/function/to_word_html.rb +3 -1
  16. data/lib/isodoc/function/utils.rb +34 -14
  17. data/lib/isodoc/html_function/comments.rb +107 -111
  18. data/lib/isodoc/html_function/footnotes.rb +68 -67
  19. data/lib/isodoc/html_function/html.rb +113 -103
  20. data/lib/isodoc/html_function/mathvariant_to_plain.rb +5 -3
  21. data/lib/isodoc/presentation_function/block.rb +73 -78
  22. data/lib/isodoc/presentation_function/concept.rb +68 -0
  23. data/lib/isodoc/presentation_function/image.rb +112 -0
  24. data/lib/isodoc/presentation_function/inline.rb +6 -39
  25. data/lib/isodoc/presentation_function/math.rb +9 -0
  26. data/lib/isodoc/presentation_function/section.rb +12 -1
  27. data/lib/isodoc/presentation_xml_convert.rb +3 -0
  28. data/lib/isodoc/version.rb +1 -1
  29. data/lib/isodoc/word_function/body.rb +176 -174
  30. data/lib/isodoc/word_function/comments.rb +117 -112
  31. data/lib/isodoc/word_function/footnotes.rb +88 -86
  32. data/lib/isodoc/word_function/inline.rb +42 -67
  33. data/lib/isodoc/word_function/postprocess_cover.rb +121 -110
  34. data/lib/isodoc/xref/xref_gen.rb +153 -150
  35. data/lib/isodoc/xslfo_convert.rb +2 -2
  36. data/lib/isodoc.rb +1 -1
  37. data/spec/assets/odf.svg +1 -4
  38. data/spec/isodoc/blocks_spec.rb +187 -32
  39. data/spec/isodoc/inline_spec.rb +300 -116
  40. data/spec/isodoc/postproc_spec.rb +38 -0
  41. data/spec/isodoc/presentation_xml_spec.rb +144 -0
  42. data/spec/isodoc/section_spec.rb +764 -0
  43. data/spec/isodoc/terms_spec.rb +116 -0
  44. metadata +63 -18
@@ -1,116 +1,119 @@
1
- module IsoDoc::Function
2
- module Table
3
- def table_title_parse(node, out)
4
- name = node.at(ns("./name")) or return
5
- out.p **{ class: "TableTitle", style: "text-align:center;" } do |p|
6
- name&.children&.each { |n| parse(n, p) }
1
+ module IsoDoc
2
+ module Function
3
+ module Table
4
+ def table_title_parse(node, out)
5
+ name = node.at(ns("./name")) or return
6
+ out.p **{ class: "TableTitle", style: "text-align:center;" } do |p|
7
+ name&.children&.each { |n| parse(n, p) }
8
+ end
7
9
  end
8
- end
9
10
 
10
- def thead_parse(node, table)
11
- thead = node.at(ns("./thead"))
12
- if thead
13
- table.thead do |h|
14
- thead.element_children.each_with_index do |n, i|
15
- tr_parse(n, h, i, thead.element_children.size, true)
11
+ def thead_parse(node, table)
12
+ thead = node.at(ns("./thead"))
13
+ if thead
14
+ table.thead do |h|
15
+ thead.element_children.each_with_index do |n, i|
16
+ tr_parse(n, h, i, thead.element_children.size, true)
17
+ end
16
18
  end
17
19
  end
18
20
  end
19
- end
20
21
 
21
- def tbody_parse(node, table)
22
- tbody = node.at(ns("./tbody")) || return
23
- table.tbody do |h|
24
- tbody.element_children.each_with_index do |n, i|
25
- tr_parse(n, h, i, tbody.element_children.size, false)
22
+ def tbody_parse(node, table)
23
+ tbody = node.at(ns("./tbody")) || return
24
+ table.tbody do |h|
25
+ tbody.element_children.each_with_index do |n, i|
26
+ tr_parse(n, h, i, tbody.element_children.size, false)
27
+ end
26
28
  end
27
29
  end
28
- end
29
30
 
30
- def tfoot_parse(node, table)
31
- tfoot = node.at(ns("./tfoot"))
32
- if tfoot
33
- table.tfoot do |h|
34
- tfoot.element_children.each_with_index do |n, i|
35
- tr_parse(n, h, i, tfoot.element_children.size, false)
31
+ def tfoot_parse(node, table)
32
+ tfoot = node.at(ns("./tfoot"))
33
+ if tfoot
34
+ table.tfoot do |h|
35
+ tfoot.element_children.each_with_index do |n, i|
36
+ tr_parse(n, h, i, tfoot.element_children.size, false)
37
+ end
36
38
  end
37
39
  end
38
40
  end
39
- end
40
41
 
41
- def table_attrs(node)
42
- width = node["width"] ? "width:#{node['width']};" : nil
43
- attr_code(
44
- id: node["id"],
45
- class: "MsoISOTable",
46
- style: "border-width:1px;border-spacing:0;#{width}#{keep_style(node)}",
47
- title: node["alt"],
48
- )
49
- end
42
+ def table_attrs(node)
43
+ width = node["width"] ? "width:#{node['width']};" : nil
44
+ attr_code(
45
+ id: node["id"],
46
+ class: "MsoISOTable",
47
+ style: "border-width:1px;border-spacing:0;"\
48
+ "#{width}#{keep_style(node)}",
49
+ title: node["alt"],
50
+ )
51
+ end
50
52
 
51
- def tcaption(node, table)
52
- return unless node["summary"]
53
+ def tcaption(node, table)
54
+ return unless node["summary"]
53
55
 
54
- table.caption do |c|
55
- c.span **{ style: "display:none" } do |s|
56
- s << node["summary"]
56
+ table.caption do |c|
57
+ c.span **{ style: "display:none" } do |s|
58
+ s << node["summary"]
59
+ end
57
60
  end
58
61
  end
59
- end
60
62
 
61
- def colgroup(node, table)
62
- colgroup = node.at(ns("./colgroup")) or return
63
- table.colgroup do |cg|
64
- colgroup.xpath(ns("./col")).each do |c|
65
- cg.col **{ style: "width: #{c['width']};" }
63
+ def colgroup(node, table)
64
+ colgroup = node.at(ns("./colgroup")) or return
65
+ table.colgroup do |cg|
66
+ colgroup.xpath(ns("./col")).each do |c|
67
+ cg.col **{ style: "width: #{c['width']};" }
68
+ end
66
69
  end
67
70
  end
68
- end
69
71
 
70
- def table_parse(node, out)
71
- @in_table = true
72
- table_title_parse(node, out)
73
- out.table **table_attrs(node) do |t|
74
- tcaption(node, t)
75
- colgroup(node, t)
76
- thead_parse(node, t)
77
- tbody_parse(node, t)
78
- tfoot_parse(node, t)
79
- (dl = node.at(ns("./dl"))) && parse(dl, out)
80
- node.xpath(ns("./note")).each { |n| parse(n, out) }
72
+ def table_parse(node, out)
73
+ @in_table = true
74
+ table_title_parse(node, out)
75
+ out.table **table_attrs(node) do |t|
76
+ tcaption(node, t)
77
+ colgroup(node, t)
78
+ thead_parse(node, t)
79
+ tbody_parse(node, t)
80
+ tfoot_parse(node, t)
81
+ (dl = node.at(ns("./dl"))) && parse(dl, out)
82
+ node.xpath(ns("./note")).each { |n| parse(n, out) }
83
+ end
84
+ @in_table = false
85
+ # out.p { |p| p << "&nbsp;" }
81
86
  end
82
- @in_table = false
83
- # out.p { |p| p << "&nbsp;" }
84
- end
85
87
 
86
- SW = "solid windowtext".freeze
88
+ SW = "solid windowtext".freeze
87
89
 
88
- # def make_tr_attr(td, row, totalrows, cols, totalcols, header)
89
- # border-left:#{col.zero? ? "#{SW} 1.5pt;" : "none;"}
90
- # border-right:#{SW} #{col == totalcols && !header ? "1.5" : "1.0"}pt;
90
+ # def make_tr_attr(td, row, totalrows, cols, totalcols, header)
91
+ # border-left:#{col.zero? ? "#{SW} 1.5pt;" : "none;"}
92
+ # border-right:#{SW} #{col == totalcols && !header ? "1.5" : "1.0"}pt;
91
93
 
92
- def make_tr_attr(cell, row, totalrows, header)
93
- style = cell.name == "th" ? "font-weight:bold;" : ""
94
- cell["align"] and style += "text-align:#{cell['align']};"
95
- cell["valign"] and style += "vertical-align:#{cell['valign']};"
96
- rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
97
- style += <<~STYLE
98
- border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
99
- border-bottom:#{SW} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
100
- STYLE
101
- header and scope = (cell["colspan"] ? "colgroup" : "col")
102
- !header and cell.name == "th" and scope =
103
- (cell["rowspan"] ? "rowgroup" : "row")
104
- { rowspan: cell["rowspan"], colspan: cell["colspan"],
105
- style: style.gsub(/\n/, ""), scope: scope }
106
- end
94
+ def make_tr_attr(cell, row, totalrows, header)
95
+ style = cell.name == "th" ? "font-weight:bold;" : ""
96
+ cell["align"] and style += "text-align:#{cell['align']};"
97
+ cell["valign"] and style += "vertical-align:#{cell['valign']};"
98
+ rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
99
+ style += <<~STYLE
100
+ border-top:#{row.zero? ? "#{SW} 1.5pt;" : 'none;'}
101
+ border-bottom:#{SW} #{rowmax == totalrows ? '1.5' : '1.0'}pt;
102
+ STYLE
103
+ header and scope = (cell["colspan"] ? "colgroup" : "col")
104
+ !header && cell.name == "th" and
105
+ scope = (cell["rowspan"] ? "rowgroup" : "row")
106
+ { rowspan: cell["rowspan"], colspan: cell["colspan"],
107
+ style: style.gsub(/\n/, ""), scope: scope }
108
+ end
107
109
 
108
- def tr_parse(node, out, ord, totalrows, header)
109
- out.tr do |r|
110
- node.elements.each do |td|
111
- attrs = make_tr_attr(td, ord, totalrows - 1, header)
112
- r.send td.name, **attr_code(attrs) do |entry|
113
- td.children.each { |n| parse(n, entry) }
110
+ def tr_parse(node, out, ord, totalrows, header)
111
+ out.tr do |r|
112
+ node.elements.each do |td|
113
+ attrs = make_tr_attr(td, ord, totalrows - 1, header)
114
+ r.send td.name, **attr_code(attrs) do |entry|
115
+ td.children.each { |n| parse(n, entry) }
116
+ end
114
117
  end
115
118
  end
116
119
  end
@@ -1,77 +1,79 @@
1
- module IsoDoc::Function
2
- module Terms
3
- def definition_parse(node, out)
4
- node.children.each { |n| parse(n, out) }
5
- end
1
+ module IsoDoc
2
+ module Function
3
+ module Terms
4
+ def definition_parse(node, out)
5
+ node.children.each { |n| parse(n, out) }
6
+ end
6
7
 
7
- def modification_parse(node, out)
8
- out << "[MODIFICATION]"
9
- para = node.at(ns("./p"))
10
- para.children.each { |n| parse(n, out) }
11
- end
8
+ def modification_parse(node, out)
9
+ out << "[MODIFICATION]"
10
+ para = node.at(ns("./p"))
11
+ para.children.each { |n| parse(n, out) }
12
+ end
12
13
 
13
- def deprecated_term_parse(node, out)
14
- out.p **{ class: "DeprecatedTerms", style: "text-align:left;" } do |p|
15
- p << l10n("#{@i18n.deprecated}: ")
16
- node.children.each { |c| parse(c, p) }
14
+ def deprecated_term_parse(node, out)
15
+ out.p **{ class: "DeprecatedTerms", style: "text-align:left;" } do |p|
16
+ p << l10n("#{@i18n.deprecated}: ")
17
+ node.children.each { |c| parse(c, p) }
18
+ end
17
19
  end
18
- end
19
20
 
20
- def admitted_term_parse(node, out)
21
- out.p **{ class: "AltTerms", style: "text-align:left;" } do |p|
22
- node.children.each { |c| parse(c, p) }
21
+ def admitted_term_parse(node, out)
22
+ out.p **{ class: "AltTerms", style: "text-align:left;" } do |p|
23
+ node.children.each { |c| parse(c, p) }
24
+ end
23
25
  end
24
- end
25
26
 
26
- def term_parse(node, out)
27
- out.p **{ class: "Terms", style: "text-align:left;" } do |p|
28
- node.children.each { |c| parse(c, p) }
27
+ def term_parse(node, out)
28
+ out.p **{ class: "Terms", style: "text-align:left;" } do |p|
29
+ node.children.each { |c| parse(c, p) }
30
+ end
29
31
  end
30
- end
31
32
 
32
- def para_then_remainder(first, node, para, div)
33
- if first.name == "p"
34
- first.children.each { |n| parse(n, para) }
35
- node.elements.drop(1).each { |n| parse(n, div) }
36
- else
37
- node.elements.each { |n| parse(n, div) }
33
+ def para_then_remainder(first, node, para, div)
34
+ if first.name == "p"
35
+ first.children.each { |n| parse(n, para) }
36
+ node.elements.drop(1).each { |n| parse(n, div) }
37
+ else
38
+ node.elements.each { |n| parse(n, div) }
39
+ end
38
40
  end
39
- end
40
41
 
41
- def termnote_delim
42
- l10n(": ")
43
- end
42
+ def termnote_delim
43
+ l10n(": ")
44
+ end
44
45
 
45
- def termnote_parse(node, out)
46
- name = node&.at(ns("./name"))&.remove
47
- out.div **note_attrs(node) do |div|
48
- div.p do |p|
49
- if name
50
- name.children.each { |n| parse(n, p) }
51
- p << termnote_delim
46
+ def termnote_parse(node, out)
47
+ name = node&.at(ns("./name"))&.remove
48
+ out.div **note_attrs(node) do |div|
49
+ div.p do |p|
50
+ if name
51
+ name.children.each { |n| parse(n, p) }
52
+ p << termnote_delim
53
+ end
54
+ para_then_remainder(node.first_element_child, node, p, div)
52
55
  end
53
- para_then_remainder(node.first_element_child, node, p, div)
54
56
  end
55
57
  end
56
- end
57
58
 
58
- def termref_parse(node, out)
59
- out.p do |p|
60
- p << "[TERMREF]"
61
- node.children.each { |n| parse(n, p) }
62
- p << "[/TERMREF]"
59
+ def termref_parse(node, out)
60
+ out.p do |p|
61
+ p << "[TERMREF]"
62
+ node.children.each { |n| parse(n, p) }
63
+ p << "[/TERMREF]"
64
+ end
63
65
  end
64
- end
65
66
 
66
- def termdef_parse(node, out)
67
- name = node&.at(ns("./name"))&.remove
68
- out.p **{ class: "TermNum", id: node["id"] } do |p|
69
- name&.children&.each { |n| parse(n, p) }
67
+ def termdef_parse(node, out)
68
+ name = node&.at(ns("./name"))&.remove
69
+ out.p **{ class: "TermNum", id: node["id"] } do |p|
70
+ name&.children&.each { |n| parse(n, p) }
71
+ end
72
+ set_termdomain("")
73
+ node.children.each { |n| parse(n, out) }
70
74
  end
71
- set_termdomain("")
72
- node.children.each { |n| parse(n, out) }
73
- end
74
75
 
75
- def termdocsource_parse(_node, _out); end
76
+ def termdocsource_parse(_node, _out); end
77
+ end
76
78
  end
77
79
  end
@@ -21,7 +21,8 @@ module IsoDoc
21
21
  filename = filepath.sub_ext("").sub(/\.presentation$/, "").to_s
22
22
  dir = init_dir(filename, debug)
23
23
  @filename = filename
24
- @localdir = "#{filepath.parent}/"
24
+ @localdir = @baseassetpath || filepath.parent.to_s
25
+ @localdir += "/"
25
26
  @sourcedir = @localdir
26
27
  @sourcefilename and
27
28
  @sourcedir = "#{Pathname.new(@sourcefilename).parent}/"
@@ -233,6 +234,7 @@ module IsoDoc
233
234
  when "option" then option_parse(node, out)
234
235
  when "textarea" then textarea_parse(node, out)
235
236
  when "toc" then toc_parse(node, out)
237
+ when "variant-title" then variant_title(node, out)
236
238
  else error_parse(node, out)
237
239
  end
238
240
  end
@@ -37,14 +37,14 @@ module IsoDoc
37
37
  end
38
38
 
39
39
  def attr_code(attributes)
40
- attributes = attributes.reject { |_, val| val.nil? }.map
40
+ attributes = attributes.compact.map
41
41
  attributes.map do |k, v|
42
42
  [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
43
43
  end.to_h
44
44
  end
45
45
 
46
46
  DOCTYPE_HDR = "<!DOCTYPE html SYSTEM "\
47
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
47
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
48
48
 
49
49
  def to_xhtml(xml)
50
50
  xml = to_xhtml_prep(xml)
@@ -55,7 +55,7 @@ module IsoDoc
55
55
  f.write xml
56
56
  end
57
57
  abort "Malformed Output XML for #{@format}: #{e} "\
58
- "(see #{@filename}.#{@format}.err)"
58
+ "(see #{@filename}.#{@format}.err)"
59
59
  end
60
60
  end
61
61
 
@@ -67,7 +67,7 @@ module IsoDoc
67
67
  HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal)
68
68
  else t
69
69
  end
70
- end.join("")
70
+ end.join
71
71
  end
72
72
 
73
73
  def to_xhtml_fragment(xml)
@@ -148,18 +148,12 @@ module IsoDoc
148
148
  elem.name == "span" && /mso-bookmark/.match(elem["style"])
149
149
  end
150
150
 
151
- =begin
152
- def liquid(doc)
153
- self.class.liquid(doc)
154
- end
155
- =end
156
-
157
151
  def liquid(doc)
158
152
  # unescape HTML escapes in doc
159
153
  doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
160
154
  a[2] = a[2].gsub(/&lt;/, "<").gsub(/&gt;/, ">") if a.size > 2
161
- a.join("")
162
- end.join("")
155
+ a.join
156
+ end.join
163
157
  Liquid::Template.parse(doc)
164
158
  end
165
159
 
@@ -181,8 +175,9 @@ module IsoDoc
181
175
  end
182
176
 
183
177
  def save_dataimage(uri, _relative_dir = true)
184
- %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
185
- imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
178
+ %r{^data:(?<imgclass>image|application)/(?<imgtype>[^;]+);(charset=[^;]+;)?base64,(?<imgdata>.+)$} =~ uri
179
+ imgtype = "emf" if emf?("#{imgclass}/#{imgtype}")
180
+ imgtype = imgtype.sub(/\+[a-z0-9]+$/, "") # svg+xml
186
181
  imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
187
182
  Tempfile.open(["image", ".#{imgtype}"]) do |f|
188
183
  f.binmode
@@ -206,6 +201,31 @@ module IsoDoc
206
201
  !node.ancestors("example, requirement, recommendation, permission, "\
207
202
  "note, table, figure, sourcecode").empty?
208
203
  end
204
+
205
+ def emf?(type)
206
+ %w(application/emf application/x-emf image/x-emf image/x-mgx-emf
207
+ application/x-msmetafile image/x-xbitmap).include? type
208
+ end
209
+
210
+ def cleanup_entities(text)
211
+ c = HTMLEntities.new
212
+ text.split(/([<>])/).each_slice(4).map do |a|
213
+ a[0] = c.encode(c.decode(a[0]), :hexadecimal)
214
+ a[1] = c.encode(c.decode(a[1]), :hexadecimal)
215
+ a
216
+ end.join
217
+ end
218
+
219
+ def external_path(path)
220
+ win = !!((RUBY_PLATFORM =~ /(win|w)(32|64)$/) ||
221
+ (RUBY_PLATFORM =~ /mswin|mingw/))
222
+ if win
223
+ path.gsub!(%{/}, "\\")
224
+ path[/\s/] ? "\"#{path}\"" : path
225
+ else
226
+ path
227
+ end
228
+ end
209
229
  end
210
230
  end
211
231
  end