isodoc 1.0.27 → 1.1.2

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +4 -8
  3. data/.github/workflows/ubuntu.yml +18 -16
  4. data/.github/workflows/windows.yml +4 -8
  5. data/Rakefile +3 -1
  6. data/isodoc.gemspec +2 -2
  7. data/lib/isodoc.rb +2 -0
  8. data/lib/isodoc/base_style/metanorma_word.scss +0 -1
  9. data/lib/isodoc/base_style/reset.scss +3 -3
  10. data/lib/isodoc/common.rb +0 -4
  11. data/lib/isodoc/convert.rb +121 -58
  12. data/lib/isodoc/function/blocks.rb +42 -53
  13. data/lib/isodoc/function/blocks_example_note.rb +108 -0
  14. data/lib/isodoc/function/cleanup.rb +8 -4
  15. data/lib/isodoc/function/i18n.rb +1 -0
  16. data/lib/isodoc/function/inline.rb +70 -90
  17. data/lib/isodoc/function/inline_simple.rb +72 -0
  18. data/lib/isodoc/function/lists.rb +12 -6
  19. data/lib/isodoc/function/references.rb +33 -38
  20. data/lib/isodoc/function/reqt.rb +14 -5
  21. data/lib/isodoc/function/section.rb +8 -11
  22. data/lib/isodoc/function/table.rb +4 -4
  23. data/lib/isodoc/function/terms.rb +3 -3
  24. data/lib/isodoc/function/to_word_html.rb +21 -13
  25. data/lib/isodoc/function/utils.rb +57 -50
  26. data/lib/isodoc/gem_tasks.rb +104 -0
  27. data/lib/isodoc/headlesshtml_convert.rb +7 -6
  28. data/lib/isodoc/html_convert.rb +2 -1
  29. data/lib/isodoc/html_function/footnotes.rb +1 -1
  30. data/lib/isodoc/html_function/html.rb +13 -1
  31. data/lib/isodoc/html_function/postprocess.rb +4 -4
  32. data/lib/isodoc/metadata.rb +74 -62
  33. data/lib/isodoc/pdf_convert.rb +8 -6
  34. data/lib/isodoc/presentation_xml_convert.rb +29 -0
  35. data/lib/isodoc/sassc_importer.rb +11 -0
  36. data/lib/isodoc/version.rb +1 -1
  37. data/lib/isodoc/word_convert.rb +2 -1
  38. data/lib/isodoc/word_function/body.rb +14 -48
  39. data/lib/isodoc/word_function/footnotes.rb +1 -1
  40. data/lib/isodoc/word_function/inline.rb +75 -0
  41. data/lib/isodoc/word_function/postprocess.rb +1 -0
  42. data/lib/isodoc/word_function/table.rb +3 -3
  43. data/lib/isodoc/xref.rb +59 -0
  44. data/lib/isodoc/{function → xref}/xref_anchor.rb +10 -21
  45. data/lib/isodoc/xref/xref_counter.rb +74 -0
  46. data/lib/isodoc/{function → xref}/xref_gen.rb +9 -22
  47. data/lib/isodoc/{function → xref}/xref_gen_seq.rb +41 -32
  48. data/lib/isodoc/{function → xref}/xref_sect_gen.rb +33 -23
  49. data/lib/isodoc/xslfo_convert.rb +16 -4
  50. data/spec/assets/{html.css → html.scss} +0 -0
  51. data/spec/assets/i18n.yaml +4 -1
  52. data/spec/assets/odf.emf +0 -0
  53. data/spec/assets/odf.svg +4 -0
  54. data/spec/assets/odf1.svg +4 -0
  55. data/spec/isodoc/blocks_spec.rb +219 -47
  56. data/spec/isodoc/cleanup_spec.rb +135 -6
  57. data/spec/isodoc/footnotes_spec.rb +22 -7
  58. data/spec/isodoc/inline_spec.rb +262 -2
  59. data/spec/isodoc/lists_spec.rb +8 -8
  60. data/spec/isodoc/metadata_spec.rb +110 -3
  61. data/spec/isodoc/postproc_spec.rb +1321 -1351
  62. data/spec/isodoc/presentation_xml_spec.rb +20 -0
  63. data/spec/isodoc/ref_spec.rb +119 -50
  64. data/spec/isodoc/section_spec.rb +84 -18
  65. data/spec/isodoc/table_spec.rb +6 -6
  66. data/spec/isodoc/terms_spec.rb +7 -7
  67. data/spec/isodoc/xref_spec.rb +165 -45
  68. metadata +36 -27
  69. data/lib/isodoc/function/blocks_example.rb +0 -53
  70. data/lib/isodoc/function/xref_counter.rb +0 -50
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module IsoDoc::Function
2
4
  module Utils
