isodoc 2.2.0 → 2.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c60f8eb9fcf49c289d99f64d901511387ae9d928a93c20ec81c011eb536f8a6a
4
- data.tar.gz: f4c33c72526c543b3d7c4929a20dfaa2413e9d007b8d2315aed424e156ad4061
3
+ metadata.gz: aed515059a4bfbb122ff29141ec687c3fab6fed9539fde9e2fc6d89b54ddc6ec
4
+ data.tar.gz: 35c681874fc12a48baa1ceffaff00680a577c90cde69c58caf896eeab8c8abb4
5
5
  SHA512:
6
- metadata.gz: bd64d2a35ac86b7b70d46b4ea3631070291b32ee014199d1bc395c5bf33c130d41527afcce573fddd49dc96a4f97d77a6e21a81ed45afec325ce2da61ad4c6ed
7
- data.tar.gz: 758249109707c1a6132311e2706f9b791799960f063546cdc8d125f36919845e03bfc5546d2a68d47c30f782fd20b3de1143e66e88a53b5b5bb766e52407a2a7
6
+ metadata.gz: 2313eec736db0f20d8ce87a8505e49a263d93ec67ee82d28d76f07c12388bce1ac213f380677784e1a9dacc12e78b655d39ecada99745f06e7e4a91f71124458
7
+ data.tar.gz: d680c24a277d386ab74cce9c87d1c0ff27087db33f4db42c973b3f51b5e098cae7a7d66aeb61dad50c36bf3ca23d7b9befe718584b3311f3f6ab971893872027
data/isodoc.gemspec CHANGED
@@ -34,15 +34,14 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency "asciimath"
35
35
  spec.add_dependency "html2doc", "~> 1.4.1"
36
36
  spec.add_dependency "htmlentities", "~> 4.3.4"
37
- spec.add_dependency "isodoc-i18n", "~> 1.0.0"
37
+ spec.add_dependency "isodoc-i18n", "~> 1.0.6"
38
38
  spec.add_dependency "liquid", "~> 4"
39
39
  # spec.add_dependency "metanorma", ">= 1.2.0"
40
40
  spec.add_dependency "emf2svg"
41
41
  spec.add_dependency "mathml2asciimath"
42
- spec.add_dependency "metanorma-utils"
43
-
42
+ spec.add_dependency "mn-requirements", "~> 0.0.1"
44
43
  spec.add_dependency "relaton-cli"
45
- spec.add_dependency "relaton-render", ">= 0.3.1"
44
+ spec.add_dependency "relaton-render", "~> 0.4.0"
46
45
  spec.add_dependency "roman-numerals"
47
46
  spec.add_dependency "thread_safe"
48
47
  spec.add_dependency "twitter_cldr", ">= 6.6.0"
@@ -13,10 +13,7 @@ module IsoDoc
13
13
  end
14
14
 
15
15
  def ns(xpath)
