metanorma 1.3.4 → 1.3.8

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.
@@ -1,13 +1,15 @@
1
1
  module Metanorma
2
2
  class Document
3
3
  # @return [Strin]
4
- attr_reader :file, :attachment, :bibitem
4
+ attr_reader :file, :attachment, :bibitem, :index
5
5
 
6
6
  # @param bibitem [RelatonBib::BibliographicItem]
7
7
  def initialize(bibitem, file, options = {})
8
8
  @bibitem = bibitem
9
9
  @file = file
10
10
  @attachment = options[:attachment]
11
+ @index = options[:index]
12
+ @index = true if @index.nil?
11
13
  @raw = options[:raw]
12
14
  end
13
15
 
@@ -16,10 +18,11 @@ module Metanorma
16
18
  # @param attachment [Bool] is an attachment
17
19
  # @param identifier [String] is the identifier assigned the file
18
20
  # in the collection file
21
+ # @param index [Bool] is indication on whether to index this file in coverpage
19
22
  # @return [Metanorma::Document]
20
- def parse_file(file, attachment, identifier = nil)
23
+ def parse_file(file, attachment, identifier = nil, index = true)
21
24
  new(bibitem(file, attachment, identifier), file,
22
- { attachment: attachment })
25
+ { attachment: attachment, index: index })
23
26
  end
24
27
 
25
28
  # #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
@@ -30,7 +33,9 @@ module Metanorma
30
33
 
31
34
  # raw XML file, can be used to put in entire file instead of just bibitem
32
35
  def raw_file(filename)
33
- doc = Nokogiri::XML(File.read(filename, encoding: "UTF-8"))
36
+ doc = Nokogiri::XML(File.read(filename, encoding: "UTF-8")) do |config|
37
+ config.huge
38
+ end
34
39
  new(doc, filename, raw: true)
35
40
  end
36
41
 
@@ -100,7 +105,9 @@ module Metanorma
100
105
  if @raw
101
106
  builder << @bibitem.root.to_xml
102
107
  else
103
- builder.send(type + "-standard") { |b| b << @bibitem.to_xml(bibdata: true) }
108
+ builder.send("#{type}-standard") do |b|
109
+ b << @bibitem.to_xml(bibdata: true)
110
+ end
104
111
  end
105
112
  end
106
113
  end
@@ -57,9 +57,9 @@ module Metanorma
57
57
  end
58
58
 
59
59
  ADOC_OPTIONS = %w(htmlstylesheet htmlcoverpage htmlintropage scripts
60
- scripts-override scripts-pdf wordstylesheet bare i18nyaml
60
+ scripts-override scripts-pdf wordstylesheet i18nyaml
61
61
  standardstylesheet header wordcoverpage wordintropage
62
- ulstyle olstyle htmlstylesheet-override
62
+ ulstyle olstyle htmlstylesheet-override bare
63
63
  htmltoclevels doctoclevels sectionsplit
64
64
  body-font header-font monospace-font title-font
65
65
  wordstylesheet-override).freeze
@@ -3,10 +3,7 @@
3
3
 
4
4
  module Metanorma
5
5
  class Processor
6
-
7
- attr_reader :short
8
- attr_reader :input_format
9
- attr_reader :asciidoctor_backend
6
+ attr_reader :short, :input_format, :asciidoctor_backend
10
7
 
11
8
  def initialize
12
9
  raise "This is an abstract class!"
@@ -16,7 +13,7 @@ module Metanorma
16
13
  {
17
14
  xml: "xml",
18
15
  presentation: "presentation.xml",
19
- rxl: "rxl"
16
+ rxl: "rxl",
20
17
  }
21
18
  end
22
19
 
@@ -36,7 +33,7 @@ module Metanorma
36
33
  end
37
34
  end
38
35
 
39
- def output(isodoc_node, inname, outname, format, options={})
36
+ def output(isodoc_node, _inname, outname, _format, _options = {})
40
37
  File.open(outname, "w:UTF-8") { |f| f.write(isodoc_node) }
41
38
  end
42
39
 
