isodoc 1.5.4 → 1.6.3

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -4
  3. data/Gemfile +2 -2
  4. data/Rakefile +2 -2
  5. data/bin/rspec +1 -2
  6. data/isodoc.gemspec +11 -11
  7. data/lib/isodoc-yaml/i18n-ar.yaml +152 -0
  8. data/lib/isodoc-yaml/i18n-de.yaml +149 -0
  9. data/lib/isodoc-yaml/i18n-es.yaml +151 -0
  10. data/lib/isodoc-yaml/i18n-ru.yaml +154 -0
  11. data/lib/isodoc/base_style/all.css +7 -0
  12. data/lib/isodoc/base_style/metanorma_word.css +7 -0
  13. data/lib/isodoc/base_style/metanorma_word.scss +8 -0
  14. data/lib/isodoc/base_style/reset.css +7 -0
  15. data/lib/isodoc/base_style/reset.scss +9 -0
  16. data/lib/isodoc/base_style/scripts.html +187 -0
  17. data/lib/isodoc/class_utils.rb +6 -5
  18. data/lib/isodoc/common.rb +2 -0
  19. data/lib/isodoc/convert.rb +30 -17
  20. data/lib/isodoc/css.rb +42 -28
  21. data/lib/isodoc/function/blocks.rb +21 -4
  22. data/lib/isodoc/function/blocks_example_note.rb +2 -2
  23. data/lib/isodoc/function/cleanup.rb +1 -2
  24. data/lib/isodoc/function/form.rb +51 -0
  25. data/lib/isodoc/function/inline.rb +32 -10
  26. data/lib/isodoc/function/references.rb +55 -42
  27. data/lib/isodoc/function/table.rb +1 -0
  28. data/lib/isodoc/function/to_word_html.rb +29 -28
  29. data/lib/isodoc/function/utils.rb +41 -38
  30. data/lib/isodoc/gem_tasks.rb +30 -31
  31. data/lib/isodoc/html_convert.rb +6 -4
  32. data/lib/isodoc/html_function/form.rb +62 -0
  33. data/lib/isodoc/html_function/postprocess.rb +35 -76
  34. data/lib/isodoc/html_function/postprocess_footnotes.rb +59 -0
  35. data/lib/isodoc/i18n.rb +33 -31
  36. data/lib/isodoc/pdf_convert.rb +1 -3
  37. data/lib/isodoc/presentation_function/bibdata.rb +13 -10
  38. data/lib/isodoc/presentation_function/block.rb +17 -8
  39. data/lib/isodoc/presentation_function/inline.rb +75 -118
  40. data/lib/isodoc/presentation_function/math.rb +84 -0
  41. data/lib/isodoc/presentation_function/section.rb +20 -22
  42. data/lib/isodoc/presentation_xml_convert.rb +2 -1
  43. data/lib/isodoc/sassc_importer.rb +1 -1
  44. data/lib/isodoc/version.rb +1 -1
  45. data/lib/isodoc/word_function/body.rb +28 -24
  46. data/lib/isodoc/word_function/footnotes.rb +22 -15
  47. data/lib/isodoc/word_function/postprocess.rb +16 -6
  48. data/lib/isodoc/xref.rb +10 -11
  49. data/lib/isodoc/xref/xref_counter.rb +32 -17
  50. data/lib/isodoc/xref/xref_gen.rb +45 -32
  51. data/lib/isodoc/xref/xref_sect_gen.rb +33 -31
  52. data/lib/isodoc/xslfo_convert.rb +36 -25
  53. data/spec/assets/html_override.css +1 -0
  54. data/spec/assets/word_override.css +1 -0
  55. data/spec/isodoc/blocks_spec.rb +2518 -2570
  56. data/spec/isodoc/cleanup_spec.rb +1107 -1109
  57. data/spec/isodoc/footnotes_spec.rb +1 -16
  58. data/spec/isodoc/form_spec.rb +156 -0
  59. data/spec/isodoc/i18n_spec.rb +984 -972
  60. data/spec/isodoc/inline_spec.rb +984 -920
  61. data/spec/isodoc/lists_spec.rb +316 -315
  62. data/spec/isodoc/postproc_spec.rb +1692 -1538
  63. data/spec/isodoc/presentation_xml_spec.rb +345 -342
  64. data/spec/isodoc/ref_spec.rb +718 -723
  65. data/spec/isodoc/section_spec.rb +910 -902
  66. data/spec/isodoc/table_spec.rb +566 -556
  67. data/spec/isodoc/terms_spec.rb +252 -256
  68. data/spec/isodoc/xref_spec.rb +3040 -2985
  69. data/spec/isodoc/xslfo_convert_spec.rb +39 -0
  70. data/spec/spec_helper.rb +30 -29
  71. metadata +80 -70
  72. data/.rubocop.ribose.yml +0 -65
  73. data/.rubocop.tb.yml +0 -650
  74. data/lib/twitter-cldr/patch.rb +0 -39
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "isodoc/common"
3
4
  require "fileutils"
