metanorma 1.7.7 → 2.0.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -1
  3. data/lib/metanorma/array_monkeypatch.rb +9 -0
  4. data/lib/metanorma/asciidoctor_extensions/glob_include_processor.rb +13 -11
  5. data/lib/metanorma/collection/collection.rb +226 -0
  6. data/lib/metanorma/collection/config/bibdata.rb +12 -0
  7. data/lib/metanorma/collection/config/compile_options.rb +13 -0
  8. data/lib/metanorma/collection/config/config.rb +163 -0
  9. data/lib/metanorma/collection/config/converters.rb +30 -0
  10. data/lib/metanorma/collection/config/directive.rb +10 -0
  11. data/lib/metanorma/collection/config/manifest.rb +88 -0
  12. data/lib/metanorma/collection/document/document.rb +133 -0
  13. data/lib/metanorma/collection/filelookup/filelookup.rb +250 -0
  14. data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +87 -0
  15. data/lib/metanorma/collection/manifest/manifest.rb +237 -0
  16. data/lib/metanorma/collection/renderer/fileparse.rb +254 -0
  17. data/lib/metanorma/collection/renderer/fileprocess.rb +174 -0
  18. data/lib/metanorma/collection/renderer/navigation.rb +133 -0
  19. data/lib/metanorma/collection/renderer/render_word.rb +133 -0
  20. data/lib/metanorma/collection/renderer/renderer.rb +157 -0
  21. data/lib/metanorma/collection/renderer/utils.rb +211 -0
  22. data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +219 -0
  23. data/lib/metanorma/collection/util/disambig_files.rb +37 -0
  24. data/lib/metanorma/collection/util/util.rb +72 -0
  25. data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +222 -0
  26. data/lib/metanorma/{compile.rb → compile/compile.rb} +19 -12
  27. data/lib/metanorma/{compile_options.rb → compile/compile_options.rb} +9 -5
  28. data/lib/metanorma/{compile_validate.rb → compile/compile_validate.rb} +1 -1
  29. data/lib/metanorma/{extract.rb → compile/extract.rb} +2 -2
  30. data/lib/metanorma/{config.rb → config/config.rb} +1 -1
  31. data/lib/metanorma/input/asciidoc.rb +3 -3
  32. data/lib/metanorma/input/base.rb +1 -5
  33. data/lib/metanorma/processor/processor.rb +54 -0
  34. data/lib/metanorma/processor.rb +1 -49
  35. data/lib/metanorma/{registry.rb → registry/registry.rb} +0 -1
  36. data/lib/metanorma/shale_monkeypatch.rb +15 -0
  37. data/lib/metanorma/util/fontist_helper.rb +130 -0
  38. data/lib/metanorma/util/util.rb +45 -0
  39. data/lib/metanorma/util/worker_pool.rb +39 -0
  40. data/lib/metanorma/version.rb +1 -1
  41. data/lib/metanorma.rb +13 -8
  42. data/metanorma.gemspec +2 -1
  43. metadata +50 -24
  44. data/lib/metanorma/collection.rb +0 -244
  45. data/lib/metanorma/collection_fileparse.rb +0 -257
  46. data/lib/metanorma/collection_fileprocess.rb +0 -168
  47. data/lib/metanorma/collection_manifest.rb +0 -168
  48. data/lib/metanorma/collection_render_utils.rb +0 -169
  49. data/lib/metanorma/collection_render_word.rb +0 -131
  50. data/lib/metanorma/collection_renderer.rb +0 -237
  51. data/lib/metanorma/collection_xref_process.rb +0 -217
  52. data/lib/metanorma/document.rb +0 -133
  53. data/lib/metanorma/files_lookup.rb +0 -224
  54. data/lib/metanorma/files_lookup_sectionsplit.rb +0 -84
  55. data/lib/metanorma/fontist_utils.rb +0 -122
  56. data/lib/metanorma/sectionsplit.rb +0 -216
  57. data/lib/metanorma/util.rb +0 -127
  58. data/lib/metanorma/worker_pool.rb +0 -29
