metanorma 1.7.7 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d25e0a641fe7ce0087e3d06ebb5851e52a3c85924259e6cf39f731f378d7212
4
- data.tar.gz: 5ae477f5ad66882bf1b22ee0f9511636c14f937d4f50eb9defa7c8122c874f7c
3
+ metadata.gz: 92e4b253c6c10fcce6aee6e827adec6281f79cd0e72e2ee84696af2bc288d0b1
4
+ data.tar.gz: 6bf08b8a123331df15d3ad9fc62d61b31ce3c53208cd14252830fee11c1b8977
5
5
  SHA512:
6
- metadata.gz: 8375fbebae7cb30ae9775b5329c567274ad47cdfc40652f7cf35f00b3691629198dc3ee56c95f0c332b7edf63788ad0f2586ecb4305c18737bdbeed8c16bff91
7
- data.tar.gz: 6e6f57ff7e26d519cfeea98daf8a027ff27fb39f02f0ac8928f2bfab01030fa866992172ef8f8f9ca7f666783afa2e878f412a4a79b7b9d62fbe86d9a2c8c2e7
6
+ metadata.gz: 9cda0f7b08169d3d9bb7aef6f25a372882f561310f5cf8913cae241398b83acae2c8d160be3d6ec1aa924a030e49d4058f2b42ff7f404c6ff8c4d906d8c126ec
7
+ data.tar.gz: 810ef3dd1033bcb57e7d097647dc5fa5f360310b15bf0e62d0056d62e67c2d290ec13c68720b0e080e1bc08ed5d13093928fb785c963ee276f9248c6473cf913
data/Gemfile CHANGED
@@ -6,4 +6,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}" }
6
6
 
7
7
  gemspec
8
8
 
9
- eval_gemfile("Gemfile.devel") rescue nil
9
+ begin
10
+ eval_gemfile("Gemfile.devel")
11
+ rescue StandardError
12
+ nil
13
+ end
@@ -0,0 +1,9 @@
1
+ # TODO sidesteps bibdata redefinition of filter, will remove
2
+
3
+ module Metanorma
4
+ module ArrayMonkeypatch
5
+ class ::Array
6
+ alias filter select
7
+ end
8
+ end
9
+ end
@@ -1,16 +1,18 @@
1
- module Metanorma::AsciidoctorExtensions
2
- class GlobIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
3
- def process(_doc, reader, target_glob, attributes)
4
- Dir[File.join reader.dir, target_glob].sort.reverse_each do |target|
5
- content = IO.readlines target
6
- content.unshift "" unless attributes["adjoin-option"]
7
- reader.push_include content, target, target, 1, attributes
1
+ module Metanorma
2
+ module AsciidoctorExtensions
3
+ class GlobIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
4
+ def process(_doc, reader, target_glob, attributes)
5
+ Dir[File.join reader.dir, target_glob].sort.reverse_each do |target|
6
+ content = File.readlines target
7
+ content.unshift "" unless attributes["adjoin-option"]
8
+ reader.push_include content, target, target, 1, attributes
9
+ end
10
+ reader
8
11
  end
9
- reader
10
- end
11
12
 
12
- def handles?(target)
13
- target.include? "*"
13
+ def handles?(target)
14
+ target.include? "*"
15
+ end
14
16
  end
15
17
  end
16
18
  end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "relaton"