4
5
  require "tempfile"
@@ -7,12 +8,12 @@ require_relative "css"
7
8
 
8
9
  module IsoDoc
9
10
  class Convert < ::IsoDoc::Common
10
- attr_accessor :options
11
- attr_accessor :i18n
12
- attr_accessor :meta
11
+ attr_accessor :options, :i18n, :meta, :xrefs
13
12
 
14
13
  # htmlstylesheet: Generic stylesheet for HTML
14
+ # htmlstylesheet_override: Override stylesheet for HTML
15
15
  # wordstylesheet: Generic stylesheet for Word
16
+ # wordstylesheet_override: Override stylesheet for Word
16
17
  # standardsheet: Stylesheet specific to Standard
17
18
  # header: Header file for Word
18
19
  # htmlcoverpage: Cover page for HTML
@@ -36,11 +37,10 @@ module IsoDoc
36
37
  # break_up_urls_in_tables: whether to insert spaces in URLs in tables
37
38
  # every 40-odd chars
38
39
  def initialize(options)
39
- @libdir ||= File.dirname(__FILE__)
40
+ @libdir ||= File.dirname(__FILE__) # rubocop:disable Lint/DisjunctiveAssignmentInConstructor
40
41
  options.merge!(default_fonts(options)) do |_, old, new|
41
42
  old || new
42
- end
43
- .merge!(default_file_locations(options)) do |_, old, new|
43
+ end.merge!(default_file_locations(options)) do |_, old, new|
44
44
  old || new
45
45
  end
46
46
  @options = options
@@ -48,7 +48,10 @@ module IsoDoc
48
48
  @tempfile_cache = []
49
49
  @htmlstylesheet_name = options[:htmlstylesheet]
50
50
  @wordstylesheet_name = options[:wordstylesheet]
51
+ @htmlstylesheet_override_name = options[:htmlstylesheet_override]
52
+ @wordstylesheet_override_name = options[:wordstylesheet_override]
51
53
  @standardstylesheet_name = options[:standardstylesheet]
54
+ @sourcefilename = options[:sourcefilename]
52
55
  @header = options[:header]
53
56
  @htmlcoverpage = options[:htmlcoverpage]
54
57
  @wordcoverpage = options[:wordcoverpage]
@@ -58,15 +61,16 @@ module IsoDoc
58
61
  @smallerfontsize = options[:smallerfontsize]
59
62
  @monospacefontsize = options[:monospacefontsize]
60
63
  @footnotefontsize = options[:footnotefontsize]
61
- @scripts = options[:scripts]
64
+ @scripts = options[:scripts] ||
65
+ File.join(File.dirname(__FILE__), "base_style", "scripts.html")
62
66
  @scripts_pdf = options[:scripts_pdf]
63
67
  @i18nyaml = options[:i18nyaml]
64
68
  @ulstyle = options[:ulstyle]
65
69
  @olstyle = options[:olstyle]