@@ -1,122 +0,0 @@
1
- module Metanorma
2
- class FontistUtils
3
- class << self
4
- private
5
-
6
- def validate_options(options)
7
- agree_to_terms = options[:agree_to_terms] || false
8
- continue_without_fonts = options[:continue_without_fonts] || false
9
- no_progress = options[:no_progress] || false
10
-
11
- [agree_to_terms, continue_without_fonts, no_progress]
12
- end
13
-
14
- def validate_install_fonts(processor, options)
15
- if options[:no_install_fonts]
16
- Util.log("[fontist] Skip font installation because" \
17
- " --no-install-fonts argument passed", :debug)
18
- return false
19
- elsif !has_custom_fonts?(processor, options, options)
20
- Util.log("[fontist] Skip font installation because "\
21
- "fonts_manifest is missing", :debug)
22
- return false
23
- end
24
- true
25
- end
26
-
27
- def install_fonts_safe(manifest, agree, continue, no_progress)
28
- fontist_install(manifest, agree, no_progress)
29
- rescue Fontist::Errors::LicensingError
30
- license_error_log(continue)
31
- rescue Fontist::Errors::FontError => e
32
- log_level = continue ? :warning : :fatal
33
- Util.log("[fontist] '#{e.font}' font is not supported. " \
34
- "Please report this issue at github.com/metanorma/metanorma" \
35
- "/issues to report this issue.", log_level)
36
- rescue Fontist::Errors::FormulaIndexNotFoundError
37
- fintist_update_repo(manifest, agree, continue, no_progress)
38
- end
39
-
40
- def fontist_install(manifest, agree, no_progress)
41
- if agree
42
- no_license_log
43
- else
44
- Fontist.log_level = :info
45
- end
46
-
47
- Fontist::Manifest::Install.from_hash(
48
- manifest,
49
- confirmation: agree ? "yes" : "no",
50
- no_progress: no_progress,
51
- )
52
- end
53
-
54
- def license_error_log(continue)
55
- if continue
56
- Util.log(
57
- "[fontist] Processing will continue without fonts installed",
58
- :debug,
59
- )
60
- else
61
- Util.log("[fontist] Aborting without proper fonts installed," \
62
- " make sure that you have set option --agree-to-terms",
63
- :fatal)
64
- end
65
- end
66
-
67
- def no_license_log
68
- Util.log(
69
- "[fontist] Font licenses are not shown with --agree-to-terms option.",
70
- :info,
71
- )
72
- end
73
-
74
- def fintist_update_repo(manifest, agree, continue, no_progress)
75
- if @@updated_formulas_repo
76
- Util.log(
77
- "[fontist] Bug: formula index not found after 'fontist update'",
78
- :fatal,
79
- )
80
- end
81
- Util.log("[fontist] Missing formula index. Fetching it...", :debug)
82
- Fontist::Formula.update_formulas_repo
83
- @@updated_formulas_repo = true
84
- install_fonts_safe(manifest, agree, continue, no_progress)
85
- end
86
- end
87
-
88
- def self.install_fonts(processor, options)
89
- return unless validate_install_fonts(processor, options)
90
-
91
- @@updated_formulas_repo = false
92
- manifest = processor.fonts_manifest.dup
93
- append_source_fonts(manifest, options)
94
- agree_to_terms, can_without_fonts, no_progress = validate_options(options)
95
-
96
- install_fonts_safe(
97
- manifest,
98
- agree_to_terms,
99
- can_without_fonts,
100
- no_progress,
101
- )
102
- end
103
-
104
- def self.has_custom_fonts?(processor, options, source_attributes)
105
- !options[:no_install_fonts] \
106
- && processor.respond_to?(:fonts_manifest) \
107
- && !processor.fonts_manifest.nil? \
108
- || source_attributes[:fonts]
109
- end
110
-
111
- def self.location_manifest(processor, source_attributes)
112
- Fontist::Manifest::Locations.from_hash(
113
- append_source_fonts(processor.fonts_manifest.dup, source_attributes),
114
- )
115
- end
116
-
117
- def self.append_source_fonts(manifest, source_attributes)
118
- source_attributes[:fonts]&.split(";")&.each { |f| manifest[f] = nil }
119
- manifest
120
- end
121
- end
122
- end
@@ -1,216 +0,0 @@
1
- require "yaml"
2
- require_relative "util"
3
- require_relative "collection_xref_process"
4
-
5
- module Metanorma
6
- class Sectionsplit
7
- attr_accessor :filecache, :key
8
-
9
- def initialize(opts)
10
- @input_filename = opts[:input]
11
- @base = opts[:base]
12
- @output_filename = opts[:output]
13
- @xml = opts[:xml]
14
- @dir = opts[:dir]
15
- @compile_opts = opts[:compile_opts] || {}
16
- @fileslookup = opts[:fileslookup]
17
- @ident = opts[:ident]
18
- @isodoc = opts[:isodoc]
19
- end
20
-
21
- def ns(xpath)
22
- @isodoc.ns(xpath)
23
- end
24
-
25
- def build_collection
26
- collection_setup(@base, @dir)
27
- files = sectionsplit # (@input_filename, @base, @dir, @compile_opts)
28
- input_xml = Nokogiri::XML(File.read(@input_filename,
29
- encoding: "UTF-8"), &:huge)
30
- collection_manifest(@base, files, input_xml, @xml, @dir).render(
31
- { format: %i(html), output_folder: "#{@output_filename}_collection",
32
- coverpage: File.join(@dir, "cover.html") }.merge(@compile_opts),
33
- )
34
- end
35
-
36
- def collection_manifest(filename, files, origxml, _presxml, dir)
37
- File.open(File.join(dir, "#{filename}.html.yaml"), "w:UTF-8") do |f|
38
- f.write(collectionyaml(files, origxml))
39
- end
40
- Metanorma::Collection.parse File.join(dir, "#{filename}.html.yaml")
41
- end
42
-
43
- def collection_setup(filename, dir)
44
- FileUtils.mkdir_p "#{filename}_collection" if filename
45
- FileUtils.mkdir_p dir
46
- File.open(File.join(dir, "cover.html"), "w:UTF-8") do |f|
47
- f.write(coll_cover)
48
- end
49
- end
50
-
51
- def coll_cover
52
- <<~COVER
53
- <html><head><meta charset="UTF-8"/></head><body>
54
- <h1>{{ doctitle }}</h1>
55
- <h2>{{ docnumber }}</h2>
56
- <nav>{{ navigation }}</nav>
57
- </body></html>
58
- COVER
59
- end
60
-
61
- SPLITSECTIONS =
62
- [["//preface/*", "preface"], ["//sections/*", "sections"],
63
- ["//annex", nil],
64
- ["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
65
- ["//indexsect", nil], ["//colophon", nil]].freeze
66
-
67
- # Input XML is Semantic
68
- # def sectionsplit(filename, basename, dir, compile_options, fileslookup = nil, ident = nil)
69
- def sectionsplit
70
- xml = sectionsplit_prep(File.read(@input_filename), @base, @dir)
71
- @key = Metanorma::XrefProcess::xref_preprocess(xml, @isodoc)
72
- SPLITSECTIONS.each_with_object([]) do |n, ret|
73
- conflate_floatingtitles(xml.xpath(ns(n[0]))).each do |s|
74
- ret << sectionfile(xml, emptydoc(xml), "#{@base}.#{ret.size}", s,
75
- n[1])
76
- end
77
- end
78
- end
79
-
80
- def block?(node)
81
- %w(p table formula admonition ol ul dl figure quote sourcecode example
82
- pre note pagebrreak hr bookmark requirement recommendation permission
83
- svgmap inputform toc passthrough review imagemap).include?(node.name)
84
- end
85
-
86
- def conflate_floatingtitles(nodes)
87
- holdover = false
88
- nodes.each_with_object([]) do |x, m|
89
- if holdover then m.last << x
90
- else m << [x]
91
- end
92
- holdover = block?(x)
93
- end
94
- end
95
-
96
- def sectionsplit_prep(file, filename, dir)
97
- @splitdir = dir
98
- xml1filename, type = sectionsplit_preprocess_semxml(file, filename)
99
- Compile.new.compile(
100
- xml1filename,
101
- { format: :asciidoc, extension_keys: [:presentation], type: type }
102
- .merge(@compile_opts),
103
- )
104
- Nokogiri::XML(File.read(xml1filename.sub(/\.xml$/, ".presentation.xml"),
105
- encoding: "utf-8"), &:huge)
106
- end
107
-
108
- def sectionsplit_preprocess_semxml(file, filename)
109
- xml = Nokogiri::XML(file, &:huge)
110
- type = xml.root.name.sub("-standard", "").to_sym
111
- sectionsplit_update_xrefs(xml)
112
- xml1 = sectionsplit_write_semxml(filename, xml)
113
- @filecache ||= []
114
- @filecache << xml1
115
- [xml1.path, type]
116
- end
117
-
118
- def sectionsplit_update_xrefs(xml)
119
- if c = @fileslookup&.parent
120
- n = c.nested
121
- c.nested = true # so unresolved erefs are not deleted
122
- c.update_xrefs(xml, @ident, {})
123
- c.nested = n
124
- end
125
- end
126
-
127
- def sectionsplit_write_semxml(filename, xml)
128
- Tempfile.open([filename, ".xml"], encoding: "utf-8") do |f|
129
- # f.write(@isodoc.to_xml(svg_preprocess(xml)))
130
- f.write(@isodoc.to_xml(xml))
131
- f
132
- end
133
- end
134
-
135
- def emptydoc(xml)
136
- out = xml.dup
137
- out.xpath(
138
- ns("//preface | //sections | //annex | //bibliography/clause | " \
139
- "//bibliography/references[not(@hidden = 'true')] | //indexsect | " \
140
- "//colophon"),
141
- ).each(&:remove)
142
- out
143
- end
144
-
145
- def sectionfile(fulldoc, xml, file, chunks, parentnode)
146
- fname = create_sectionfile(fulldoc, xml.dup, file, chunks, parentnode)
147
- { order: chunks.last["displayorder"].to_i, url: fname,
148
- title: titlerender(chunks.last) }
149
- end
150
-
151
- def create_sectionfile(xml, out, file, chunks, parentnode)
152
- ins = out.at(ns("//metanorma-extension")) || out.at(ns("//bibdata"))
153
- sectionfile_insert(ins, chunks, parentnode)
154
- Metanorma::XrefProcess::xref_process(out, xml, @key, @ident, @isodoc)
155
- outname = "#{file}.xml"
156
- File.open(File.join(@splitdir, outname), "w:UTF-8") do |f|
157
- f.write(out)
158
- end
159
- outname
160
- end
161
-
162
- def sectionfile_insert(ins, chunks, parentnode)
163
- if parentnode
164
- ins.next = "<#{parentnode}/>"
165
- chunks.each { |c| ins.next.add_child(c.dup) }
166
- else chunks.each { |c| ins.next = c.dup }
167
- end
168
- end
169
-
170
- def titlerender(section)
171
- title = section.at(ns("./title")) or return "[Untitled]"
172
- t = title.dup
173
- t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") }
174
- t.xpath(ns(".//strong")).each { |x| x.replace(x.children) }
175
- t.children.to_xml
176
- end
177
-
178
- def collectionyaml(files, xml)
179
- ret = {
180
- directives: ["presentation-xml", "bare-after-first"],
181
- bibdata: {
182
- title: {
183
- type: "title-main", language: @lang,
184
- content: xml.at(ns("//bibdata/title")).text
185
- },
186
- type: "collection",
187
- docid: {
188
- type: xml.at(ns("//bibdata/docidentifier/@type")).text,
189
- id: xml.at(ns("//bibdata/docidentifier")).text,
190
- },
191
- },
192
- manifest: {
193
- level: "collection", title: "Collection",
194
- docref: files.sort_by { |f| f[:order] }.each.map do |f|
195
- { fileref: f[:url], identifier: f[:title] }
196
- end
197
- },
198
- }
199
- Util::recursive_string_keys(ret).to_yaml
200
- end
201
-
202
- def section_split_cover(col, ident, one_doc_coll)
203
- dir = File.dirname(col.file)
204
- collection_setup(nil, dir)
205
- CollectionRenderer.new(col, dir,
206
- output_folder: "#{ident}_collection",
207
- format: %i(html),
208
- coverpage: File.join(dir, "cover.html")).coverpage
209
- #filename = one_doc_coll ? "#{ident}_index.html" : "index.html"
210
- filename = "#{ident}_index.html"
211
- FileUtils.mv "#{ident}_collection/index.html", File.join(dir, filename)
212
- FileUtils.rm_rf "#{ident}_collection"
213
- filename
214
- end
215
- end
216
- end
@@ -1,127 +0,0 @@
1
- module Metanorma
2
- module Util
3
- def self.log(message, type = :info)
4
- log_types = Metanorma.configuration.logs.map(&:to_s) || []
5
-
6
- if log_types.include?(type.to_s)
7
- puts(message)
8
- end
9
-
10
- if type == :fatal
11
- exit(1)
12
- end
13
- end
14
-
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
- def self.recursive_string_keys(hash)
33
- case hash
34
- when Hash then hash.map { |k, v| [k.to_s, recursive_string_keys(v)] }.to_h
35
- when Enumerable then hash.map { |v| recursive_string_keys(v) }
36
- else
37
- hash
38
- end
39
- end
40
-
41
- def self.gather_bibitems(xml)
42
- xml.xpath("//xmlns:bibitem[@id]").each_with_object({}) do |b, m|
43
- if m[b["id"]]
44
- b.remove
45
- next # we can't update duplicate bibitem, processing updates wrong one
46
- else
47
- m[b["id"]] = b
48
- end
49
- end
50
- end
51
-
52
- def self.gather_bibitemids(xml)
53
- xml.xpath("//*[@bibitemid]").each_with_object({}) do |e, m|
54
- /^semantic__/.match?(e.name) and next
55
- m[e["bibitemid"]] ||= []
56
- m[e["bibitemid"]] << e
57
- end
58
- end
59
-
60
- def self.gather_citeases(xml)
61
- xml.xpath("//*[@citeas]").each_with_object({}) do |e, m|
62
- /^semantic__/.match?(e.name) and next
63
- m[e["citeas"]] ||= []
64
- m[e["citeas"]] << e
65
- end
66
- end
67
-
68
- def self.add_suffix_to_attributes(doc, suffix, tag_name, attr_name, isodoc)
69
- (suffix.nil? || suffix.empty?) and return
70
- doc.xpath(isodoc.ns("//#{tag_name}[@#{attr_name}]")).each do |elem|
71
- a = elem.attributes[attr_name].value
72
- /_#{suffix}$/.match?(a) or
73
- elem.attributes[attr_name].value = "#{a}_#{suffix}"
74
- end
75
- end
76
-
77
- def self.hash_key_detect(directives, key, variable)
78
- c = directives.detect { |x| x.is_a?(Hash) && x.has_key?(key) } or
79
- return variable
80
- c[key]
81
- end
82
-
83
- def self.rel_path_resolve(dir, path)
84
- path.nil? and return path
85
- path.empty? and return path
86
- p = Pathname.new(path)
87
- p.absolute? ? path : File.join(dir, path)
88
- end
89
-
90
- def self.key(ident)
91
- @c ||= HTMLEntities.new
92
- @c.decode(ident).gsub(/(\p{Zs})+/, " ")
93
- end
94
-
95
- class DisambigFiles
96
- def initialize
97
- @seen_filenames = []
98
- end
99
-
100
- def strip_root(name)
101
- name.sub(%r{^(\./)?(\.\./)+}, "")
102
- end
103
-
104
- def source2dest_filename(name, disambig = true)
105
- n = strip_root(name)
106
- dir = File.dirname(n)
107
- base = File.basename(n)
108
- if disambig && @seen_filenames.include?(base)
109
- base = disambiguate_filename(base)
110
- end
111
- @seen_filenames << base
112
- dir == "." ? base : File.join(dir, base)
113
- end
114
-
115
- def disambiguate_filename(base)
116
- m = /^(?<start>.+\.)(?!0)(?<num>\d+)\.(?<suff>[^.]*)$/.match(base) ||
117
- /^(?<start>.+\.)(?<suff>[^.]*)/.match(base) ||
118
- /^(?<start>.+)$/.match(base)
119
- i = m.names.include?("num") ? m["num"].to_i + 1 : 1
120
- while @seen_filenames.include? base = "#{m['start']}#{i}.#{m['suff']}"
121
- i += 1
122
- end
123
- base
124
- end
125
- end
126
- end
127
- end
@@ -1,29 +0,0 @@
1
- module Metanorma
2
- class WorkersPool
3
- def initialize(workers)
4
- @workers = workers
5
- @queue = SizedQueue.new(@workers)
6
- @threads = Array.new(@workers) do
7
- Thread.new do
8
- catch(:exit) do
9
- loop do
10
- job, args = @queue.pop
11
- job.call *args
12
- end
13
- end
14
- end
15
- end
16
- end
17
-
18
- def schedule(*args, &block)
19
- @queue << [block, args]
20
- end
21
-
22
- def shutdown
23
- @workers.times do
24
- schedule { throw :exit }
25
- end
26
- @threads.map(&:join)
27
- end
28
- end
29
- end