metanorma 2.3.0 → 2.3.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 (33) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +14 -0
  3. data/lib/metanorma/collection/collection.rb +46 -105
  4. data/lib/metanorma/collection/config/config.rb +5 -0
  5. data/lib/metanorma/collection/config/converters.rb +1 -0
  6. data/lib/metanorma/collection/config/manifest.rb +23 -0
  7. data/lib/metanorma/collection/document/document.rb +32 -10
  8. data/lib/metanorma/collection/filelookup/base.rb +43 -0
  9. data/lib/metanorma/collection/filelookup/filelookup.rb +168 -69
  10. data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +49 -10
  11. data/lib/metanorma/collection/filelookup/utils.rb +93 -0
  12. data/lib/metanorma/collection/helpers.rb +82 -0
  13. data/lib/metanorma/collection/manifest/manifest.rb +14 -3
  14. data/lib/metanorma/collection/multilingual/multilingual.rb +1 -1
  15. data/lib/metanorma/collection/renderer/filelocation.rb +162 -0
  16. data/lib/metanorma/collection/renderer/fileparse.rb +9 -6
  17. data/lib/metanorma/collection/renderer/fileprocess.rb +56 -42
  18. data/lib/metanorma/collection/renderer/navigation.rb +15 -1
  19. data/lib/metanorma/collection/renderer/render_word.rb +8 -4
  20. data/lib/metanorma/collection/renderer/renderer.rb +104 -10
  21. data/lib/metanorma/collection/renderer/svg.rb +54 -7
  22. data/lib/metanorma/collection/renderer/utils.rb +58 -22
  23. data/lib/metanorma/collection/sectionsplit/collection.rb +14 -5
  24. data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +20 -7
  25. data/lib/metanorma/collection/util/disambig_files.rb +4 -5
  26. data/lib/metanorma/collection/util/util.rb +106 -6
  27. data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +2 -2
  28. data/lib/metanorma/compile/compile_options.rb +3 -2
  29. data/lib/metanorma/compile/flavor.rb +11 -4
  30. data/lib/metanorma/compile/render.rb +1 -0
  31. data/lib/metanorma/version.rb +1 -1
  32. data/metanorma.gemspec +4 -14
  33. metadata +28 -150
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0b38bef2506229ec98ad17d482c5b1fff15bf21d159833393a54dc19842a501
4
- data.tar.gz: 8e6b6a5f689f5b37379bf80d2d987ac2d2cfe28d2b5a678069b90fbf79628ff2
3
+ metadata.gz: 19c34c2ef752fa708266aa2ace4d50d685ddd1c6089425988c44a6bd597c1c1c
4
+ data.tar.gz: 96b255a5cee296cfce50666c4a9e5f90807c61a2242626d60335e33d435d5570
5
5
  SHA512:
6
- metadata.gz: e98a37c21f6741a3d59c765947a6f589938b44e11120a066ebac4fa1919aa00fb32fdb4f812a6bed66a1db88207df673c2361ac4b32889bd0ca25d106b0904e4
7
- data.tar.gz: ee81239a3a28c45650b5a2770609a029e31be0f36cba332b9e5d2cacd5845149a8fa986e2aee8d8461e8d61e5f4ce2aec50b4715dae1fab23ef989128e49d40d
6
+ metadata.gz: 34240a210ea5f8570f4d3cc422f6fe6e42884dbfef72efb9f19c3087ded496230c5be8565e2d9f3ba2d42d5d7b991da75bad1fa637cc433c5893b86ee41888cb
7
+ data.tar.gz: eba23b08ef0b0eeb3ea6753bd73695ad84702d1ce5a7f1059f480873989f500e30ccd70bd8318f7570429e8d7f13ca6b4d2d4e6fe413c2bfd3799820472039ca
data/Gemfile CHANGED
@@ -11,3 +11,17 @@ begin
11
11
  rescue StandardError
12
12
  nil
13
13
  end
14
+
15
+ gem "debug"
16
+ gem "equivalent-xml"
17
+ #gem "metanorma-iho"
18
+ #gem "metanorma-iso", ">= 3.2.0"
19
+ gem "mnconvert"
20
+ gem "pry"
21
+ gem "rake", "~> 13.0"
22
+ gem "rspec", "~> 3.0"
23
+ gem "rspec-command", "~> 1.0"
24
+ gem "rubocop", "~> 1"
25
+ gem "rubocop-performance"
26
+ gem "sassc-embedded", "~> 1"
27
+ gem "simplecov", "~> 0.15"
@@ -4,6 +4,7 @@ require_relative "util/util"
4
4
  require_relative "util/disambig_files"