@@ -0,0 +1,270 @@
1
+ require "yaml"
2
+
3
+ module Metanorma
4
+ class Compile
5
+ # assume we pass in Presentation XML, but we want to recover Semantic XML
6
+ def sectionsplit_convert(input_filename, file, output_filename = nil,
7
+ opts = {})
8
+ @isodoc = IsoDoc::Convert.new({})
9
+ input_filename += ".xml" unless input_filename.match?(/\.xml$/)
10
+ File.exist?(input_filename) or
11
+ File.open(input_filename, "w:UTF-8") { |f| f.write(file) }
12
+ presxml = File.read(input_filename, encoding: "utf-8")
13
+ @openmathdelim, @closemathdelim = @isodoc.extract_delims(presxml)
14
+ xml, filename, dir = @isodoc.convert_init(presxml, input_filename, false)
15
+ build_collection(xml, presxml, output_filename || filename, dir, opts)
16
+ end
17
+
18
+ def ns(xpath)
19
+ @isodoc.ns(xpath)
20
+ end
21
+
22
+ def build_collection(xml, presxml, filename, dir, opts = {})
23
+ base = File.basename(filename)
24
+ collection_setup(base, dir)
25
+ files = sectionsplit(xml, base, dir)
26
+ collection_manifest(base, files, xml, presxml, dir).render(
27
+ { format: %i(html), output_folder: "#{filename}_collection",
28
+ coverpage: File.join(dir, "cover.html") }.merge(opts),
29
+ )
30
+ end
31
+
32
+ def collection_manifest(filename, files, origxml, _presxml, dir)
33
+ File.open(File.join(dir, "#{filename}.html.yaml"), "w:UTF-8") do |f|
34
+ f.write(collectionyaml(files, origxml))
35
+ end
36
+ Metanorma::Collection.parse File.join(dir, "#{filename}.html.yaml")
37
+ end
38
+
39
+ def collection_setup(filename, dir)
40
+ FileUtils.mkdir_p "#{filename}_collection" if filename
41
+ FileUtils.mkdir_p dir
42
+ File.open(File.join(dir, "cover.html"), "w:UTF-8") do |f|
43
+ f.write(coll_cover)
44
+ end
45
+ end
46
+
47
+ def coll_cover
48
+ <<~COVER
49
+ <html>
50
+ <head/>
51
+ <body>
52
+ <h1>{{ doctitle }}</h1>
53
+ <h2>{{ docnumber }}</h2>
54
+ <nav>{{ labels["navigation"] }}</nav>
55
+ </body>
56
+ </html>
57
+ COVER
58
+ end
59
+
60
+ SPLITSECTIONS =
61
+ [["//preface/*", "preface"], ["//sections/*", "sections"],
62
+ ["//annex", nil],
63
+ ["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
64
+ ["//indexsect", nil]].freeze
65
+
66
+ def sectionsplit(xml, filename, dir)
67
+ @key = xref_preprocess(xml)
68
+ @splitdir = dir
69
+ out = emptydoc(xml)
70
+ SPLITSECTIONS.each_with_object([]) do |n, ret|
71
+ xml.xpath(ns(n[0])).each do |s|
72
+ ret << sectionfile(xml, out, "#{filename}.#{ret.size}", s, n[1])
73
+ end
74
+ end
75
+ end
76
+
77
+ def emptydoc(xml)
78
+ out = xml.dup
79
+ out.xpath(
80
+ ns("//preface | //sections | //annex | //bibliography/clause | "\
81
+ "//bibliography/references[not(@hidden = 'true')] | //indexsect"),
82
+ ).each(&:remove)
83
+ out
84
+ end
85
+
86
+ def sectionfile(fulldoc, xml, file, chunk, parentnode)
87
+ fname = create_sectionfile(fulldoc, xml.dup, file, chunk, parentnode)
88
+ { order: chunk["displayorder"].to_i, url: fname,
89
+ title: titlerender(chunk) }
90
+ end
91
+
92
+ def create_sectionfile(xml, out, file, chunk, parentnode)
93
+ ins = out.at(ns("//misccontainer")) || out.at(ns("//bibdata"))
94
+ if parentnode
95
+ ins.next = "<#{parentnode}/>"
96
+ ins.next.add_child(chunk.dup)
97
+ else ins.next = chunk.dup
98
+ end
99
+ xref_process(out, xml, @key)
100
+ outname = "#{file}.xml"
101
+ File.open(File.join(@splitdir, outname), "w:UTF-8") { |f| f.write(out) }
102
+ outname
103
+ end
104
+
105
+ # def xref_preprocess(xml)
106
+ # svg_preprocess(xml)
107
+ # key = (0...8).map { rand(65..90).chr }.join # random string
108
+ # xml.root["type"] = key # to force recognition of internal refs
109
+ # refs = eref_to_internal_eref(xml, key)
110
+ # refs += xref_to_internal_eref(xml, key)
111
+ # ins = new_hidden_ref(xml)
112
+ # copy_repo_items_biblio(ins, xml)
113
+ # insert_indirect_biblio(ins, refs, key)
114
+ # end
115
+
116
+ def xref_preprocess(xml)
117
+ svg_preprocess(xml)
118
+ key = (0...8).map { rand(65..90).chr }.join # random string
119
+ xml.root["type"] = key # to force recognition of internal refs
120
+ key
121
+ end
122
+
123
+ def xref_process(section, xml, key)
124
+ refs = eref_to_internal_eref(section, xml, key)
125
+ refs += xref_to_internal_eref(section, key)
126
+ ins = new_hidden_ref(section)
127
+ copied_refs = copy_repo_items_biblio(ins, section, xml)
128
+ insert_indirect_biblio(ins, refs - copied_refs, key)
129
+ end
130
+
131
+ def svg_preprocess(xml)
132
+ xml.xpath("//m:svg", "m" => "http://www.w3.org/2000/svg").each do |s|
133
+ m = svgmap_wrap(s)
134
+ s.xpath(".//m:a", "m" => "http://www.w3.org/2000/svg").each do |a|
135
+ next unless /^#/.match? a["href"]
136
+
137
+ a["href"] = a["href"].sub(/^#/, "")
138
+ m << "<target href='#{a['href']}'>"\
139
+ "<xref target='#{a['href']}'/></target>"
140
+ end
141
+ end
142
+ end
143
+
144
+ def svgmap_wrap(svg)
145
+ ret = svg.at("./ancestor::xmlns:svgmap") and return ret
146
+ ret = svg.at("./ancestor::xmlns:figure")
147
+ ret.wrap("<svgmap/>")
148
+ svg.at("./ancestor::xmlns:svgmap")
149
+ end
150
+
151
+ def make_anchor(anchor)
152
+ "<localityStack><locality type='anchor'><referenceFrom>"\
153
+ "#{anchor}</referenceFrom></locality></localityStack>"
154
+ end
155
+
156
+ def xref_to_internal_eref(xml, key)
157
+ xml.xpath(ns("//xref")).each_with_object({}) do |x, m|
158
+ x["bibitemid"] = "#{key}_#{x['target']}"
159
+ x << make_anchor(x["target"])
160
+ m[x["bibitemid"]] = true
161
+ x.delete("target")
162
+ x["type"] = key
163
+ x.name = "eref"
164
+ end.keys
165
+ end
166
+
167
+ def eref_to_internal_eref(section, xml, key)
168
+ eref_to_internal_eref_select(section, xml).each_with_object([]) do |x, m|
169
+ url = xml.at(ns("//bibitem[@id = '#{x}']/url[@type = 'citation']"))
170
+ section.xpath(("//*[@bibitemid = '#{x}']")).each do |e|
171
+ id = eref_to_internal_eref1(e, key, url)
172
+ id and m << id
173
+ end
174
+ end
175
+ end
176
+
177
+ def eref_to_internal_eref1(elem, key, url)
178
+ if url
179
+ elem.name = "link"
180
+ elem["target"] = url
181
+ nil
182
+ else
183
+ elem["bibitemid"] = "#{key}_#{elem['bibitemid']}"
184
+ elem << make_anchor(elem["bibitemid"])
185
+ elem["type"] = key
186
+ elem["bibitemid"]
187
+ end
188
+ end
189
+
190
+ def eref_to_internal_eref_select(section, xml)
191
+ refs = section.xpath(("//*/@bibitemid")).map { |x| x.text } # rubocop:disable Style/SymbolProc
192
+ refs.uniq.reject do |x|
193
+ xml.at(ns("//bibitem[@id = '#{x}'][@type = 'internal']")) ||
194
+ xml.at(ns("//bibitem[@id = '#{x}']"\
195
+ "[docidentifier/@type = 'repository']"))
196
+ end
197
+ end
198
+
199
+ # from standoc
200
+ def new_hidden_ref(xmldoc)
201
+ ins = xmldoc.at("bibliography") or
202
+ xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography")
203
+ ins.add_child("<references hidden='true' normative='false'/>").first
204
+ end
205
+
206
+ def copy_repo_items_biblio(ins, section, xml)
207
+ xml.xpath(ns("//references/bibitem[docidentifier/@type = 'repository']"))
208
+ .each_with_object([]) do |b, m|
209
+ section.at("//*[@bibitemid = '#{b['id']}']") or next
210
+ ins << b.dup
211
+ m << b["id"]
212
+ end
213
+ end
214
+
215
+ def insert_indirect_biblio(ins, refs, prefix)
216
+ refs.each do |x|
217
+ ins << <<~BIBENTRY
218
+ <bibitem id="#{x}" type="internal">
219
+ <docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
220
+ </bibitem>
221
+ BIBENTRY
222
+ end
223
+ end
224
+
225
+ def recursive_string_keys(hash)
226
+ case hash
227
+ when Hash then Hash[
228
+ hash.map { |k, v| [k.to_s, recursive_string_keys(v)] }
229
+ ]
230
+ when Enumerable then hash.map { |v| recursive_string_keys(v) }
231
+ else
232
+ hash
233
+ end
234
+ end
235
+
236
+ def titlerender(section)
237
+ title = section.at(ns("./title")) or return "[Untitled]"
238
+ t = title.dup
239
+ t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") }
240
+ t.xpath(ns(".//strong")).each { |x| x.replace(x.children) }
241
+ t.children.to_xml
242
+ end
243
+
244
+ def collectionyaml(files, xml)
245
+ ret = {
246
+ directives: ["presentation-xml", "bare-after-first"],
247
+ bibdata: {
248
+ title: {
249
+ type: "title-main",
250
+ language: @lang,
251
+ content: xml.at(ns("//bibdata/title")).text,
252
+ },
253
+ type: "collection",
254
+ docid: {
255
+ type: xml.at(ns("//bibdata/docidentifier/@type")).text,
256
+ id: xml.at(ns("//bibdata/docidentifier")).text,
257
+ },
258
+ },
259
+ manifest: {
260
+ level: "collection",
261
+ title: "Collection",
262
+ docref: files.sort_by { |f| f[:order] }.each.map do |f|
263
+ { fileref: f[:url], identifier: f[:title] }
264
+ end,
265
+ },
266
+ }
267
+ recursive_string_keys(ret).to_yaml
268
+ end
269
+ end
270
+ end
@@ -12,8 +12,49 @@ module Metanorma
12
12
  end
13
13
  end
14
14
 
15
- def self.source2dest_filename(name)
16
- name.sub(%r{^(\./)?(\.\./)+}, "")
15
+ # dependency ordering
16
+ def self.sort_extensions_execution_ord(ext)
17
+ case ext
18
+ when :xml then 0
19
+ when :rxl then 1
20
+ when :presentation then 2
21
+ else
22
+ 99
23
+ end
24
+ end
25
+
26
+ def self.sort_extensions_execution(ext)
27
+ ext.sort do |a, b|
28
+ sort_extensions_execution_ord(a) <=> sort_extensions_execution_ord(b)
29
+ end
30
+ end
31
+
32
+ class DisambigFiles
33
+ def initialize
34
+ @seen_filenames = []
35
+ end
36
+
37
+ def source2dest_filename(name, disambig = true)
38
+ n = name.sub(%r{^(\./)?(\.\./)+}, "")
39
+ dir = File.dirname(n)
40
+ base = File.basename(n)
41
+ if disambig && @seen_filenames.include?(base)
42
+ base = disambiguate_filename(base)
43
+ end
44
+ @seen_filenames << base
45
+ dir == "." ? base : File.join(dir, base)
46
+ end
47
+
48
+ def disambiguate_filename(base)
49
+ m = /^(?<start>.+\.)(?!0)(?<num>\d+)\.(?<suff>[^.]*)$/.match(base) ||
50
+ /^(?<start>.+\.)(?<suff>[^.]*)/.match(base) ||
51
+ /^(?<start>.+)$/.match(base)
52
+ i = m.names.include?("num") ? m["num"].to_i + 1 : 1
53
+ while @seen_filenames.include? base = "#{m['start']}#{i}.#{m['suff']}"
54
+ i += 1
55
+ end
56
+ base
57
+ end
17
58
  end
18
59
  end
19
60
  end
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "1.3.4".freeze
2
+ VERSION = "1.3.8".freeze
3
3
  end
data/metanorma.gemspec CHANGED
@@ -20,10 +20,10 @@ Gem::Specification.new do |spec|
20
20
  spec.bindir = "bin"
21
21
  # spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
- spec.required_ruby_version = ">= 2.4.0"
23
+ spec.required_ruby_version = ">= 2.5.0"
24
24
 
25
25
  spec.add_runtime_dependency "asciidoctor"
26
- spec.add_runtime_dependency "fontist", "~> 1.8"
26
+ spec.add_runtime_dependency "fontist", "~> 1.9.0"
27
27
  spec.add_runtime_dependency "htmlentities"
28
28
  spec.add_runtime_dependency "metanorma-utils", "~> 1.2.0"
29
29
  spec.add_runtime_dependency "mn2pdf", "~> 1"
@@ -36,10 +36,11 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.add_development_dependency "byebug", "~> 10.0"
38
38
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
39
- spec.add_development_dependency "metanorma-iso", "~> 1.8.0"
39
+ spec.add_development_dependency "metanorma-iso", "~> 1.9.0"
40
40
  spec.add_development_dependency "rake", "~> 13.0"
41
41
  spec.add_development_dependency "rspec", "~> 3.0"
42
42
  spec.add_development_dependency "rspec-command", "~> 1.0"
43
43
  spec.add_development_dependency "rubocop", "~> 1.5.2"
44
44
  spec.add_development_dependency "sassc", "~> 2.4.0"
45
+ spec.add_development_dependency "mnconvert"
45
46
  end