16
- xpath.gsub(%r{/([a-zA-z])}, "/xmlns:\\1")
17
- .gsub(%r{::([a-zA-z])}, "::xmlns:\\1")
18
- .gsub(%r{\[([a-zA-z][a-z0-9A-Z@/-]* ?=)}, "[xmlns:\\1")
19
- .gsub(%r{\[([a-zA-z][a-z0-9A-Z@/-]*[/\[\]])}, "[xmlns:\\1")
16
+ Metanorma::Utils::ns(xpath)
20
17
  end
21
18
 
22
19
  def liquid(doc)
@@ -5,11 +5,13 @@ require "fileutils"
5
5
  require "tempfile"
6
6
  require_relative "i18n"
7
7
  require_relative "css"
8
+ require_relative "init"
8
9
  require "securerandom"
10
+ require "mn-requirements"
9
11
 
10
12
  module IsoDoc
11
13
  class Convert < ::IsoDoc::Common
12
- attr_accessor :options, :i18n, :meta, :xrefs
14
+ attr_accessor :options, :i18n, :meta, :xrefs, :reqt_models
13
15
 
14
16
  # htmlstylesheet: Generic stylesheet for HTML
15
17
  # htmlstylesheet_override: Override stylesheet for HTML
@@ -45,22 +47,28 @@ module IsoDoc
45
47
  # tocrecommendations: add ToC for rcommendations
46
48
  # fonts: fontist fonts to install
47
49
  # fontlicenseagreement: fontist font license agreement
48
- def initialize(options)
49
- @libdir ||= File.dirname(__FILE__) # rubocop:disable Lint/DisjunctiveAssignmentInConstructor
50
+ def initialize(options) # rubocop:disable Lint/MissingSuper
51
+ @options = options_preprocess(options)
52
+ init_stylesheets(@options)
53
+ init_covers(@options)
54
+ init_toc(@options)
55
+ init_fonts(@options)
56
+ init_processing
57
+ init_locations(@options)
58
+ init_i18n(@options)
59
+ init_rendering(@options)
60
+ end
61
+
62
+ def options_preprocess(options)
50
63
  options.merge!(default_fonts(options)) do |_, old, new|
51
64
  old || new
52
65
  end.merge!(default_file_locations(options)) do |_, old, new|
53
66
  old || new
54
67
  end
55
- @options = options
56
- @files_to_delete = []
57
- @tempfile_cache = []
58
- @sourcefilename = options[:sourcefilename]
59
- init_stylesheets(options)
60
- init_covers(options)
61
- init_toc(options)
62
- init_fonts(options)
63
- @i18nyaml = options[:i18nyaml]
68
+ options
69
+ end
70
+
71
+ def init_rendering(options)
64
72
  @ulstyle = options[:ulstyle]
65
73
  @olstyle = options[:olstyle]
66
74
  @datauriimage = options[:datauriimage]
@@ -69,6 +77,26 @@ module IsoDoc
69
77
  @sectionsplit = options[:sectionsplit] == "true"
70
78
  @suppressasciimathdup = options[:suppressasciimathdup] == "true"
71
79
  @bare = options[:bare]
80
+ @aligncrosselements = options[:aligncrosselements]
81
+ end
82
+
83
+ def init_i18n(options)
84
+ @i18nyaml = options[:i18nyaml]
85
+ @lang = options[:language] || "en"
86
+ @script = options[:script] || "Latn"
87
+ end
88
+
89
+ def init_locations(options)
90
+ @libdir ||= File.dirname(__FILE__)
91
+ @baseassetpath = options[:baseassetpath]
92
+ @tmpimagedir_suffix = tmpimagedir_suffix
93
+ @tmpfilesdir_suffix = tmpfilesdir_suffix
94
+ @sourcefilename = options[:sourcefilename]
95
+ @files_to_delete = []
96
+ @tempfile_cache = []
97
+ end
98
+
99
+ def init_processing
72
100
  @termdomain = ""
73
101
  @termexample = false
74
102
  @note = false
@@ -83,16 +111,10 @@ module IsoDoc
83
111
  @c = HTMLEntities.new
84
112
  @openmathdelim = "`"
85
113
  @closemathdelim = "`"
86
- @lang = options[:language] || "en"
87
- @script = options[:script] || "Latn"
88
114
  @maxwidth = 1200
89
115
  @maxheight = 800
90
116
  @bookmarks_allocated = { "X" => true }
91
117
  @fn_bookmarks = {}
92
- @baseassetpath = options[:baseassetpath]
93
- @aligncrosselements = options[:aligncrosselements]
94
- @tmpimagedir_suffix = tmpimagedir_suffix
95
- @tmpfilesdir_suffix = tmpfilesdir_suffix
96
118
  end
97
119
 
98
120
  def init_fonts(options)
@@ -171,35 +193,27 @@ module IsoDoc
171
193
  end
172
194
  end
173
195
 
174
- def metadata_init(lang, script, i18n)
175
- @meta = Metadata.new(lang, script, i18n)
176
- end
177
-
178
- def xref_init(lang, script, _klass, i18n, options)
179
- html = HtmlConvert.new(language: @lang, script: @script)
180
- @xrefs = Xref.new(lang, script, html, i18n, options)
181
- end
182
-
183
- def i18n_init(lang, script, i18nyaml = nil)
184
- @i18n = I18n.new(lang, script, i18nyaml: i18nyaml || @i18nyaml)
185
- end
186
-
187
- def l10n(expr, lang = @lang, script = @script)
188
- @i18n.l10n(expr, lang, script)
189
- end
190
-
191
196
  def convert_init(file, input_filename, debug)
192
197
  docxml = Nokogiri::XML(file) { |config| config.huge }
193
198
  filename, dir = init_file(input_filename, debug)
194
199
  docxml.root.default_namespace = ""
195
- lang = docxml&.at(ns("//bibdata/language"))&.text and @lang = lang
196
- script = docxml&.at(ns("//bibdata/script"))&.text and @script = script
197
- i18n_init(@lang, @script)
200
+ convert_i18n_init(docxml)
198
201
  metadata_init(@lang, @script, @i18n)
199
202
  xref_init(@lang, @script, self, @i18n, {})
200
203
  [docxml, filename, dir]
201
204
  end
202
205
 
206
+ def convert_i18n_init(docxml)
207
+ lang = docxml&.at(ns("//bibdata/language"))&.text and @lang = lang
208
+ script = docxml&.at(ns("//bibdata/script"))&.text and @script = script
209
+ i18n_init(@lang, @script)
210
+ @reqt_models = Metanorma::Requirements
211
+ .new({
212
+ default: "default", lang: lang, script: script,
213
+ labels: @i18n.get
214
+ })
215
+ end
216
+
203
217
  def convert(input_filename, file = nil, debug = false,
204
218
  output_filename = nil)
205
219
  file = File.read(input_filename, encoding: "utf-8") if file.nil?
@@ -219,10 +233,8 @@ module IsoDoc
219
233
  end
220
234
 
221
235
  def target_pdf(node)
222
- if /#/.match?(node["target"])
223
- node["target"].sub(/#/, ".pdf#")
224
- else
225
- "##{node['target']}"
236
+ if /#/.match?(node["target"]) then node["target"].sub(/#/, ".pdf#")
237
+ else "##{node['target']}"
226
238
  end
227
239
  end
228
240
  end
@@ -120,7 +120,7 @@ module IsoDoc
120
120
  def omit_docid_prefix(prefix)
121
121
  return true if prefix.nil? || prefix.empty?
122
122
 
123
- %w(ISO IEC IEV ITU W3C csd metanorma repository metanorma-ordinal)
123
+ %w(ISO IEC IEV ITU W3C BIPM csd metanorma repository metanorma-ordinal)
124
124
  .include? prefix
125
125
  end
126
126
 
@@ -1,121 +1,50 @@
1
1
  module IsoDoc
2
2
  module Function
3
3
  module Blocks
4
- def recommendation_labels(node)
5
- [node.at(ns("./label")), node.at(ns("./title")), node.at(ns("./name"))]
6
- end
7
-
8
- def recommendation_name(node, out, _type)
9
- label, title, lbl = recommendation_labels(node)
10
- out.p **{ class: "RecommendationTitle" } do |b|
11
- lbl&.children&.each { |n| parse(n, b) }
12
- b << l10n(":")
13
- if label || title
14
- b.br
15
- label&.children&.each { |n| parse(n, b) }
16
- b << "#{clausedelim} " if label && title
17
- title&.children&.each { |n| parse(n, b) }
18
- end
19
- end
20
- end
21
-
22
- def recommendation_attributes1(node)
23
- out = []
24
- oblig = node["obligation"] and
25
- out << l10n("#{@i18n.obligation}: #{oblig}")
26
- node.xpath(ns("./subject")).each do |subj|
27
- out << l10n("#{@i18n.subject}: #{subj.text}")
28
- end
29
- node.xpath(ns("./inherit")).each do |i|
30
- out << recommendation_attr_parse(i, @i18n.inherits)
31
- end
32
- node.xpath(ns("./classification")).each do |c|
33
- line = recommendation_attr_keyvalue(c, "tag", "value") and out << line
34
- end
35
- out
36
- end
37
-
38
- def recommendation_attr_parse(node, label)
39
- noko do |xml|
40
- xml << "#{label}: "
41
- node.children.each { |n| parse(n, xml) }
42
- end.join
43
- end
4
+ def recommendation_name(name, out)
5
+ return if name.nil?
44
6
 
45
- def recommendation_attr_keyvalue(node, key, value)
46
- tag = node.at(ns("./#{key}")) or return nil
47
- value = node.at(ns("./#{value}")) or return nil
48
- "#{tag.text.capitalize}: #{value.text}"
49
- end
50
-
51
- def recommendation_attributes(node, out)
52
- ret = recommendation_attributes1(node)
53
- return if ret.empty?
54
-
55
- out.p do |p|
56
- p.i do |i|
57
- i << ret.join("<br/>")
58
- end
7
+ out.p **{ class: "RecommendationTitle" } do |p|
8
+ name.children.each { |n| parse(n, p) }
59
9
  end
60
10
  end
61
11
 
62
- def reqt_metadata_node(node)
63
- %w(label title subject classification tag value
64
- inherit name).include? node.name
65
- end
66
-
67
12
  def reqt_attrs(node, klass)
68
13
  attr_code(class: klass, id: node["id"], style: keep_style(node))
69
14
  end
70
15
 
71
16
  def recommendation_parse(node, out)
72
17
  out.div **reqt_attrs(node, "recommend") do |t|
73
- recommendation_name(node, t, @i18n.recommendation)
74
- recommendation_attributes(node, out)
75
- node.children.each do |n|
76
- parse(n, t) unless reqt_metadata_node(n)
77
- end
18
+ recommendation_parse1(node, t)
19
+ end
20
+ end
21
+
22
+ def recommendation_parse1(node, out)
23
+ recommendation_name(node.at(ns("./name")), out)
24
+ node.children.each do |n|
25
+ parse(n, out) unless n.name == "name"
78
26
  end
79
27
  end
80
28
 
81
29
  def requirement_parse(node, out)
82
30
  out.div **reqt_attrs(node, "require") do |t|
83
- recommendation_name(node, t, @i18n.requirement)
84
- recommendation_attributes(node, out)
85
- node.children.each do |n|
86
- parse(n, t) unless reqt_metadata_node(n)
87
- end
31
+ recommendation_parse1(node, t)
88
32
  end
89
33
  end
90
34
 
91
35
  def permission_parse(node, out)
92
36
  out.div **reqt_attrs(node, "permission") do |t|
93
- recommendation_name(node, t, @i18n.permission)
94
- recommendation_attributes(node, out)
95
- node.children.each do |n|
96
- parse(n, t) unless reqt_metadata_node(n)
97
- end
37
+ recommendation_parse1(node, t)
98
38
  end
99
39
  end
100
40
 
101
- def reqt_component_attrs(node)
102
- klass = node.name
103
- klass == "component" and klass = node["class"]
104
- attr_code(class: "requirement-#{klass}",
105
- style: keep_style(node))
106
- end
107
-
108
- def requirement_component_parse(node, out)
109
- return if node["exclude"] == "true"
110
-
111
- out.div **reqt_component_attrs(node) do |div|
41
+ def div_parse(node, out)
42
+ out.div **reqt_attrs(node, node["type"]) do |t|
112
43
  node.children.each do |n|
113
- parse(n, div)
44
+ parse(n, t)
114
45
  end
115
46
  end
116
47
  end
117
-
118
- def requirement_skip_parse(node, out); end
119
48
  end
120
49
  end
121
50
  end
@@ -204,11 +204,12 @@ module IsoDoc
204
204
  when "requirement" then requirement_parse(node, out)
205
205
  when "recommendation" then recommendation_parse(node, out)
206
206
  when "permission" then permission_parse(node, out)
207
- when "subject", "classification"
208
- requirement_skip_parse(node, out)
209
- when "inherit", "description", "specification", "measurement-target",
210
- "verification", "import", "component"
211
- requirement_component_parse(node, out)
207
+ when "div" then div_parse(node, out)
208
+ #when "subject", "classification"
209
+ # requirement_skip_parse(node, out)
210
+ #when "inherit", "description", "specification", "measurement-target",
211
+ #"verification", "import", "component"
212
+ # requirement_component_parse(node, out)
212
213
  when "index" then index_parse(node, out)
213
214
  when "index-xref" then index_xref_parse(node, out)
214
215
  when "termref" then termrefelem_parse(node, out)
@@ -222,6 +222,10 @@ module IsoDoc
222
222
  application/x-msmetafile image/x-xbitmap).include? type
223
223
  end
224
224
 
225
+ def eps?(type)
226
+ %w(application/postscript image/x-eps).include? type
227
+ end
228
+
225
229
  def cleanup_entities(text, is_xml: true)
226
230
  c = HTMLEntities.new
227
231
  if is_xml
@@ -0,0 +1,20 @@
1
+ module IsoDoc
2
+ class Convert < ::IsoDoc::Common
3
+ def metadata_init(lang, script, i18n)
4
+ @meta = Metadata.new(lang, script, i18n)
5
+ end
6
+
7
+ def xref_init(lang, script, _klass, i18n, options)
8
+ html = HtmlConvert.new(language: @lang, script: @script)
9
+ @xrefs = Xref.new(lang, script, html, i18n, options)
10
+ end
11
+
12
+ def i18n_init(lang, script, i18nyaml = nil)
13
+ @i18n = I18n.new(lang, script, i18nyaml: i18nyaml || @i18nyaml)
14
+ end
15
+
16
+ def l10n(expr, lang = @lang, script = @script)
17
+ @i18n.l10n(expr, lang, script)
18
+ end
19
+ end
20
+ end
@@ -45,7 +45,6 @@ module IsoDoc
45
45
  end
46
46
  end
47
47
 
48
- # introduce name element
49
48
  def formula1(elem)
50
49
  lbl = @xrefs.anchor(elem["id"], :label, false)
51
50
  prefix_name(elem, "", lbl, "name")
@@ -73,7 +72,6 @@ module IsoDoc
73
72
  end
74
73
  end
75
74
 
76
- # introduce name element
77
75
  def note1(elem)
78
76
  return if elem.parent.name == "bibitem" || elem["notag"] == "true"
79
77
 
@@ -116,11 +114,10 @@ module IsoDoc
116
114
  end
117
115
  end
118
116
 
119
- # introduce name element
120
117
  def recommendation1(elem, type)
121
- n = @xrefs.anchor(elem["id"], :label, false)
122
- lbl = (n.nil? ? type : l10n("#{type} #{n}"))
123
- prefix_name(elem, "", lbl, "name")
118
+ lbl = @reqt_models.model(elem["model"])
119
+ .recommendation_label(elem, type, xrefs)
120
+ prefix_name(elem, "", l10n(lbl), "name")
124
121
  end
125
122
 
126
123
  def table(docxml)
@@ -175,5 +172,25 @@ module IsoDoc
175
172
  def ol1(elem)
176
173
  elem["type"] ||= ol_depth(elem).to_s
177
174
  end
175
+
176
+ def requirement_render_preprocessing(docxml); end
177
+
178
+ REQS = %w(requirement recommendation permission).freeze
179
+
180
+ def requirement_render(docxml)
181
+ requirement_render_preprocessing(docxml)
182
+ REQS.each do |x|
183
+ REQS.each do |y|
184
+ docxml.xpath(ns("//#{x}//#{y}")).each { |r| requirement_render1(r) }
185
+ end
186
+ end
187
+ docxml.xpath(ns("//requirement | //recommendation | //permission"))
188
+ .each { |r| requirement_render1(r) }
189
+ end
190
+
191
+ def requirement_render1(node)
192
+ node.replace(@reqt_models.model(node["model"])
193
+ .requirement_render1(node))
194
+ end
178
195
  end
179
196
  end
@@ -11,7 +11,14 @@ module IsoDoc
11
11
  else s.remove
12
12
  end
13
13
  end
14
- docxml.xpath(ns("//image")).each { |f| svg_emf_double(f) }
14
+ imageconvert(docxml)
15
+ end
16
+
17
+ def imageconvert(docxml)
18
+ docxml.xpath(ns("//image")).each do |f|
19
+ eps2svg(f)
20
+ svg_emf_double(f)
21
+ end
15
22
  end
16
23
 
17
24
  def svg_extract(elem)
@@ -36,6 +43,16 @@ module IsoDoc
36
43
  l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
37
44
  end
38
45
 
46
+ def eps2svg(img)
47
+ return unless eps?(img["mimetype"])
48
+
49
+ img["mimetype"] = "image/svg+xml"
50
+ if src = eps_to_svg(img)
51
+ img["src"] = src
52
+ img.children = ""
53
+ end
54
+ end
55
+
39
56
  def svg_emf_double(img)
40
57
  if emf?(img["mimetype"])
41
58
  img = emf_encode(img)
@@ -46,40 +63,59 @@ module IsoDoc
46
63
  end
47
64
 
48
65
  def emf_encode(img)
49
- img["mimetype"] = "image/svg+xml"
50
- unless %r{^data:image}.match?(img["src"])
51
- img["src"] = Metanorma::Utils::datauri(img["src"])
52
- end
66
+ svg_prep(img)
53
67
  img.children = "<emf src='#{img['src']}'/>"
54
68
  img["src"] = ""
55
69
  img
56
70
  end
57
71
 
72
+ def svg_prep(img)
73
+ img["mimetype"] = "image/svg+xml"
74
+ %r{^data:image}.match?(img["src"]) or
75
+ img["src"] = Metanorma::Utils::datauri(img["src"])
76
+ end
77
+
58
78
  def emf_to_svg(img)
59
79
  emf = Metanorma::Utils::save_dataimage(img.at(ns("./emf/@src")).text)
60
80
  Emf2svg.from_file(emf).sub(/<\?[^>]+>/, "")
61
81
  end
62
82
 
83
+ def eps_to_svg(node)
84
+ uri = eps_to_svg_uri(node)
85
+ ret = imgfile_suffix(uri, "svg")
86
+ File.exist?(ret) and return ret
87
+ inkscape_convert(uri, ret, "--export-plain-svg")
88
+ end
89
+
63
90
  def svg_to_emf(node)
64
91
  uri = svg_to_emf_uri(node)
65
- ret = svg_to_emf_filename(uri)
92
+ ret = imgfile_suffix(uri, "emf")
66
93
  File.exist?(ret) and return ret
94
+ inkscape_convert(uri, ret, '--export-type="emf"')
95
+ end
96
+
97
+ def inkscape_convert(uri, file, option)
67
98
  exe = inkscape_installed? or raise "Inkscape missing in PATH, unable" \
68
- "to convert EMF to SVG. Aborting."
99
+ "to convert image #{uri}. Aborting."
69
100
  uri = Metanorma::Utils::external_path uri
70
101
  exe = Metanorma::Utils::external_path exe
71
- system(%(#{exe} --export-type="emf" #{uri})) and
72
- return Metanorma::Utils::datauri(ret)
102
+ system(%(#{exe} #{option} #{uri})) and
103
+ return Metanorma::Utils::datauri(file)
73
104
 
74
- raise %(Fail on #{exe} --export-type="emf" #{uri})
105
+ raise %(Fail on #{exe} #{option} #{uri})
75
106
  end
76
107
 
77
108
  def svg_to_emf_uri(node)
78
- uri = if node&.elements&.first&.name == "svg"
79
- a = Base64.strict_encode64(node.children.to_xml)
80
- "data:image/svg+xml;base64,#{a}"
81
- else node["src"]
82
- end
109
+ uri = svg_to_emf_uri_convert(node)
110
+ cache_dataimage(uri)
111
+ end
112
+
113
+ def eps_to_svg_uri(node)
114
+ uri = eps_to_svg_uri_convert(node)
115
+ cache_dataimage(uri)
116
+ end
117
+
118
+ def cache_dataimage(uri)
83
119
  if %r{^data:}.match?(uri)
84
120
  uri = save_dataimage(uri)
85
121
  @tempfile_cache << uri
@@ -87,12 +123,25 @@ module IsoDoc
87
123
  uri
88
124
  end
89
125
 
90
- def svg_to_emf_filename(uri)
91
- "#{File.join(File.dirname(uri), File.basename(uri, '.*'))}.emf"
126
+ def svg_to_emf_uri_convert(node)
127
+ if node&.elements&.first&.name == "svg"
128
+ a = Base64.strict_encode64(node.children.to_xml)
129
+ "data:image/svg+xml;base64,#{a}"
130
+ else node["src"]
131
+ end
132
+ end
133
+
134
+ def eps_to_svg_uri_convert(node)
135
+ if node.text.strip.empty?
136
+ node["src"]
137
+ else
138
+ a = Base64.strict_encode64(node.children.to_xml)
139
+ "data:application/postscript;base64,#{a}"
140
+ end
92
141
  end
93
142
 
94
- def emf_to_svgfilename(uri)
95
- "#{File.join(File.dirname(uri), File.basename(uri, '.*'))}.svg"
143
+ def imgfile_suffix(uri, suffix)
144
+ "#{File.join(File.dirname(uri), File.basename(uri, '.*'))}.#{suffix}"
96
145
  end
97
146
 
98
147
  def inkscape_installed?