66
70
  @datauriimage = options[:datauriimage]
67
71
  @suppressheadingnumbers = options[:suppressheadingnumbers]
68
- @break_up_urls_in_tables = options[:break_up_urls_in_tables] == 'true'
69
- @termdomain = ''
72
+ @break_up_urls_in_tables = options[:break_up_urls_in_tables] == "true"
73
+ @termdomain = ""
70
74
  @termexample = false
71
75
  @note = false
72
76
  @sourcecode = false
@@ -88,17 +92,17 @@ module IsoDoc
88
92
  @wordToClevels = 2 if @wordToClevels.zero?
89
93
  @htmlToClevels = options[:htmltoclevels].to_i
90
94
  @htmlToClevels = 2 if @htmlToClevels.zero?
91
- @bookmarks_allocated = { 'X' => true }
95
+ @bookmarks_allocated = { "X" => true }
92
96
  @fn_bookmarks = {}
93
97
  end
94
98
 
95
99
  def tmpimagedir_suffix
96
- '_images'
100
+ "_images"
97
101
  end
98
102
 
99
103
  def html_doc_path(*file)
100
104
  file.each do |f|
101
- ret = File.join(@libdir, File.join('html', f))
105
+ ret = File.join(@libdir, File.join("html", f))
102
106
  File.exist?(ret) and return ret
103
107
  end
104
108
  nil
@@ -108,7 +112,7 @@ module IsoDoc
108
112
  @xrefs.parse docxml
109
113
  noko do |xml|
110
114
  xml.html **{ lang: @lang.to_s } do |html|
111
- html.parent.add_namespace('epub', 'http://www.idpf.org/2007/ops')
115
+ html.parent.add_namespace("epub", "http://www.idpf.org/2007/ops")
112
116
  info docxml, nil
113
117
  populate_css
114
118
  html.head { |head| define_head head, filename, dir }
@@ -130,8 +134,8 @@ module IsoDoc
130
134
  @i18n = I18n.new(lang, script, i18nyaml || @i18nyaml)
131
135
  end
132
136
 
133
- def l10n(x, lang = @lang, script = @script)
134
- @i18n.l10n(x, lang, script)
137
+ def l10n(expr, lang = @lang, script = @script)
138
+ @i18n.l10n(expr, lang, script)
135
139
  end
136
140
 
137
141
  def convert_init(file, input_filename, debug)
@@ -153,14 +157,23 @@ module IsoDoc
153
157
  docxml, filename, dir = convert_init(file, input_filename, debug)
154
158
  result = convert1(docxml, filename, dir)
155
159
  return result if debug
160
+
156
161
  output_filename ||= "#{filename}.#{@suffix}"
157
162
  postprocess(result, output_filename, dir)
158
163
  FileUtils.rm_rf dir
159
164
  end
160
165
 
161
- def middle_clause(docxml = nil)
166
+ def middle_clause(_docxml = nil)
162
167
  "//clause[parent::sections][not(@type = 'scope')]"\