3
5
  def date_range(date)
@@ -9,50 +11,50 @@ module IsoDoc::Function
9
11
  end
10
12
 
11
13
  def insert_tab(out, n)
12
- [1..n].each { out << "&nbsp; " }
14
+ [1..n].each { out << '&nbsp; ' }
13
15
  end
14
16
 
15
17
  # add namespaces for Word fragments
16
- NOKOHEAD = <<~HERE.freeze
17
- <!DOCTYPE html SYSTEM
18
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
19
- <html xmlns="http://www.w3.org/1999/xhtml">
20
- <head> <title></title> <meta charset="UTF-8" /> </head>
21
- <body> </body> </html>
18
+ NOKOHEAD = <<~HERE
19
+ <!DOCTYPE html SYSTEM
20
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
21
+ <html xmlns="http://www.w3.org/1999/xhtml">
22
+ <head> <title></title> <meta charset="UTF-8" /> </head>
23
+ <body> </body> </html>
22
24
  HERE
23
25
 
24
26
  # block for processing XML document fragments as XHTML,
25
27
  # to allow for HTMLentities
26
28
  def noko(&block)
27
29
  doc = ::Nokogiri::XML.parse(NOKOHEAD)
28
- fragment = doc.fragment("")
30
+ fragment = doc.fragment('')
29
31
  ::Nokogiri::XML::Builder.with fragment, &block
30
- fragment.to_xml(encoding: "US-ASCII").lines.map do |l|
31
- l.gsub(/\s*\n/, "")
32
+ fragment.to_xml(encoding: 'US-ASCII').lines.map do |l|
33
+ l.gsub(/\s*\n/, '')
32
34
  end
33
35
  end
34
36
 
35
37
  def attr_code(attributes)
36
38
  attributes = attributes.reject { |_, val| val.nil? }.map
37
39
  attributes.map do |k, v|