5
5
  require_relative "config/config"
6
6
  require_relative "config/manifest"
7
+ require_relative "helpers"
7
8
 
8
9
  module Metanorma
9
10
  class FileNotFoundException < StandardError; end
@@ -12,12 +13,13 @@ module Metanorma
12
13
 
13
14
  # Metanorma collection of documents
14
15
  class Collection
15
- attr_reader :file
16
+ attr_reader :file, :prefatory, :final
16
17
 
17
18
  # @return [Array<String>] documents-inline to inject the XML into
18
19
  # the collection manifest; documents-external to keeps them outside
19
- attr_accessor :directives, :documents, :bibdatas, :coverpage, :dirname
20
- attr_accessor :disambig, :manifest, :bibdata, :compile, :config
20
+ attr_accessor :directives, :documents, :bibdatas, :coverpage,
21
+ :coverpage_pdf_portfolio, :dirname,
22
+ :disambig, :manifest, :bibdata, :compile, :config
21
23
 
22
24
  # @param file [String] path to source file
23
25
  # @param config [Metanorma::Collection::Config]
@@ -64,6 +66,7 @@ module Metanorma
64
66
  def initialize_directives
65
67
  d = @directives.each_with_object({}) { |x, m| m[x.key] = x.value }
66
68
  @coverpage = d["coverpage"]
69
+ @coverpage_pdf_portfolio = d["coverpage-pdf-portfolio"]
67
70
  @coverpage_style = d["coverpage-style"]
68
71
  @flavor = d["flavor"]
69
72
  if (@documents.any? || @manifest) && !d.key?("documents-inline") &&
@@ -109,39 +112,55 @@ module Metanorma
109
112
  warn opts[:output_folder]
110
113
  end
111
114
 
112
- # @return [String, nil]
113
- attr_reader :prefatory, :final
114
-
115
- # @return [String]
116
- def dummy_header
117
- <<~DUMMY
118
- = X
119
- A
120
-
121
- DUMMY
122
- end
123
-
124
115
  # @param elm [String] 'prefatory' or 'final'
125
116
  # @param builder [Nokogiri::XML::Builder]
126
117
  def content_to_xml(elm, builder)
127
118
  (cnt = send(elm)) or return
128
- @compile.load_flavor(flavor)
129
- out = sections(dummy_header + cnt.strip)
119
+ @compile.load_flavor(Util::taste2flavor(flavor))
120
+ out = prefatory_parse(Util::asciidoc_dummy_header + cnt.strip)
130
121
  builder.send("#{elm}-content") { |b| b << out }
131
122
  end
132
123
 
133
124
  # @param cnt [String] prefatory/final content
134
125
  # @return [String] XML
135
- def sections(cnt)
136
- c = Asciidoctor.convert(cnt, backend: flavor.to_sym, header_footer: true)
126
+ def prefatory_parse(cnt)
127
+ x = prefatory_parse_semantic(cnt)
128
+ _, filepath = Util::nokogiri_to_temp(x, "foo", ".presentation.xml")
129
+ c1 = Util::isodoc_create(Util::taste2flavor(@flavor), @manifest.lang,
130
+ @manifest.script, x,
131
+ presxml: true).convert(filepath, nil, true)
132
+ presxml = Nokogiri::XML(c1)
133
+ prefatory_extract_xml(presxml)
134
+ end
135
+
136
+ def prefatory_extract_xml(presxml)
137
+ body = presxml.at("//xmlns:sections")
138
+ body.at("//xmlns:p[@class = 'zzSTDTitle1']")&.remove
139
+ body.text.to_s.strip.empty? and body = presxml.at("//xmlns:preface")
140
+ body.at("//xmlns:clause[@type = 'toc']")&.remove
141
+ body.children.to_xml
142
+ end
143
+
144
+ def prefatory_parse_semantic(cnt)
145
+ c = Asciidoctor.convert(cnt, backend: Util::taste2flavor(flavor).to_sym,
146
+ header_footer: true)
137
147
  x = Nokogiri::XML(c)
138
148
  x.xpath("//xmlns:clause").each { |n| n["unnumbered"] = true }