163
- '[not(descendant::terms)]'
168
+ "[not(descendant::terms)]"
169
+ end
170
+
171
+ def target_pdf(node)
172
+ if /#/.match?(node["target"])
173
+ node["target"].sub(/#/, ".pdf#")
174
+ else
175
+ "##{node['target']}"
176
+ end
164
177
  end
165
178
  end
166
179
  end
data/lib/isodoc/css.rb CHANGED
@@ -6,26 +6,40 @@ module IsoDoc
6
6
  def precompiled_style_or_original(stylesheet_path)
7
7
  # Already have compiled stylesheet, use it
8
8
  return stylesheet_path if stylesheet_path.nil? ||
9
- File.extname(stylesheet_path) == '.css'
10
- basename = File.basename(stylesheet_path, '.*')
9
+ File.extname(stylesheet_path) == ".css"
10
+
11
+ basename = File.basename(stylesheet_path, ".*")
11
12
  compiled_path = File.join(File.dirname(stylesheet_path),
12
13
  "#{basename}.css")
13
14
  return stylesheet_path unless File.file?(compiled_path)
15
+
14
16
  compiled_path
15
17
  end
16
18
 
19
+ def localpath(path)
20
+ return path if %r{^[A-Z]:|^/|^file:/}.match?(path)
21
+ return path unless (@sourcedir || @localdir) && path
22
+
23
+ File.expand_path(File.join((@sourcedir || @localdir), path))
24
+ end
25
+
17
26
  # run this after @meta is populated
18
27
  def populate_css
19
- @htmlstylesheet = generate_css(@htmlstylesheet_name, true)
20
- @wordstylesheet = generate_css(@wordstylesheet_name, false)
21
- @standardstylesheet = generate_css(@standardstylesheet_name, false)
28
+ @htmlstylesheet = generate_css(localpath(@htmlstylesheet_name), true)
29
+ @wordstylesheet = generate_css(localpath(@wordstylesheet_name), false)
30
+ @standardstylesheet =
31
+ generate_css(localpath(@standardstylesheet_name), false)
32
+ @htmlstylesheet_override_name and @htmlstylesheet_override =
33
+ File.open(localpath(@htmlstylesheet_override_name))
34
+ @wordstylesheet_override_name and @wordstylesheet_override =
35
+ File.open(localpath(@wordstylesheet_override_name))
22
36
  end
23
37
 
24
38
  def default_fonts(_options)
25
39
  {
26
- bodyfont: 'Arial',
27
- headerfont: 'Arial',
28
- monospacefont: 'Courier',
40
+ bodyfont: "Arial",
41
+ headerfont: "Arial",
42
+ monospacefont: "Courier",
29
43
  }
30
44
  end
31
45
 
@@ -37,35 +51,35 @@ module IsoDoc
37
51
 
38
52
  def fonts_options
39
53
  {
40
- 'bodyfont' => options[:bodyfont] || 'Arial',
41
- 'headerfont' => options[:headerfont] || 'Arial',
42
- 'monospacefont' => options[:monospacefont] || 'Courier',
54
+ "bodyfont" => options[:bodyfont] || "Arial",
55
+ "headerfont" => options[:headerfont] || "Arial",
56
+ "monospacefont" => options[:monospacefont] || "Courier",
43
57
  "normalfontsize" => options[:normalfontsize],
44
58
  "monospacefontsize" => options[:monospacefontsize],
45
59
  "smallerfontsize" => options[:smallerfontsize],
46
- "footnotefontsize" => options[:footnotefontsize]
60
+ "footnotefontsize" => options[:footnotefontsize],
47
61
  }
48
62
  end
49
63
 
50
64
  def scss_fontheader(is_html_css)
51
- b = options[:bodyfont] || 'Arial'
52
- h = options[:headerfont] || 'Arial'
53
- m = options[:monospacefont] || 'Courier'
54
- ns = options[:normalfontsize] || (is_html_css ? "1.0em" : '12.0pt')
55
- ms = options[:monospacefontsize] || (is_html_css ? "0.8em" : '11.0pt')
56
- ss = options[:smallerfontsize] || (is_html_css ? "0.9em" : '10.0pt')
57
- fs = options[:footnotefontsize] || (is_html_css ? "0.9em" : '9.0pt')
65
+ b = options[:bodyfont] || "Arial"
66
+ h = options[:headerfont] || "Arial"
67
+ m = options[:monospacefont] || "Courier"
68
+ ns = options[:normalfontsize] || (is_html_css ? "1.0em" : "12.0pt")
69
+ ms = options[:monospacefontsize] || (is_html_css ? "0.8em" : "11.0pt")
70
+ ss = options[:smallerfontsize] || (is_html_css ? "0.9em" : "10.0pt")
71
+ fs = options[:footnotefontsize] || (is_html_css ? "0.9em" : "9.0pt")
58
72
  "$bodyfont: #{b};\n$headerfont: #{h};\n$monospacefont: #{m};\n"\
59
73
  "$normalfontsize: #{ns};\n$monospacefontsize: #{ms};\n"\
60
74
  "$smallerfontsize: #{ss};\n$footnotefontsize: #{fs};\n"
61
75
  end
62
76
 
63
77
  def convert_scss(filename, stylesheet, stripwordcss)
64
- require 'sassc'
65
- require 'isodoc/sassc_importer'
78
+ require "sassc"
79
+ require "isodoc/sassc_importer"
66
80
 
67
- [File.join(Gem.loaded_specs['isodoc'].full_gem_path,
68
- 'lib', 'isodoc'),
81
+ [File.join(Gem.loaded_specs["isodoc"].full_gem_path,
82
+ "lib", "isodoc"),
69
83
  File.dirname(filename)].each do |name|
70
84
  SassC.load_paths << name
71
85
  end
@@ -79,14 +93,14 @@ module IsoDoc
79
93
  return nil if filename.nil?
80
94
 
81
95
  filename = precompiled_style_or_original(filename)
82
- stylesheet = File.read(filename, encoding: 'UTF-8')
96
+ stylesheet = File.read(filename, encoding: "UTF-8")
83
97
  stylesheet = populate_template(stylesheet, :word)
84
- stylesheet.gsub!(/(\s|\{)mso-[^:]+:[^;]+;/m, '\\1') if stripwordcss
85
- if File.extname(filename) == '.scss'
98
+ stylesheet.gsub!(/(\s|\{)mso-[^:]+:[^;]+;/m, "\\1") if stripwordcss
99
+ if File.extname(filename) == ".scss"
86
100
  stylesheet = convert_scss(filename, stylesheet, stripwordcss)
87
101
  end
88
- Tempfile.open([File.basename(filename, '.*'), 'css'],
89
- encoding: 'utf-8') do |f|
102
+ Tempfile.open([File.basename(filename, ".*"), "css"],
103
+ encoding: "utf-8") do |f|
90
104
  f.write(stylesheet)
91
105
  f
92
106
  end
@@ -4,6 +4,16 @@ module IsoDoc::Function
4
4
  module Blocks
5
5
  @annotation = false
6
6
 
7
+ def middle_title(_isoxml, out)
8
+ out.p(**{ class: "zzSTDTitle1" }) { |p| p << @meta.get[:doctitle] }
9
+ end
10
+
11
+ def middle_admonitions(isoxml, out)
12
+ isoxml.xpath(ns("//sections/note | //sections/admonition")).each do |x|
13
+ parse(x, out)
14
+ end
15
+ end
16
+
7
17
  def figure_name_parse(node, div, name)
8
18
  return if name.nil?
9
19
  div.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
@@ -24,6 +34,7 @@ module IsoDoc::Function
24
34
  def figure_parse(node, out)
25
35
  return pseudocode_parse(node, out) if node["class"] == "pseudocode" ||
26
36
  node["type"] == "pseudocode"
37
+
27
38
  @in_figure = true
28
39
  out.div **figure_attrs(node) do |div|
29
40
  node.children.each do |n|
@@ -51,6 +62,7 @@ module IsoDoc::Function
51
62
 
52
63
  def sourcecode_name_parse(node, div, name)
53
64
  return if name.nil?
65
+
54
66
  div.p **{ class: "SourceTitle", style: "text-align:center;" } do |p|
55
67
  name.children.each { |n| parse(n, p) }
56
68
  end
@@ -91,14 +103,15 @@ module IsoDoc::Function
91
103
  @annotation = false
92
104
  end
93
105
 
94
- def admonition_class(node)
106
+ def admonition_class(_node)
95
107
  "Admonition"
96
108
  end
97
109
 
98
110
  def admonition_name(node, type)
99
111
  name = node&.at(ns("./name")) and return name
100
- name = Nokogiri::XML::Node.new('name', node.document)
112
+ name = Nokogiri::XML::Node.new("name", node.document)
101
113
  return unless type && @i18n.admonition[type]
114
+
102
115
  name << @i18n.admonition[type]&.upcase
103
116
  name
104
117
  end
@@ -119,7 +132,8 @@ module IsoDoc::Function
119
132
 
120
133
  def formula_where(dl, out)
121
134
  return unless dl
122
- out.p **{ style: "page-break-after:avoid;"} do |p|
135
+
136
+ out.p **{ style: "page-break-after:avoid;" } do |p|
123
137
  p << @i18n.where
124
138
  end
125
139
  parse(dl, out)
@@ -148,6 +162,7 @@ module IsoDoc::Function
148
162
  formula_where(node.at(ns("./dl")), div)
149
163
  node.children.each do |n|
150
164
  next if %w(stem dl name).include? n.name
165
+
151
166
  parse(n, div)
152
167
  end
153
168
  end
@@ -182,6 +197,7 @@ module IsoDoc::Function
182
197
  author = node.at(ns("./author"))
183
198
  source = node.at(ns("./source"))
184
199
  return if author.nil? && source.nil?
200
+
185
201
  out.p **{ class: "QuoteAttribution" } do |p|
186
202
  p << "&mdash; #{author.text}" if author
187
203
  p << ", " if author && source
@@ -201,8 +217,9 @@ module IsoDoc::Function
201
217
  end
202
218
 
203
219
  def passthrough_parse(node, out)
204
- return if node["format"] and
220
+ return if node["format"] &&
205
221
  !(node["format"].split(/,/).include? @format.to_s)
222
+
206
223
  out.passthrough node.text
207
224
  end
208
225
 
@@ -59,7 +59,7 @@ module IsoDoc::Function
59
59
  name = node&.at(ns("./name"))&.remove
60
60
  div.p do |p|
61
61
  name and p.span **{ class: "note_label" } do |s|
62
- name and name.children.each { |n| parse(n, s) }
62
+ name.children.each { |n| parse(n, s) }
63
63
  s << note_delim
64
64
  end
65
65
  insert_tab(p, 1)
@@ -98,7 +98,7 @@ module IsoDoc::Function
98
98
  @note = true
99
99
  out.div **note_attrs(node) do |div|
100
100
  node&.at(ns("./*[local-name() != 'name'][1]"))&.name == "p" ?
101
- #node.first_element_child.name == "p" ?
101
+ # node.first_element_child.name == "p" ?
102
102
  note_p_parse(node, div) : note_parse1(node, div)
103
103
  end
104
104
  @note = false
@@ -204,8 +204,7 @@ module IsoDoc::Function
204
204
  docxml
205
205
  end
206
206
 
207
- def symbols_cleanup(docxml)
208
- end
207
+ def symbols_cleanup(docxml); end
209
208
 
210
209
  def table_footnote_reference_format(a)
211
210
  a
@@ -0,0 +1,51 @@
1
+ module IsoDoc::Function
2
+ module Form
3
+ def form_parse(node, out)
4
+ node.children.each do |n|
5
+ parse(n, out)
6
+ end
7
+ end
8
+
9
+ def input_parse(node, out)
10
+ case node["type"]
11
+ when "button" then out << "[#{node['value'] || 'BUTTON'}]"
12
+ when "checkbox" then out << "&#x2610; "
13
+ when "date" then text_input(out)
14
+ when "file" then text_input(out)
15
+ when "password" then text_input(out)
16
+ when "radio" then out << "&#x25CE; "
17
+ when "submit" # nop
18
+ when "text" then text_input(out, node["maxlength"])
19
+ end
20
+ end
21
+
22
+ def text_input(out, length = 10)
23
+ length ||= 10
24
+ length = length.to_i
25
+ length.zero? and length = 10
26
+ out << "_" * length
27
+ out << " "
28
+ end
29
+
30
+ def select_parse(node, out)
31
+ text_input(out, node["size"] || 10)
32
+ end
33
+
34
+ def label_parse(node, out)
35
+ node.children.each do |n|
36
+ parse(n, out)
37
+ end
38
+ end
39
+
40
+ def option_parse(node, out); end
41
+
42
+ def textarea_parse(_node, out)
43
+ out.table **{ border: 1, width: "50%" } do |t|
44
+ t.tr do |tr|
45
+ tr.td do |td|
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -23,21 +23,27 @@ module IsoDoc::Function
23
23
  end
24
24
 
25
25
  def xref_parse(node, out)
26
- target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".html#") :
27
- "##{node["target"]}"
28
- out.a(**{ "href": target }) { |l| no_locality_parse(node, l) }
26
+ target = if /#/.match?(node["target"])
27
+ node["target"].sub(/#/, ".html#")
28
+ else
29
+ "##{node['target']}"
30
+ end
31
+ out.a(**{ "href": target }) { |l| no_locality_parse(node, l) }
29
32
  end
30
33
 
31
34
  def suffix_url(url)
32
- return url if %r{^http[s]?://}.match(url)
35
+ return url if %r{^https?://}.match?(url)
36
+ return url unless File.extname(url).empty?
37
+
33
38
  url.sub(/#{File.extname(url)}$/, ".html")
34
39
  end
35
40
 
36
41
  def eref_target(node)
37
- href = "#" + node["bibitemid"]
42
+ href = "##{node['bibitemid']}"
38
43
  url = node.at(ns("//bibitem[@id = '#{node['bibitemid']}']/"\
39
44
  "uri[@type = 'citation']"))
40
45
  return href unless url
46
+
41
47
  href = suffix_url(url.text)
42
48
  anchor = node&.at(ns(".//locality[@type = 'anchor']"))&.text&.strip
43
49
  anchor and href += "##{anchor}"
@@ -68,10 +74,11 @@ module IsoDoc::Function
68
74
  end
69
75
 
70
76
  def stem_parse(node, out)
71
- ooml = if node["type"] == "AsciiMath"
77
+ ooml = case node["type"]
78
+ when "AsciiMath"
72
79
  "#{@openmathdelim}#{HTMLEntities.new.encode(node.text)}"\
73
80
  "#{@closemathdelim}"
74
- elsif node["type"] == "MathML" then node.first_element_child.to_s
81
+ when "MathML" then node.first_element_child.to_s
75
82
  else
76
83
  HTMLEntities.new.encode(node.text)
77
84
  end
@@ -93,7 +100,7 @@ module IsoDoc::Function
93
100
  height: node["height"] || "auto",
94
101
  width: node["width"] || "auto",
95
102
  title: node["title"],
96
- alt: node["alt"] }
103
+ alt: node["alt"] }
97
104
  out.img **attr_code(attrs)
98
105
  image_title_parse(out, caption)
99
106
  end
@@ -106,12 +113,27 @@ module IsoDoc::Function
106
113
 
107
114
  def text_parse(node, out)
108
115
  return if node.nil? || node.text.nil?
116
+
109
117
  text = node.to_s
110
- text = text.gsub("\n", "<br/>").gsub("<br/> ", "<br/>&nbsp;").
111
- gsub(/[ ](?=[ ])/, "&nbsp;") if in_sourcecode
118
+ if in_sourcecode
119
+ text = text.gsub("\n", "<br/>").gsub("<br/> ", "<br/>&nbsp;")
120
+ .gsub(/ (?= )/, "&nbsp;")
121
+ end
112
122
  out << text
113
123
  end
114
124
 
125
+ def add_parse(node, out)
126
+ out.span **{class: "addition"} do |e|
127
+ node.children.each { |n| parse(n, e) }
128
+ end
129
+ end
130
+
131
+ def del_parse(node, out)
132
+ out.span **{class: "deletion"} do |e|
133
+ node.children.each { |n| parse(n, e) }
134
+ end
135
+ end
136
+
115
137
  def error_parse(node, out)
116
138
  text = node.to_xml.gsub(/</, "&lt;").gsub(/>/, "&gt;")
117
139
  out.para do |p|