38
- [k, (v.is_a? String) ? HTMLEntities.new.decode(v) : v]
40
+ [k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
39
41
  end.to_h
40
42
  end
41
43
 
42
44
  DOCTYPE_HDR = '<!DOCTYPE html SYSTEM '\
43
- '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
45
+ '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
44
46
 
45
47
  def to_xhtml(xml)
46
- xml.gsub!(/<\?xml[^>]*>/, "")
47
- /<!DOCTYPE /.match xml or xml = DOCTYPE_HDR + xml
48
+ xml.gsub!(/<\?xml[^>]*>/, '')
49
+ /<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
48
50
  xml = xml.split(/(\&[^ \r\n\t#;]+;)/).map do |t|
49
- /^(\&[^ \t\r\n#;]+;)/.match(t) ?
51
+ /^(\&[^ \t\r\n#;]+;)/.match?(t) ?
50
52
  HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
51
- end.join("")
53
+ end.join('')
52
54
  begin
53
- Nokogiri::XML.parse(xml) { |config| config.strict }
55
+ Nokogiri::XML.parse(xml, &:strict)
54
56
  rescue Nokogiri::XML::SyntaxError => e
55
- File.open("#{@filename}.#{@format}.err", "w:UTF-8") { |f| f.write xml }
57
+ File.open("#{@filename}.#{@format}.err", 'w:UTF-8') { |f| f.write xml }
56
58
  abort "Malformed Output XML for #{@format}: #{e} (see #{@filename}.#{@format}.err)"
57
59
  end
58
60
  end
@@ -64,7 +66,7 @@ module IsoDoc::Function
64
66
  end
65
67
 
66
68
  def from_xhtml(xml)
67
- xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, "")
69
+ xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, '')
68
70
  end
69
71
 
70
72
  CLAUSE_ANCESTOR =
@@ -72,7 +74,7 @@ module IsoDoc::Function
72
74
  "local-name() = 'acknowledgements' or local-name() = 'term' or "\
73
75
  "local-name() = 'appendix' or local-name() = 'foreword' or "\
74
76
  "local-name() = 'introduction' or local-name() = 'terms' or "\
75
- "local-name() = 'clause' or local-name() = 'references']/@id".freeze
77
+ "local-name() = 'clause' or local-name() = 'references']/@id"
76
78
 
77
79
  def get_clause_id(node)
78
80
  clause = node.xpath(CLAUSE_ANCESTOR)
@@ -86,7 +88,7 @@ module IsoDoc::Function
86
88
  "local-name() = 'acknowledgements' or local-name() = 'term' or "\
87
89
  "local-name() = 'clause' or local-name() = 'references' or "\
88
90
  "local-name() = 'figure' or local-name() = 'formula' or "\
89
- "local-name() = 'table' or local-name() = 'example']/@id".freeze
91
+ "local-name() = 'table' or local-name() = 'example']/@id"
90
92
 
91
93
  def get_note_container_id(node)
92
94
  container = node.xpath(NOTE_CONTAINER_ANCESTOR)
@@ -94,7 +96,7 @@ module IsoDoc::Function
94
96
  end
95
97
 
96
98
  def sentence_join(array)
97
- return "" if array.nil? || array.empty?
99
+ return '' if array.nil? || array.empty?
98
100
  if array.length == 1 then array[0]
99
101
  else
100
102
  IsoDoc::Function::I18n::l10n("#{array[0..-2].join(', ')} "\
@@ -105,25 +107,25 @@ module IsoDoc::Function
105
107
 
106
108
  # avoid `; avoid {{ (Liquid Templates); avoid [[ (Javascript)
107
109
  def extract_delims(text)
108
- @openmathdelim = "(#("
109
- @closemathdelim = ")#)"
110
+ @openmathdelim = '(#('
111
+ @closemathdelim = ')#)'
110
112
  while text.include?(@openmathdelim) || text.include?(@closemathdelim)
111
- @openmathdelim += "("
112
- @closemathdelim += ")"
113
+ @openmathdelim += '('
114
+ @closemathdelim += ')'
113
115
  end
114
116
  [@openmathdelim, @closemathdelim]
115
117
  end
116
118
 
117
119
  def header_strip(h)
118
- h = h.to_s.gsub(%r{<br\s*/>}, " ").gsub(/<\/?h[123456][^>]*>/, "").
119
- gsub(/<\/?b[^>]*>/, "")
120
+ h = h.to_s.gsub(%r{<br\s*/>}, ' ').gsub(/<\/?h[123456][^>]*>/, '')
121
+ .gsub(/<\/?b[^>]*>/, '')
120
122
  h1 = to_xhtml_fragment(h.dup)
121
123
  h1.traverse do |x|
122
- x.replace(" ") if x.name == "span" && /mso-tab-count/.match(x["style"])
123
- x.remove if x.name == "span" && x["class"] == "MsoCommentReference"
124
- x.remove if x.name == "a" && x["epub:type"] == "footnote"
125
- x.remove if x.name == "span" && /mso-bookmark/.match(x["style"])
126
- x.replace(x.children) if x.name == "a"
124
+ x.replace(' ') if x.name == 'span' && /mso-tab-count/.match(x['style'])
125
+ x.remove if x.name == 'span' && x['class'] == 'MsoCommentReference'
126
+ x.remove if x.name == 'a' && x['class'] == 'FootnoteRef'
127
+ x.remove if x.name == 'span' && /mso-bookmark/.match(x['style'])
128
+ x.replace(x.children) if x.name == 'a'
127
129
  end
128
130
  from_xhtml(h1)
129
131
  end
@@ -135,9 +137,9 @@ module IsoDoc::Function
135
137
  def liquid(doc)
136
138
  # unescape HTML escapes in doc
137
139
  doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
138
- a[2] = a[2].gsub(/\&lt;/, "<").gsub(/\&gt;/, ">") if a.size > 2
139
- a.join("")
140
- end.join("")
140
+ a[2] = a[2].gsub(/\&lt;/, '<').gsub(/\&gt;/, '>') if a.size > 2
141
+ a.join('')
142
+ end.join('')
141
143
  Liquid::Template.parse(doc)
142
144
  end
143
145
 
@@ -147,36 +149,41 @@ module IsoDoc::Function
147
149
  end
148
150
 
149
151
  def populate_template(docxml, _format = nil)
150
- meta = @meta.get.merge(@labels || {})
152
+ meta = @meta
153
+ .get
154
+ .merge(@labels || {})
155
+ .merge(@meta.labels || {})
156
+ .merge(@meta.fonts_options || {})
151
157
  template = liquid(docxml)
152
- template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h).
153
- gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
158
+ template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
159
+ .gsub('&lt;', '&#x3c;').gsub('&gt;', '&#x3e;').gsub('&amp;', '&#x26;')
154
160
  end
155
161
 
156
- def save_dataimage(uri, relative_dir = true)
162
+ def save_dataimage(uri, _relative_dir = true)
157
163
  %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
158
- imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
159
- Tempfile.open(["image", ".#{imgtype}"]) do |f|
164
+ imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
165
+ imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
166
+ Tempfile.open(['image', ".#{imgtype}"]) do |f|
160
167
  f.binmode
161
168
  f.write(Base64.strict_decode64(imgdata))
162
- @tempfile_cache << f #persist to the end
169
+ @tempfile_cache << f # persist to the end
163
170
  f.path
164
171
  end
165
172
  end
166
173
 
167
174
  def image_localfile(i)
168
- if /^data:image/.match i["src"]
169
- save_dataimage(i["src"], false)
170
- elsif %r{^([A-Z]:)?/}.match i["src"]
171
- i["src"]
175
+ if /^data:image/.match? i['src']
176
+ save_dataimage(i['src'], false)
177
+ elsif %r{^([A-Z]:)?/}.match? i['src']
178
+ i['src']
172
179
  else
173
- File.join(@localdir, i["src"])
180
+ File.join(@localdir, i['src'])
174
181
  end
175
182
  end
176
183
 
177
184
  def labelled_ancestor(node)
178
- return !node.ancestors("example, requirement, recommendation, permission, "\
179
- "table, figure, sourcecode").empty?
185
+ !node.ancestors('example, requirement, recommendation, permission, '\
186
+ 'table, figure, sourcecode').empty?
180
187
  end
181
188
  end
182
189
  end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sassc'
4
+ require 'isodoc/sassc_importer'
5
+ require 'rake/clean'
6
+
7
+ module IsoDoc
8
+ module GemTasks
9
+ extend Rake::DSL if defined? Rake::DSL
10
+
11
+ module_function
12
+
13
+ def install
14
+ rule '.css' => [proc { |tn| tn.sub(/\.css$/, '.scss') }] do |current_task|
15
+ begin
16
+ puts(current_task)
17
+ compile_scss_task(current_task)
18
+ rescue StandardError => e
19
+ puts(e.message)
20
+ puts("skiping #{current_task}")
21
+ end
22
+ end
23
+
24
+ scss_files = Rake::FileList['lib/**/*.scss']
25
+ source_files = scss_files.ext('.css')
26
+
27
+ task :comment_out_liquid do
28
+ process_css_files(scss_files) do |file_name|
29
+ comment_out_liquid(File.read(file_name, encoding: 'UTF-8'))
30
+ end
31
+ end
32
+
33
+ task build_scss: [:comment_out_liquid].push(*source_files) do
34
+ process_css_files(scss_files) do |file_name|
35
+ uncomment_out_liquid(File.read(file_name, encoding: 'UTF-8'))
36
+ end
37
+ puts('Built scss!')
38
+ end
39
+
40
+ Rake::Task['build'].enhance [:build_scss] do
41
+ Rake::Task[:clean].invoke
42
+ end
43
+ end
44
+
45
+ def process_css_files(scss_files)
46
+ scss_files.each do |file_name|
47
+ result = yield(file_name)
48
+ File.open(file_name, 'w', encoding: 'UTF-8') do |file|
49
+ file.puts(result)
50
+ end
51
+ end
52
+ end
53
+
54
+ def comment_out_liquid(text)
55
+ text.split("\n").map do |line|
56
+ if line.match?(/{({|%).+(}|%)}/)
57
+ "/* LIQUID_COMMENT#{line}LIQUID_COMMENT */"
58
+ else
59
+ line
60
+ end
61
+ end
62
+ .join("\n")
63
+ end
64
+
65
+ def uncomment_out_liquid(text)
66
+ text
67
+ .gsub('/* LIQUID_COMMENT', '')
68
+ .gsub('LIQUID_COMMENT */', '')
69
+ .gsub('"{{', '{{').gsub('}}"', '}}')
70
+ end
71
+
72
+ def fonts_placeholder
73
+ <<~TEXT
74
+ $bodyfont: '{{bodyfont}}';
75
+ $headerfont: '{{headerfont}}';
76
+ $monospacefont: '{{monospacefont}}';
77
+ TEXT
78
+ end
79
+
80
+ def compile_scss(filename)
81
+ require 'sassc'
82
+ [File.join(Gem.loaded_specs['isodoc'].full_gem_path, 'lib', 'isodoc'),
83
+ File.dirname(filename)].each do |name|
84
+ SassC.load_paths << name
85
+ end
86
+ sheet_content = File.read(filename, encoding: 'UTF-8')
87
+ SassC::Engine.new(fonts_placeholder + sheet_content,
88
+ syntax: :scss,
89
+ importer: SasscImporter)
90
+ .render
91
+ end
92
+
93
+ def compile_scss_task(current_task)
94
+ filename = current_task.source
95
+ basename = File.basename(filename, '.*')
96
+ compiled_path = File.join(File.dirname(filename), "#{basename}.css")
97
+ content = uncomment_out_liquid(compile_scss(filename))
98
+ File.open(compiled_path, 'w:UTF-8') do |f|
99
+ f.write(content)
100
+ end
101
+ CLEAN << compiled_path
102
+ end
103
+ end
104
+ end
@@ -16,18 +16,19 @@ module IsoDoc
16
16
 
17
17
  def initialize(options)
18
18
  @format = :html
19
+ @suffix = "headless.html"
19
20
  super
20
21
  end
21
22
 
22
- def convert(filename, file = nil, debug = false)
23
- file = File.read(filename, encoding: "utf-8") if file.nil?
23
+ def convert(input_filename, file = nil, debug = false, output_filename = nil)
24
+ file = File.read(input_filename, encoding: "utf-8") if file.nil?
24
25
  @openmathdelim, @closemathdelim = extract_delims(file)
25
- docxml, outname_html, dir = convert_init(file, filename, debug)
26
- result = convert1(docxml, outname_html, dir)
26
+ docxml, filename, dir = convert_init(file, input_filename, debug)
27
+ result = convert1(docxml, filename, dir)
27
28
  return result if debug
28
- postprocess(result, filename + ".tmp", dir)
29
+ postprocess(result, filename + ".tmp.html", dir)
29
30
  FileUtils.rm_rf dir
30
- strip_head(filename + ".tmp.html", outname_html + ".headless.html")
31
+ strip_head(filename + ".tmp.html", output_filename || "#{filename}.#{@suffix}")
31
32
  FileUtils.rm_rf ["#{filename}.tmp.html", tmpimagedir]
32
33
  end
33
34
 
@@ -16,10 +16,11 @@ module IsoDoc
16
16
 
17
17
  def initialize(options)
18
18
  @format = :html
19
+ @suffix = "html"
19
20
  super
20
21
  end
21
22
 
22
- def convert(filename, file = nil, debug = false)
23
+ def convert(filename, file = nil, debug = false, output_filename = nil)
23
24
  ret = super
24
25
  Dir.exists?(tmpimagedir) and Dir["#{tmpimagedir}/*"].empty? and
25
26
  FileUtils.rm_r tmpimagedir
@@ -65,7 +65,7 @@ module IsoDoc::HtmlFunction
65
65
  return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
66
66
  !node.ancestors.map {|m| m.name }.include?("name")
67
67
  fn = node["reference"] || UUIDTools::UUID.random_create.to_s
68
- attrs = { "epub:type": "footnote", rel: "footnote", href: "#fn:#{fn}" }
68
+ attrs = { class: "FootnoteRef", href: "#fn:#{fn}" }
69
69
  out.a **attrs do |a|
70
70
  a.sup { |sup| sup << fn }
71
71
  end
@@ -3,6 +3,18 @@ require "base64"
3
3
 
4
4
  module IsoDoc::HtmlFunction
5
5
  module Html
6
+ def convert1(docxml, filename, dir)
7
+ @xrefs.parse docxml
8
+ noko do |xml|
9
+ xml.html **{ lang: "#{@lang}" } do |html|
10
+ info docxml, nil
11
+ populate_css()
12
+ html.head { |head| define_head head, filename, dir }
13
+ make_body(html, docxml)
14
+ end
15
+ end.join("\n")
16
+ end
17
+
6
18
  def make_body1(body, _docxml)
7
19
  body.div **{ class: "title-section" } do |div1|
8
20
  div1.p { |p| p << "&nbsp;" } # placeholder
@@ -90,7 +102,7 @@ module IsoDoc::HtmlFunction
90
102
  def sourcecode_parse(node, out)
91
103
  name = node.at(ns("./name"))
92
104
  class1 = "prettyprint #{sourcecodelang(node&.at(ns('./@lang'))&.value)}"
93
- out.pre **attr_code(id: node["id"], class: class1) do |div|
105
+ out.pre **sourcecode_attrs(node).merge(class: class1) do |div|
94
106
  @sourcecode = true
95
107
  node.children.each { |n| parse(n, div) unless n.name == "name" }
96
108
  @sourcecode = false
@@ -18,7 +18,7 @@ module IsoDoc::HtmlFunction
18
18
  #result = populate_template(result, :html)
19
19
  result = from_xhtml(move_images(to_xhtml(result)))
20
20
  result = html5(script_cdata(inject_script(result)))
21
- File.open("#{filename}.html", "w:UTF-8") { |f| f.write(result) }
21
+ File.open(filename, "w:UTF-8") { |f| f.write(result) }
22
22
  end
23
23
 
24
24
  def html5(doc)
@@ -179,7 +179,7 @@ module IsoDoc::HtmlFunction
179
179
  def html_footnote_filter(docxml)
180
180
  seen = {}
181
181
  i = 1
182
- docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
182
+ docxml.xpath('//a[@class = "FootnoteRef"]').each do |x|
183
183
  fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
184
184
  i, seen = update_footnote_filter(fn, x, i, seen)
185
185
  end
@@ -188,7 +188,7 @@ module IsoDoc::HtmlFunction
188
188
 
189
189
  def footnote_backlinks(docxml)
190
190
  seen = {}
191
- docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
191
+ docxml.xpath('//a[@class = "FootnoteRef"]').each_with_index do |x, i|
192
192
  seen[x["href"]] and next or seen[x["href"]] = true
193
193
  fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
194
194
  xdup = x.dup
@@ -201,7 +201,7 @@ module IsoDoc::HtmlFunction
201
201
  end
202
202
 
203
203
  def footnote_format(docxml)
204
- docxml.xpath("//a[@epub:type = 'footnote']/sup").each do |x|
204
+ docxml.xpath("//a[@class = 'FootnoteRef']/sup").each do |x|
205
205
  footnote_reference_format(x)
206
206
  end
207
207
  docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
@@ -1,10 +1,15 @@
1
- require_relative "./metadata_date"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './metadata_date'
2
4
 
3
5
  module IsoDoc
4
6
  class Metadata
5
7
  DATETYPES = %w{published accessed created implemented obsoleted confirmed
6
- updated issued received transmitted copied unchanged circulated vote-started
7
- vote-ended}.freeze
8
+ updated issued received transmitted copied unchanged
9
+ circulated vote-started
10
+ vote-ended}.freeze
11
+
12
+ attr_accessor :fonts_options
8
13
 
9
14
  def ns(xpath)
10
15
  Common::ns(xpath)
@@ -14,13 +19,14 @@ module IsoDoc
14
19
  IsoDoc::Function::I18n::l10n(a, b, c)
15
20
  end
16
21
 
17
- def initialize(lang, script, labels)
22
+ def initialize(lang, script, labels, fonts_options = {})
18
23
  @metadata = {}
19
- DATETYPES.each { |w| @metadata["#{w.gsub(/-/, "_")}date".to_sym] = "XXX" }
24
+ DATETYPES.each { |w| @metadata["#{w.gsub(/-/, '_')}date".to_sym] = 'XXX' }
20
25
  @lang = lang
21
26
  @script = script
22
27
  @c = HTMLEntities.new
23
28
  @labels = labels
29
+ @fonts_options = fonts_options
24
30
  end
25
31
 
26
32
  def get
@@ -36,26 +42,26 @@ module IsoDoc
36
42
  end
37
43
 
38
44
  def extract_person_names(authors)
39
- authors.inject([]) do |ret, a|
40
- if a.at(ns("./name/completename"))
41
- ret << a.at(ns("./name/completename")).text
45
+ authors.reduce([]) do |ret, a|
46
+ if a.at(ns('./name/completename'))
47
+ ret << a.at(ns('./name/completename')).text
42
48
  else
43
49
  fn = []
44
- forenames = a.xpath(ns("./name/forename"))
50
+ forenames = a.xpath(ns('./name/forename'))
45
51
  forenames.each { |f| fn << f.text }
46
- surname = a&.at(ns("./name/surname"))&.text
47
- ret << fn.join(" ") + " " + surname
52
+ surname = a&.at(ns('./name/surname'))&.text
53
+ ret << fn.join(' ') + ' ' + surname
48
54
  end
49
55
  end
50
56
  end
51
57
 
52
58
  def extract_person_affiliations(authors)
53
- authors.inject([]) do |m, a|
54
- name = a&.at(ns("./affiliation/organization/name"))&.text
55
- location = a&.at(ns("./affiliation/organization/address/"\
56
- "formattedAddress"))&.text
57
- m << ((!name.nil? && !location.nil?) ? "#{name}, #{location}" :
58
- (name || location || ""))
59
+ authors.reduce([]) do |m, a|
60
+ name = a&.at(ns('./affiliation/organization/name'))&.text
61
+ location = a&.at(ns('./affiliation/organization/address/'\
62
+ 'formattedAddress'))&.text
63
+ m << (!name.nil? && !location.nil? ? "#{name}, #{location}" :
64
+ (name || location || ''))
59
65
  m
60
66
  end
61
67
  end
@@ -84,99 +90,99 @@ module IsoDoc
84
90
  end
85
91
 
86
92
  def bibdate(isoxml, _out)
87
- isoxml.xpath(ns("//bibdata/date")).each do |d|
88
- set("#{d['type'].gsub(/-/, "_")}date".to_sym, Common::date_range(d))
93
+ isoxml.xpath(ns('//bibdata/date')).each do |d|
94
+ set("#{d['type'].gsub(/-/, '_')}date".to_sym, Common::date_range(d))
89
95
  end
90
96
  end
91
97
 
92
98
  def doctype(isoxml, _out)
93
- b = isoxml&.at(ns("//bibdata/ext/doctype"))&.text || return
94
- t = b.split(/[- ]/).map{ |w| w.capitalize }.join(" ")
99
+ b = isoxml&.at(ns('//bibdata/ext/doctype'))&.text || return
100
+ t = b.split(/[- ]/).map(&:capitalize).join(' ')
95
101
  set(:doctype, t)
96
102
  end
97
103
 
98
104
  def iso?(org)
99
- name = org&.at(ns("./name"))&.text
100
- abbrev = org&.at(ns("./abbreviation"))&.text
101
- (abbrev == "ISO" ||
102
- name == "International Organization for Standardization" )
105
+ name = org&.at(ns('./name'))&.text
106
+ abbrev = org&.at(ns('./abbreviation'))&.text
107
+ (abbrev == 'ISO' ||
108
+ name == 'International Organization for Standardization')
103
109
  end
104
110
 
105
111
  def agency(xml)
106
- agency = ""
112
+ agency = ''
107
113
  publisher = []
108
114
  xml.xpath(ns("//bibdata/contributor[xmlns:role/@type = 'publisher']/"\
109
- "organization")).each do |org|
110
- name = org&.at(ns("./name"))&.text
111
- agency1 = org&.at(ns("./abbreviation"))&.text || name
115
+ 'organization')).each do |org|
116
+ name = org&.at(ns('./name'))&.text
117
+ agency1 = org&.at(ns('./abbreviation'))&.text || name
112
118
  publisher << name if name
113
- agency = iso?(org) ? "ISO/#{agency}" : "#{agency}#{agency1}/"
119
+ agency = iso?(org) ? "ISO/#{agency}" : "#{agency}#{agency1}/"
114
120
  end
115
- set(:agency, agency.sub(%r{/$}, ""))
116
- set(:publisher, multiple_and(publisher, @labels["and"]))
121
+ set(:agency, agency.sub(%r{/$}, ''))
122
+ set(:publisher, multiple_and(publisher, @labels['and']))
117
123
  end
118
124
 
119
125
  def multiple_and(names, andword)
120
- return "" if names.length == 0
126
+ return '' if names.empty?
121
127
  return names[0] if names.length == 1
122
- names.length == 2 and
123
- return l10n("#{names[0]} #{andword} #{names[1]}", @lang, @script)
124
- l10n(names[0..-2].join(", ") + " #{andword} #{names[-1]}", @lang, @script)
128
+ (names.length == 2) &&
129
+ (return l10n("#{names[0]} #{andword} #{names[1]}", @lang, @script))
130
+ l10n(names[0..-2].join(', ') + " #{andword} #{names[-1]}", @lang, @script)
125
131
  end
126
132
 
127
133
  def docstatus(isoxml, _out)
128
- docstatus = isoxml.at(ns("//bibdata/status/stage"))
134
+ docstatus = isoxml.at(ns('//bibdata/status/stage'))
129
135
  set(:unpublished, true)
130
136
  if docstatus
131
137
  set(:stage, status_print(docstatus.text))
132
- i = isoxml&.at(ns("//bibdata/status/substage"))&.text and
138
+ (i = isoxml&.at(ns('//bibdata/status/substage'))&.text) &&
133
139
  set(:substage, i)
134
- i = isoxml&.at(ns("//bibdata/status/iteration"))&.text and
140
+ (i = isoxml&.at(ns('//bibdata/status/iteration'))&.text) &&
135
141
  set(:iteration, i)
136
142
  set(:unpublished, unpublished(docstatus.text))
137
- unpublished(docstatus.text) and
143
+ unpublished(docstatus.text) &&
138
144
  set(:stageabbr, stage_abbr(docstatus.text))
139
145
  end
140
146
  end
141
147
 
142
148
  def stage_abbr(docstatus)
143
- status_print(docstatus).split(/ /).
144
- map { |s| s[0].upcase }.join("")
149
+ status_print(docstatus).split(/ /)
150
+ .map { |s| s[0].upcase }.join('')
145
151
  end
146
152
 
147
153
  def unpublished(status)
148
- !(status.downcase == "published")
154
+ !status.casecmp('published').zero?
149
155
  end
150
156
 
151
157
  def status_print(status)
152
- status.split(/-/).map{ |w| w.capitalize }.join(" ")
158
+ status.split(/-/).map(&:capitalize).join(' ')
153
159
  end
154
160
 
155
161
  def docid(isoxml, _out)
156
- dn = isoxml.at(ns("//bibdata/docidentifier"))
162
+ dn = isoxml.at(ns('//bibdata/docidentifier'))
157
163
  set(:docnumber, dn&.text)
158
164
  end
159
165
 
160
166
  def docnumeric(isoxml, _out)
161
- dn = isoxml.at(ns("//bibdata/docnumber"))
167
+ dn = isoxml.at(ns('//bibdata/docnumber'))
162
168
  set(:docnumeric, dn&.text)
163
169
  end
164
170
 
165
171
  def draftinfo(draft, revdate)
166
- draftinfo = ""
172
+ draftinfo = ''
167
173
  if draft
168
- draftinfo = " (#{@labels["draft_label"]} #{draft}"
174
+ draftinfo = " (#{@labels['draft_label']} #{draft}"
169
175
  draftinfo += ", #{revdate}" if revdate
170
- draftinfo += ")"
176
+ draftinfo += ')'
171
177
  end
172
178
  l10n(draftinfo, @lang, @script)
173
179
  end
174
180
 
175
181
  def version(isoxml, _out)
176
- set(:edition, isoxml&.at(ns("//bibdata/edition"))&.text)
177
- set(:docyear, isoxml&.at(ns("//bibdata/copyright/from"))&.text)
178
- set(:draft, isoxml&.at(ns("//version/draft"))&.text)
179
- revdate = isoxml&.at(ns("//version/revision-date"))&.text
182
+ set(:edition, isoxml&.at(ns('//bibdata/edition'))&.text)
183
+ set(:docyear, isoxml&.at(ns('//bibdata/copyright/from'))&.text)
184
+ set(:draft, isoxml&.at(ns('//version/draft'))&.text)
185
+ revdate = isoxml&.at(ns('//version/revision-date'))&.text
180
186
  set(:revdate, revdate)
181
187
  set(:revdate_monthyear, monthyr(revdate))
182
188
  set(:draftinfo,
@@ -188,7 +194,7 @@ module IsoDoc
188
194
  set(:doctitle, main)
189
195
  end
190
196
 
191
- def subtitle(isoxml, _out)
197
+ def subtitle(_isoxml, _out)
192
198
  nil
193
199
  end
194
200
 
@@ -199,24 +205,30 @@ module IsoDoc
199
205
 
200
206
  def relations_partof(isoxml)
201
207
  std = isoxml.at(ns("//bibdata/relation[@type = 'partOf']")) || return
202
- id = std.at(ns(".//docidentifier"))
208
+ id = std.at(ns('.//docidentifier'))
203
209
  set(:partof, id.text) if id
204
210
  end
205
211
 
206
212
  def relations_obsoletes(isoxml)
207
213
  std = isoxml.at(ns("//bibdata/relation[@type = 'obsoletes']")) || return
208
- locality = std.at(ns(".//locality"))
209
- id = std.at(ns(".//docidentifier"))
214
+ locality = std.at(ns('.//locality'))
215
+ id = std.at(ns('.//docidentifier'))
210
216
  set(:obsoletes, id.text) if id
211
217
  set(:obsoletes_part, locality.text) if locality
212
218
  end
213
219
 
214
220
  def url(xml, _out)
215
- a = xml.at(ns("//bibdata/uri[not(@type)]")) and set(:url, a.text)
216
- a = xml.at(ns("//bibdata/uri[@type = 'html']")) and set(:html, a.text)
217
- a = xml.at(ns("//bibdata/uri[@type = 'xml']")) and set(:xml, a.text)
218
- a = xml.at(ns("//bibdata/uri[@type = 'pdf']")) and set(:pdf, a.text)
219
- a = xml.at(ns("//bibdata/uri[@type = 'doc']")) and set(:doc, a.text)
221
+ (a = xml.at(ns('//bibdata/uri[not(@type)]'))) && set(:url, a.text)
222
+ (a = xml.at(ns("//bibdata/uri[@type = 'html']"))) && set(:html, a.text)
223
+ (a = xml.at(ns("//bibdata/uri[@type = 'xml']"))) && set(:xml, a.text)
224
+ (a = xml.at(ns("//bibdata/uri[@type = 'pdf']"))) && set(:pdf, a.text)
225
+ (a = xml.at(ns("//bibdata/uri[@type = 'doc']"))) && set(:doc, a.text)
226
+ end
227
+
228
+ def keywords(isoxml, _out)
229
+ ret = []
230
+ isoxml.xpath(ns('//bibdata/keyword')).each { |kw| ret << kw.text }
231
+ set(:keywords, ret)
220
232
  end
221
233
  end
222
234
  end