139
- file = Tempfile.new(%w(foo presentation.xml))
140
- file.write(x.to_xml(indent: 0))
141
- file.close
142
- c1 = Util::isodoc_create(@flavor, @manifest.lang, @manifest.script, x, presxml: true)
143
- .convert(file.path, nil, true)
144
- Nokogiri::XML(c1).at("//xmlns:sections").children.to_xml
149
+ b = x.at("//xmlns:bibdata")
150
+ prefatory_parse_fix_bibdata(b)
151
+ b.children = ::Metanorma::Standoc::Cleanup::MergeBibitems
152
+ .new(b.to_xml, @bibdata.to_xml(bibdata: true)).merge.to_noko.children
153
+ x
154
+ end
155
+
156
+ # Stop standoc ownerless copyright from breaking Relaton parse of bibdata
157
+ def prefatory_parse_fix_bibdata(bibdata)
158
+ if cop = bibdata.at("//xmlns:copyright")
159
+ cop.at("./xmlns:owner") or
160
+ cop.children.first.previous =
161
+ "<owner><organization><name>SDO</name></organization></owner>"
162
+ end
163
+ bibdata
145
164
  end
146
165
 
147
166
  # @param builder [Nokogiri::XML::Builder]
@@ -160,7 +179,7 @@ module Metanorma
160
179
  b.attachment Vectory::Utils::datauri(doc.file)
161
180
  else
162
181
  doc.to_xml b
163
- b.parent.children.first["flavor"] = flavor
182
+ b.parent.children.first["flavor"] = Util::taste2flavor(flavor)
164
183
  end
165
184
  end
166
185
  end
@@ -174,89 +193,11 @@ module Metanorma
174
193
  def fetch_flavor
175
194
  docid = @bibdata.docidentifier.first or return
176
195
  f = docid.type.downcase || docid.id.sub(/\s.*$/, "").downcase or return
196
+ f = Util::taste2flavor(f)
177
197
  require ::Metanorma::Compile.new.stdtype2flavor_gem(f)
178
198
  f
179
199
  rescue LoadError
180
200
  nil
181
201
  end
182
-
183
- class << self
184
- # @param Block [Proc]
185
- # @note allow user-specific function to run in pre-parse model stage
186
- def set_pre_parse_model(&block)
187
- @pre_parse_model_proc = block
188
- end
189
-
190
- # @param Block [Proc]
191
- # @note allow user-specific function to resolve identifier
192
- def set_identifier_resolver(&block)
193
- @identifier_resolver = block
194
- end
195
-
196
- # @param Block [Proc]
197
- # @note allow user-specific function to resolve fileref
198
- # NOTE: MUST ALWAYS RETURN PATH relative to working directory
199
- # (initial YAML file location). @fileref_resolver.call(ref_folder, fileref)
200
- # fileref is not what is in the YAML, but the resolved path
201
- # relative to the working directory
202
- def set_fileref_resolver(&block)
203
- @fileref_resolver = block
204
- end
205
-
206
- def unset_fileref_resolver
207
- @fileref_resolver = nil
208
- end
209
-
210
- # @param collection_model [Hash{String=>String}]
211
- def pre_parse_model(collection_model)
212
- @pre_parse_model_proc or return
213
- @pre_parse_model_proc.call(collection_model)
214
- end
215
-
216
- # @param identifier [String]
217
- # @return [String]
218
- def resolve_identifier(identifier)
219
- @identifier_resolver or return identifier
220
- @identifier_resolver.call(identifier)
221
- end
222
-
223
- # @param fileref [String]
224
- # @return [String]
225
- def resolve_fileref(ref_folder, fileref)
226
- warn ref_folder
227
- warn fileref
228
- unless @fileref_resolver
229
- (Pathname.new fileref).absolute? or
230
- fileref = File.join(ref_folder, fileref)
231
- return fileref
232
- end
233
-
234
- @fileref_resolver.call(ref_folder, fileref)
235
- end
236
-
237
- # @param filepath
238
- # @raise [FileNotFoundException]
239
- def check_file_existence(filepath)
240
- unless File.exist?(filepath)
241
- error_message = "#{filepath} not found!"
242
- ::Metanorma::Util.log("[metanorma] Error: #{error_message}", :error)
243
- raise FileNotFoundException.new error_message.to_s
244
- end
245
- end
246
-
247
- def parse(file)
248
- # need @dirname initialised before collection object initialisation
249
- @dirname = File.expand_path(File.dirname(file))
250
- config = case file
251
- when /\.xml$/
252
- ::Metanorma::Collection::Config::Config.from_xml(File.read(file))
253
- when /.ya?ml$/
254
- y = YAML.safe_load(File.read(file))
255
- pre_parse_model(y)
256
- ::Metanorma::Collection::Config::Config.from_yaml(y.to_yaml)
257
- end
258
- new(file: file, config: config)
259
- end
260
- end
261
202
  end