4
+ require "relaton/cli"
5
+ require "metanorma-utils"
6
+ require_relative "util/util"
7
+ require_relative "util/disambig_files"
8
+ require_relative "config/config"
9
+ require_relative "config/manifest"
10
+
11
+ module Metanorma
12
+ class FileNotFoundException < StandardError; end
13
+
14
+ class AdocFileNotFoundException < StandardError; end
15
+
16
+ # Metanorma collection of documents
17
+ class Collection
18
+ attr_reader :file
19
+
20
+ # @return [Array<String>] documents-inline to inject the XML into
21
+ # the collection manifest; documents-external to keeps them outside
22
+ attr_accessor :directives, :documents, :bibdatas, :coverpage, :dirname
23
+ attr_accessor :disambig, :manifest, :bibdata, :compile, :config
24
+
25
+ # @param file [String] path to source file
26
+ # @param config [Metanorma::Collection::Config]
27
+ # @param documents [Hash<String, Metanorma::Collection::Document>]
28
+ def initialize(**args)
29
+ @file = args[:file]
30
+ @dirname = File.expand_path(File.dirname(@file)) # feeds @manifest
31
+ @documents = args[:documents] || {} # feeds initialize_directives
32
+ @bibdatas = args[:documents] || {}
33
+ initialize_vars
34
+ initialize_config(args[:config])
35
+ initialize_directives
36
+ @documents.merge! @manifest.documents
37
+ @bibdatas.merge! @manifest.documents
38
+ @documents.transform_keys { |k| Util::key(k) }
39
+ @bibdatas.transform_keys { |k| Util::key(k) }
40
+ end
41
+
42
+ def initialize_vars
43
+ @compile = Metanorma::Compile.new # feeds @manifest
44
+ @log = Metanorma::Utils::Log.new
45
+ @disambig = Util::DisambigFiles.new
46
+ end
47
+
48
+ def initialize_config(config)
49
+ @config = config
50
+ @directives = config.directive || [] # feeds initialize_directives
51
+ @bibdata = config.bibdata
52
+ @prefatory = config.prefatory_content
53
+ @final = config.final_content
54
+ @manifest = ::Metanorma::Collection::Manifest
55
+ .new(config.manifest, self, @dirname) # feeds initialize_directives
56
+ end
57
+
58
+ def initialize_directives
59
+ d = @directives.each_with_object({}) { |x, m| m[x.key] = x.value }
60
+ @coverpage = d["coverpage"]
61
+ @coverpage_style = d["coverpage-style"]
62
+ if (@documents.any? || @manifest) && !d.key?("documents-inline") &&
63
+ !d.key?("documents-external")
64
+ @directives << ::Metanorma::Collection::Config::Directive
65
+ .new(key: "documents-inline")
66
+ end
67
+ end
68
+
69
+ def clean_exit
70
+ @log.write(File.join(@dirname,
71
+ "#{File.basename(@file, '.*')}.err.html"))
72
+ end
73
+
74
+ # @return [String] XML
75
+ def to_xml
76
+ c = ::Metanorma::Collection::Config::Config
77
+ .new(directive: @directives, bibdata: @bibdata,
78
+ manifest: @manifest.config, documents: @documents,
79
+ prefatory_content: @prefatory, final_content: @final)
80
+ c.collection = self
81
+ c.to_xml # .sub("<metanorma-collection", "<metanorma-collection xmlns='http://metanorma.org'")
82
+ end
83
+
84
+ def render(opts)
85
+ opts[:format].nil? || opts[:format].empty? and opts[:format] = [:html]
86
+ ::Metanorma::Collection::Renderer.render self, opts.merge(log: @log)
87
+ clean_exit
88
+ end
89
+
90
+ # @return [String, nil]
91
+ attr_reader :prefatory, :final
92
+
93
+ # @return [String]
94
+ def dummy_header
95
+ <<~DUMMY
96
+ = X
97
+ A
98
+
99
+ DUMMY
100
+ end
101
+
102
+ # @param elm [String] 'prefatory' or 'final'
103
+ # @param builder [Nokogiri::XML::Builder]
104
+ def content_to_xml(elm, builder)
105
+ (cnt = send(elm)) or return
106
+ @compile.load_flavor(doctype)
107
+ out = sections(dummy_header + cnt.strip)
108
+ builder.send("#{elm}-content") { |b| b << out }
109
+ end
110
+
111
+ # @param cnt [String] prefatory/final content
112
+ # @return [String] XML
113
+ def sections(cnt)
114
+ c = Asciidoctor.convert(cnt, backend: doctype.to_sym, header_footer: true)
115
+ Nokogiri::XML(c, &:huge).at("//xmlns:sections").children.to_xml
116
+ end
117
+
118
+ # @param builder [Nokogiri::XML::Builder]
119
+ def doccontainer(builder)
120
+ # Array(@directives).include? "documents-inline" or return
121
+ @directives.detect { |d| d.key == "documents-inline" } or return
122
+ documents.each_with_index do |(_, d), i|
123
+ doccontainer1(builder, d, i)
124
+ end
125
+ end
126
+
127
+ def doccontainer1(builder, doc, idx)
128
+ id = format("doc%<index>09d", index: idx)
129
+ builder.send(:"doc-container", id: id) do |b|
130
+ if doc.attachment
131
+ doc.bibitem and b << doc.bibitem.root.to_xml
132
+ b.attachment Vectory::Utils::datauri(doc.file)
133
+ else
134
+ doc.to_xml b
135
+ end
136
+ end
137
+ end
138
+
139
+ def doctype
140
+ @doctype ||= fetch_doctype || "standoc"
141
+ end
142
+
143
+ def fetch_doctype
144
+ docid = @bibdata.docidentifier.first
145
+ docid or return
146
+ docid.type&.downcase || docid.id&.sub(/\s.*$/, "")&.downcase
147
+ end
148
+
149
+ class << self
150
+ # @param Block [Proc]
151
+ # @note allow user-specific function to run in pre-parse model stage
152
+ def set_pre_parse_model(&block)
153
+ @pre_parse_model_proc = block
154
+ end
155
+
156
+ # @param Block [Proc]
157
+ # @note allow user-specific function to resolve identifier
158
+ def set_identifier_resolver(&block)
159
+ @identifier_resolver = block
160
+ end
161
+
162
+ # @param Block [Proc]
163
+ # @note allow user-specific function to resolve fileref
164
+ # NOTE: MUST ALWAYS RETURN PATH relative to working directory
165
+ # (initial YAML file location). @fileref_resolver.call(ref_folder, fileref)
166
+ # fileref is not what is in the YAML, but the resolved path
167
+ # relative to the working directory
168
+ def set_fileref_resolver(&block)
169
+ @fileref_resolver = block
170
+ end
171
+
172
+ def unset_fileref_resolver
173
+ @fileref_resolver = nil
174
+ end
175
+
176
+ # @param collection_model [Hash{String=>String}]
177
+ def pre_parse_model(collection_model)
178
+ @pre_parse_model_proc or return
179
+ @pre_parse_model_proc.call(collection_model)
180
+ end
181
+
182
+ # @param identifier [String]
183
+ # @return [String]
184
+ def resolve_identifier(identifier)
185
+ @identifier_resolver or return identifier
186
+ @identifier_resolver.call(identifier)
187
+ end
188
+
189
+ # @param fileref [String]
190
+ # @return [String]
191
+ def resolve_fileref(ref_folder, fileref)
192
+ unless @fileref_resolver
193
+ (Pathname.new fileref).absolute? or
194
+ fileref = File.join(ref_folder, fileref)
195
+ return fileref
196
+ end
197
+
198
+ @fileref_resolver.call(ref_folder, fileref)
199
+ end
200
+
201
+ # @param filepath
202
+ # @raise [FileNotFoundException]
203
+ def check_file_existence(filepath)
204
+ unless File.exist?(filepath)
205
+ error_message = "#{filepath} not found!"
206
+ ::Metanorma::Util.log("[metanorma] Error: #{error_message}", :error)
207
+ raise FileNotFoundException.new error_message.to_s
208
+ end
209
+ end
210
+
211
+ def parse(file)
212
+ # need @dirname initialised before collection object initialisation
213
+ @dirname = File.expand_path(File.dirname(file))
214
+ config = case file
215
+ when /\.xml$/
216
+ ::Metanorma::Collection::Config::Config.from_xml(File.read(file))
217
+ when /.ya?ml$/
218
+ y = YAML.safe_load(File.read(file))
219
+ pre_parse_model(y)
220
+ ::Metanorma::Collection::Config::Config.from_yaml(y.to_yaml)
221
+ end
222
+ new(file: file, config: config)
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,12 @@
1
+ require "relaton"
2
+ require "shale"
3
+
4
+ module Metanorma
5
+ class Collection
6
+ module Config
7
+ class Bibdata < ::Shale::Mapper
8
+ model ::RelatonBib::BibliographicItem
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ require "shale"
2
+
3
+ module Metanorma
4
+ class Collection
5
+ module Config
6
+ class CompileOptions < ::Shale::Mapper
7
+ attribute :no_install_fonts, ::Shale::Type::Boolean,
8
+ default: -> { true }
9
+ attribute :agree_to_terms, ::Shale::Type::Boolean, default: -> { true }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,163 @@
1
+ require "shale"
2
+ require_relative "../../shale_monkeypatch"
3
+ require_relative "../../array_monkeypatch"
4
+ require_relative "compile_options"
5
+ require_relative "converters"
6
+ require_relative "bibdata"
7
+ require_relative "directive"
8
+ require_relative "manifest"
9
+
10
+ module Metanorma
11
+ class Collection
12
+ module Config
13
+ require "shale/adapter/nokogiri"
14
+ ::Shale.xml_adapter = ::Shale::Adapter::Nokogiri
15
+
16
+ class Config < ::Shale::Mapper
17
+ attr_accessor :path, :collection, :from_xml
18
+
19
+ attribute :bibdata, Bibdata
20
+ attribute :directive, Directive, collection: true
21
+ attribute :manifest, Manifest
22
+ attribute :format, ::Shale::Type::String, collection: true,
23
+ default: -> { [:html] }
24
+ attribute :output_folder, ::Shale::Type::String
25
+ attribute :coverpage, ::Shale::Type::String, default: -> {
26
+ "cover.html"
27
+ }
28
+ attribute :compile, CompileOptions
29
+ attribute :prefatory_content, ::Shale::Type::String
30
+ attribute :final_content, ::Shale::Type::String
31
+ attribute :documents, Bibdata, collection: true
32
+ attribute :xmlns, ::Shale::Type::String, default: -> { "http://metanorma.org" }
33
+
34
+ yaml do
35
+ map "directives", using: { from: :directives_from_yaml,
36
+ to: :directives_to_yaml }
37
+ map "bibdata", using: { from: :bibdata_from_yaml,
38
+ to: :bibdata_to_yaml }
39
+ map "manifest", to: :manifest
40
+ map "format", to: :format
41
+ map "output_folder", to: :output_folder
42
+ map "coverpage", to: :coverpage
43
+ map "compile", to: :compile
44
+ map "prefatory-content", to: :prefatory_content
45
+ map "final-content", to: :final_content
46
+ end
47
+
48
+ xml do
49
+ root "metanorma-collection"
50
+ # namespace "http://metanorma.org", "m"
51
+ # map_attribute "xmlns", to: :xmlns
52
+ map_element "bibdata", using: { from: :bibdata_from_xml,
53
+ to: :bibdata_to_xml }
54
+ map_element "directive", using: { from: :directive_from_xml,
55
+ to: :directive_to_xml }
56
+ map_element "entry", using: { from: :manifest_from_xml,
57
+ to: :manifest_to_xml }
58
+ map_element "format", to: :format
59
+ map_element "output_folder", to: :output_folder
60
+ map_element "coverpage", to: :coverpage
61
+ map_element "compile", to: :compile
62
+ map_element "prefatory-content", using: { from: :prefatory_from_xml,
63
+ to: :prefatory_to_xml }
64
+ map_element "doc-container",
65
+ using: { from: :documents_from_xml,
66
+ to: :documents_to_xml }
67
+ map_element "final-content", using: { from: :final_from_xml,
68
+ to: :final_to_xml }
69
+ end
70
+
71
+ def manifest_from_xml(model, node)
72
+ model.manifest = Manifest.from_xml(node.to_xml)
73
+ end
74
+
75
+ def manifest_to_xml(model, parent, doc)
76
+ model.collection&.manifest&.clean_manifest(model.manifest)
77
+ doc.add_element(parent, model.manifest.to_xml)
78
+ end
79
+
80
+ def prefatory_from_xml(model, node)
81
+ model.prefatory_content = node.to_xml
82
+ end
83
+
84
+ def prefatory_to_xml(model, parent, doc)
85
+ content_to_xml(model, parent, doc, "prefatory")
86
+ end
87
+
88
+ def final_to_xml(model, parent, doc)
89
+ content_to_xml(model, parent, doc, "final")
90
+ end
91
+
92
+ def content_to_xml(model, parent, doc, type)
93
+ x = model.send("#{type}_content") or return
94
+ n = Nokogiri::XML(x)
95
+ elem = if n.elements.size == 1 then n.root
96
+ else
97
+ b = Nokogiri::XML::Builder.new
98
+ model.collection.content_to_xml(type, b)
99
+ b.parent.elements.first
100
+ end
101
+ doc.add_element(parent, elem)
102
+ end
103
+
104
+ def final_from_xml(model, node)
105
+ model.final_content = node.to_xml
106
+ end
107
+
108
+ def directive_from_xml(model, node)
109
+ model.directive ||= []
110
+ model.directive << Directive.from_xml(node.to_xml)
111
+ end
112
+
113
+ def directive_to_xml(model, parent, doc)
114
+ Array(model.directive).each do |e|
115
+ elem = e.to_xml
116
+ doc.add_element(parent, elem)
117
+ end
118
+ end
119
+
120
+ def directives_from_yaml(model, value)
121
+ model.directive = value&.each_with_object([]) do |v, m|
122
+ m << case v
123
+ when String then Directive.new(key: v)
124
+ when Hash
125
+ k = v.keys.first
126
+ Directive.new(key: k, value: v[k])
127
+ end
128
+ end
129
+ end
130
+
131
+ def directives_to_yaml(model, doc)
132
+ doc["directives"] = model.directive.each_with_object([]) do |d, m|
133
+ m << { d.key => d.value }
134
+ end
135
+ end
136
+
137
+ def documents_from_xml(model, value)
138
+ x = if value.is_a?(Shale::Adapter::Nokogiri::Node)
139
+ value.content
140
+ else Nokogiri::XML(value)
141
+ end
142
+ model.documents = x.xpath(".//bibdata")
143
+ .each_with_object([]) do |b, m|
144
+ m << Bibdata.from_xml(b.to_xml)
145
+ end
146
+ end
147
+
148
+ def documents_to_xml(model, parent, doc)
149
+ b = Nokogiri::XML::Builder.new do |xml|
150
+ xml.document do |m|
151
+ model.collection.doccontainer(m) or return
152
+ end
153
+ end
154
+ b.parent.elements.first.elements.each do |x|
155
+ doc.add_element(parent, x)
156
+ end
157
+ end
158
+
159
+ include Converters
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,30 @@
1
+ require "relaton-cli"
2
+
3
+ module Metanorma
4
+ class Collection
5
+ module Config
6
+ module Converters
7
+ def bibdata_from_yaml(model, value)
8
+ value and !value.empty? or return
9
+ model.bibdata = Relaton::Cli::YAMLConvertor.convert_single_file(value)
10
+ end
11
+
12
+ def bibdata_to_yaml(model, doc)
13
+ doc["bibdata"] = model.bibdata&.to_hash
14
+ end
15
+
16
+ def bibdata_from_xml(model, node)
17
+ model.bibdata = Relaton::Cli.parse_xml(node.content)
18
+ end
19
+
20
+ def bibdata_to_xml(model, parent, doc)
21
+ b = model.bibdata or return
22
+ elem = b.to_xml(bibdata: true, date_format: :full)
23
+ doc.add_element(parent, elem)
24
+ end
25
+
26
+ def nop_to_yaml(model, doc); end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module Metanorma
2
+ class Collection
3
+ module Config
4
+ class Directive < ::Shale::Mapper
5
+ attribute :key, ::Shale::Type::String
6
+ attribute :value, ::Shale::Type::String
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,88 @@
1
+ require "shale"
2
+ require_relative "../../shale_monkeypatch"
3
+ require_relative "../../array_monkeypatch"
4
+ require_relative "converters"
5
+ require_relative "bibdata"
6
+
7
+ module Metanorma
8
+ class Collection
9
+ module Config
10
+ require "shale/adapter/nokogiri"
11
+ ::Shale.xml_adapter = ::Shale::Adapter::Nokogiri
12
+
13
+ class Manifest < ::Shale::Mapper
14
+ attribute :identifier, ::Shale::Type::String,
15
+ default: -> { UUIDTools::UUID.random_create.to_s }
16
+ attribute :id, ::Shale::Type::String
17
+ attribute :bibdata, Bibdata
18
+ attribute :type, ::Shale::Type::String
19
+ attribute :title, ::Shale::Type::String
20
+ attribute :url, ::Shale::Type::String
21
+ attribute :attachment, ::Shale::Type::Boolean
22
+ attribute :sectionsplit, ::Shale::Type::Boolean
23
+ attribute :index, ::Shale::Type::Boolean, default: -> { true }
24
+ attribute :entry, Manifest, collection: true
25
+ attribute :file, ::Shale::Type::String
26
+
27
+ yaml do
28
+ map "identifier", to: :identifier
29
+ map "type", to: :type
30
+ map "level", using: { from: :level_from_yaml, to: :nop_to_yaml }
31
+ map "title", to: :title
32
+ map "url", to: :url
33
+ map "attachment", to: :attachment
34
+ map "sectionsplit", to: :sectionsplit
35
+ map "index", to: :index
36
+ map "file", to: :file
37
+ map "fileref", using: { from: :fileref_from_yaml, to: :nop_to_yaml }
38
+ map "entry", to: :entry
39
+ map "docref", using: { from: :docref_from_yaml, to: :nop_to_yaml }
40
+ map "manifest", using: { from: :docref_from_yaml, to: :nop_to_yaml }
41
+ map "bibdata", using: { from: :bibdata_from_yaml,
42
+ to: :bibdata_to_yaml }
43
+ end
44
+
45
+ xml do
46
+ root "entry"
47
+ map_attribute "id", to: :id
48
+ map_attribute "attachment", to: :attachment
49
+ map_attribute "sectionsplit", to: :sectionsplit
50
+ map_attribute "index", to: :index
51
+ map_attribute "url", to: :url
52
+ map_attribute "fileref", to: :file
53
+ map_element "identifier", to: :identifier
54
+ map_element "type", to: :type
55
+ map_element "title", to: :title
56
+ map_element "bibdata", using: { from: :bibdata_from_xml,
57
+ to: :bibdata_to_xml }
58
+ map_element "entry", to: :entry # using: { from: :entry_from_xml, to: :entry_to_xml }
59
+ end
60
+
61
+ def entry_from_xml(model, node)
62
+ model.entry = Manifest.from_xml(node.content)
63
+ end
64
+
65
+ def entry_to_xml(model, parent, doc)
66
+ Array(model.entry).each do |e|
67
+ elem = e.to_xml
68
+ doc.add_element(parent, elem)
69
+ end
70
+ end
71
+
72
+ def level_from_yaml(model, value)
73
+ model.type ||= value
74
+ end
75
+
76
+ def fileref_from_yaml(model, value)
77
+ model.file ||= value
78
+ end
79
+
80
+ def docref_from_yaml(model, value)
81
+ model.entry = Manifest.from_yaml(value.to_yaml)
82
+ end
83
+
84
+ include Converters
85
+ end
86
+ end
87
+ end
88
+ end