262
203
  end
@@ -20,6 +20,7 @@ module Metanorma
20
20
  attribute :directive, Directive, collection: true
21
21
  attribute :manifest, Manifest
22
22
  attribute :coverpage, :string, default: -> { "cover.html" }
23
+ attribute :coverpage_pdf_portfolio, :string
23
24
  attribute :format, :string, collection: true, default: -> { [:html] }
24
25
  attribute :output_folder, :string
25
26
  attribute :compile, CompileOptions
@@ -37,6 +38,8 @@ module Metanorma
37
38
  map "format", to: :format, render_default: true
38
39
  map "output_folder", to: :output_folder
39
40
  map "coverpage", to: :coverpage, render_default: true
41
+ map "coverpage-pdf-portfolio", to: :coverpage_pdf_portfolio,
42
+ render_default: true
40
43
  map "compile", to: :compile, render_default: true
41
44
  map "prefatory-content", to: :prefatory_content
42
45
  map "final-content", to: :final_content
@@ -54,6 +57,8 @@ module Metanorma
54
57
  map_element "format", to: :format, render_default: true
55
58
  map_element "output_folder", to: :output_folder
56
59
  map_element "coverpage", to: :coverpage, render_default: true
60
+ map_element "coverpage-pdf-portfolio", to: :coverpage_pdf_portfolio,
61
+ render_default: true
57
62
  map_element "compile", to: :compile, render_default: true
58
63
  map_element "prefatory-content",
59
64
  to: :prefatory_content,
@@ -46,6 +46,7 @@ module Metanorma
46
46
  end
47
47
 
48
48
  def nop_to_yaml(model, doc); end
49
+ def nop_to_xml(model, parent, doc); end
49
50
 
50
51
  def documents_from_xml(model, value)
51
52
  model.documents = value
@@ -25,10 +25,15 @@ module Metanorma
25
25
  attribute :index, :boolean, default: -> { true }
26
26
  attribute :entry, Manifest, collection: true
27
27
  attribute :file, :string
28
+ attribute :pdffile, :string
28
29
  attribute :format, :string, collection: true
30
+ attribute :output_filename, :string
31
+ attribute :sectionsplit_filename, :string
32
+ attribute :sectionsplit_output, :boolean
29
33
 
30
34
  yaml do
31
35
  map "identifier", to: :identifier
36
+ map "pdf-file", to: :pdffile
32
37
  map "type", to: :type
33
38
  map "level", to: :level,
34
39
  with: { from: :level_from_yaml, to: :nop_to_yaml }
@@ -48,6 +53,9 @@ module Metanorma
48
53
  map "bibdata", to: :bibdata, with: { from: :bibdata_from_yaml,
49
54
  to: :bibdata_to_yaml }
50
55
  map "format", to: :format, render_default: true
56
+ map "output-filename", to: :output_filename
57
+ map "sectionsplit-filename", to: :sectionsplit_filename
58
+ map "sectionsplit-output", to: :sectionsplit_output
51
59
  end
52
60
 
53
61
  xml do
@@ -57,6 +65,7 @@ module Metanorma
57
65
  map_attribute "sectionsplit", to: :sectionsplit
58
66
  map_attribute "index", to: :index
59
67
  map_attribute "url", to: :url
68
+ map_attribute "pdf-file", to: :pdffile
60
69
  map_attribute "fileref", to: :file
61
70
  map_element "identifier", to: :identifier, render_default: true
62
71
  map_element "type", to: :type
@@ -65,6 +74,12 @@ module Metanorma
65
74
  map_element "bibdata", to: :bibdata, with: { from: :bibdata_from_xml,
66
75
  to: :bibdata_to_xml }
67
76
  map_element "entry", to: :entry
77
+ map_element "output-filename", to: :output_filename,
78
+ with: { from: :output_filename_from_xml,
79
+ to: :nop_to_xml }
80
+ map_element "sectionsplit-filename", to: :sectionsplit_filename,
81
+ with: { from: :sectionsplit_filename_from_xml,
82
+ to: :nop_to_xml }
68
83
  end
69
84
 
70
85
  def entry_from_xml(model, node)
@@ -78,6 +93,14 @@ module Metanorma
78
93
  end
79
94
  end
80
95
 
96
+ def output_filename_from_xml(model, node)
97
+ model.output_filename ||= node.content
98
+ end
99
+
100
+ def sectionsplit_filename_from_xml(model, node)
101
+ model.sectionsplit_filename ||= node.content
102
+ end
103
+
81
104
  def level_from_yaml(model, value)
82
105
  model.type ||= value
83
106
  end
@@ -50,17 +50,39 @@ module Metanorma
50
50
 
51
51
  def mn2relaton_parser(tag)
52
52
  case tag
53
- when "bipm" then ::RelatonBipm::XMLParser
54
- when "bsi" then ::RelatonBsi::XMLParser
55
- when "ietf" then ::RelatonIetf::XMLParser
56
- when "iho" then ::RelatonIho::XMLParser
57
- when "itu" then ::RelatonItu::XMLParser
58
- when "iec" then ::RelatonIec::XMLParser
59
- when "iso" then ::RelatonIsoBib::XMLParser
60
- when "nist" then ::RelatonNist::XMLParser
61
- when "ogc" then ::RelatonOgc::XMLParser
62
- else ::RelatonBib::XMLParser
53
+ when "bipm"
54
+ require "relaton_bipm" unless defined?(::RelatonBipm::XMLParser)
55
+ ::RelatonBipm::XMLParser
56
+ when "bsi"
57
+ require "relaton_bsi" unless defined?(::RelatonBsi::XMLParser)
58
+ ::RelatonBsi::XMLParser
59
+ when "ietf"
60
+ require "relaton_ietf" unless defined?(::RelatonIetf::XMLParser)
61
+ ::RelatonIetf::XMLParser
62
+ when "iho"
63
+ require "relaton_iho" unless defined?(::RelatonIho::XMLParser)
64
+ ::RelatonIho::XMLParser
65
+ when "itu"
66
+ require "relaton_itu" unless defined?(::RelatonItu::XMLParser)
67
+ ::RelatonItu::XMLParser
68
+ when "iec"
69
+ require "relaton_iec" unless defined?(::RelatonIec::XMLParser)
70
+ ::RelatonIec::XMLParser
71
+ when "iso"
72
+ require "relaton_iso" unless defined?(::RelatonIsoBib::XMLParser)
73
+ ::RelatonIsoBib::XMLParser
74
+ when "nist"
75
+ require "relaton_nist" unless defined?(::RelatonNist::XMLParser)
76
+ ::RelatonNist::XMLParser
77
+ when "ogc"
78
+ require "relaton_ogc" unless defined?(::RelatonOgc::XMLParser)
79
+ ::RelatonOgc::XMLParser
80
+ else
81
+ ::RelatonBib::XMLParser
63
82
  end
83
+ rescue LoadError => e
84
+ warn "Warning: Failed to load relaton gem for '#{tag}': #{e.message}. Falling back to RelatonBib::XMLParser"
85
+ ::RelatonBib::XMLParser
64
86
  end
65
87
 
66
88
  # #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
@@ -0,0 +1,43 @@
1
+ module Metanorma
2
+ class Collection
3
+ class FileLookup
4
+ # are references to the file to be linked to a file in the collection,
5
+ # or externally? Determines whether file suffix anchors are to be used
6
+ def url?(ident)
7
+ data = get(ident) or return false
8
+ data[:url]
9
+ end
10
+
11
+ def key(ident)
12
+ @c.decode(ident).gsub(/(\p{Zs})+/, " ")
13
+ .sub(/^metanorma-collection /, "")
14
+ end
15
+
16
+ def keys
17
+ @files.keys
18
+ end
19
+
20
+ def get(ident, attr = nil)
21
+ if attr then @files[key(ident)][attr]
22
+ else @files[key(ident)]
23
+ end
24
+ end
25
+
26
+ def set(ident, attr, value)
27
+ @files[key(ident)][attr] = value
28
+ end
29
+
30
+ def each
31
+ @files.each
32
+ end
33
+
34
+ def each_with_index
35
+ @files.each_with_index
36
+ end
37
+
38
+ def ns(xpath)
39
+ @isodoc.ns(xpath)
40
+ end
41
+ end
42
+ end
43
+ end