ro-crate 0.4.0 → 0.4.5

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: 1a00cfaaae356d223c2104408fc10f894aa53271f982924b3c73c9661169b69f
4
- data.tar.gz: c26895cf57e0d1e4b31243a2f79031f5121ce0c7c598cb1862f6eb1e146fa2cc
3
+ metadata.gz: 78897fbce0fd01688c27516dceba600ed7cd984668fd16abde32a1713c0ba40f
4
+ data.tar.gz: 3194d882e4b7f6cd347d652d5da38cb2fe02cfb18e36d84f50e012193a538a69
5
5
  SHA512:
6
- metadata.gz: c16426ceee5c8660c145ea9bf4de09cc58bff30d726992628616c9795c8bd54b102f524f6a28514660322e1465d2fe3f0071ea2894000ccfc30ed88a99d9ad86
7
- data.tar.gz: fc8f8a3654ef0de78864a808cb797622189ee50becba25c1f0d1c095355655320c218c14d09a21f7baf87da34a1ec8bdcc93d50bd1f69ecc8dccc13708c090d6
6
+ metadata.gz: ddc2f5ffe217717299f2e5d76313b2a124fabfbc7b1e1800db18ca36d2f79c716ef249c6fcb8a6a8bfd4e0c5bba3b8a30d6ae3498ef8fd0068d7df08985c72f5
7
+ data.tar.gz: 802bf935d2e911ce771e962d6faaf0821f682049424cf5ac893ec780b8fc89d22f844156a83dd38adbe045a31faa7e527b4d8406bcabe937bdf8a2e8afafcd93
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.4.9
1
+ ruby-2.6.6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ro-crate (0.3.0)
4
+ ro-crate (0.4.5)
5
5
  addressable (~> 2.7.0)
6
6
  rubyzip (~> 2.0.0)
7
7
 
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  # ro-crate-ruby
2
2
 
3
- This is a WIP gem for creating, manipulating and reading RO crates (conforming to version 1.1 of the specification).
3
+ This is a WIP gem for creating, manipulating and reading RO-Crates (conforming to version 1.1 of the specification).
4
4
 
5
- * RO Crate - https://researchobject.github.io/ro-crate/
6
- * RO Crate spec (1.1) - https://researchobject.github.io/ro-crate/1.1/
5
+ * RO-Crate - https://researchobject.github.io/ro-crate/
6
+ * RO-Crate spec (1.1) - https://researchobject.github.io/ro-crate/1.1/
7
7
 
8
8
  ## Installation
9
9
 
10
10
  Using bundler, add the following to your Gemfile:
11
11
 
12
12
  ```
13
- gem 'ro-crate-ruby', git: 'https://github.com/ResearchObject/ro-crate-ruby.git'
13
+ gem 'ro-crate'
14
14
  ```
15
15
 
16
16
  and run `bundle install`.
@@ -24,20 +24,24 @@ and run `bundle install`.
24
24
  ### Examples
25
25
 
26
26
  ```ruby
27
- require 'ro_crate_ruby'
27
+ require 'ro_crate'
28
28
 
29
29
  # Make a new crate
30
30
  crate = ROCrate::Crate.new
31
31
  crate.add_file(File.open('Gemfile')) # Using IO-like objects
32
32
  crate.add_file('README.md') # or paths
33
33
 
34
+ # Quickly add everything from a directory into the crate
35
+ crate = ROCrate::Crate.new
36
+ crate.add_all('workspace/secret_project/dataset123')
37
+
34
38
  # Write to a zip file
35
39
  ROCrate::Writer.new(crate).write_zip(File.new('ro_crate.zip', 'w'))
36
40
 
37
41
  # Write to a directory
38
42
  ROCrate::Writer.new(crate).write('./ro_crate_stuff')
39
43
 
40
- # Read an RO crate
44
+ # Read an RO-Crate
41
45
  crate = ROCrate::Reader.read('./an_ro_crate_directory')
42
46
 
43
47
  # Make some changes
@@ -55,9 +59,9 @@ ext_file = crate.add_external_file('https://example.com/my_file.txt')
55
59
  ROCrate::Writer.new(crate).write('./an_ro_crate_directory')
56
60
  ```
57
61
 
58
- ### RO Crate Preview
59
- A simple HTML preview page is generated when an RO Crate is written, containing a list of the crate's contents and some
60
- metadata. This preview is written to `ro-crate-preview.html` at the root of the RO Crate.
62
+ ### RO-Crate Preview
63
+ A simple HTML preview page is generated when an RO-Crate is written, containing a list of the crate's contents and some
64
+ metadata. This preview is written to `ro-crate-preview.html` at the root of the RO-Crate.
61
65
 
62
66
  The default template can be seen here [here](lib/ro_crate/ro-crate-preview.html.erb).
63
67
 
data/Rakefile CHANGED
@@ -24,7 +24,7 @@ end
24
24
  task :console do
25
25
  require 'irb'
26
26
  require 'irb/completion'
27
- require 'ro_crate_ruby'
27
+ require 'ro_crate'
28
28
  ARGV.clear
29
29
  IRB.start
30
30
  end
File without changes
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A wrapper class for Hash that adds methods to dereference Entities within an RO Crate.
3
+ # A wrapper class for Hash that adds methods to dereference Entities within an RO-Crate.
4
4
  class JSONLDHash < ::Hash
5
5
  def initialize(graph, content = {})
6
6
  @graph = graph
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to represent a "Contextual Entity" within an RO Crate.
3
+ # A class to represent a "Contextual Entity" within an RO-Crate.
4
4
  # Contextual Entities are used to describe and provide context to the Data Entities within the crate.
5
5
  class ContextualEntity < Entity
6
6
  def self.format_id(id)
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A Ruby abstraction of an RO Crate.
3
+ # A Ruby abstraction of an RO-Crate.
4
4
  class Crate < Directory
5
5
  IDENTIFIER = './'.freeze
6
6
  attr_reader :data_entities
@@ -13,7 +13,7 @@ module ROCrate
13
13
  end
14
14
 
15
15
  ##
16
- # Initialize an empty RO Crate.
16
+ # Initialize an empty RO-Crate.
17
17
  def initialize(id = IDENTIFIER, properties = {})
18
18
  @data_entities = []
19
19
  @contextual_entities = []
@@ -24,7 +24,7 @@ module ROCrate
24
24
  # Create a new file and add it to the crate.
25
25
  #
26
26
  # @param source [String, Pathname, ::File, #read, nil] The source on the disk where this file will be read.
27
- # @param crate_path [String] The relative path within the RO crate where this file will be written.
27
+ # @param crate_path [String] The relative path within the RO-Crate where this file will be written.
28
28
  # @param entity_class [Class] The class to use to instantiate the Entity,
29
29
  # useful if you have created a subclass of ROCrate::File that you want to use. (defaults to ROCrate::File).
30
30
  # @param properties [Hash{String => Object}] A hash of JSON-LD properties to associate with this file.
@@ -51,7 +51,7 @@ module ROCrate
51
51
  # Create a new directory and add it to the crate.
52
52
  #
53
53
  # @param source_directory [String, Pathname, ::File, #read, nil] The source directory that will be included in the crate.
54
- # @param crate_path [String] The relative path within the RO crate where this directory will be written.
54
+ # @param crate_path [String] The relative path within the RO-Crate where this directory will be written.
55
55
  # @param entity_class [Class] The class to use to instantiate the Entity,
56
56
  # useful if you have created a subclass of ROCrate::Directory that you want to use. (defaults to ROCrate::Directory).
57
57
  # @param properties [Hash{String => Object}] A hash of JSON-LD properties to associate with this directory.
@@ -61,6 +61,35 @@ module ROCrate
61
61
  entity_class.new(self, source_directory, crate_path, properties).tap { |e| add_data_entity(e) }
62
62
  end
63
63
 
64
+ ##
65
+ # Recursively add the contents of the given source directory at the root of the crate.
66
+ # Useful for quickly RO-Crate-ifying a directory.
67
+ # Creates data entities for each file/directory discovered (excluding the top level directory itself) if `create_entities` is true.
68
+ #
69
+ # @param source_directory [String, Pathname, ::File,] The source directory that will be included in the crate.
70
+ # @param create_entities [Boolean] Whether to create data entities for the added content, or just include them anonymously.
71
+ # @param include_hidden [Boolean] Whether to include hidden files, i.e. those prefixed by a `.` (period).
72
+ #
73
+ # @return [Array<DataEntity>] Any entities that were created from the directory contents. Will be empty if `create_entities` was false.
74
+ def add_all(source_directory, create_entities = true, include_hidden: false)
75
+ added = []
76
+
77
+ if create_entities
78
+ list_all_files(source_directory, include_hidden: include_hidden).each do |rel_path|
79
+ source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
80
+ if source_path.directory?
81
+ added << add_directory(source_path, rel_path)
82
+ else
83
+ added << add_file(source_path, rel_path)
84
+ end
85
+ end
86
+ else
87
+ populate_entries(Pathname.new(::File.expand_path(source_directory)), include_hidden: include_hidden)
88
+ end
89
+
90
+ added
91
+ end
92
+
64
93
  ##
65
94
  # Create a new ROCrate::Person and add it to the crate
66
95
  #
@@ -119,7 +148,7 @@ module ROCrate
119
148
  end
120
149
 
121
150
  ##
122
- # The RO crate metadata file
151
+ # The RO-Crate metadata file
123
152
  #
124
153
  # @return [Metadata]
125
154
  def metadata
@@ -127,7 +156,7 @@ module ROCrate
127
156
  end
128
157
 
129
158
  ##
130
- # The RO crate preview file
159
+ # The RO-Crate preview file
131
160
  #
132
161
  # @return [Preview]
133
162
  def preview
@@ -143,7 +172,7 @@ module ROCrate
143
172
  end
144
173
 
145
174
  ##
146
- # Entities for the metadata file and crate itself, which should be present in all RO crates.
175
+ # Entities for the metadata file and crate itself, which should be present in all RO-Crates.
147
176
  #
148
177
  # @return [Array<Entity>]
149
178
  def default_entities
@@ -186,8 +215,9 @@ module ROCrate
186
215
  entity.class.new(crate, entity.id, entity.raw_properties)
187
216
  end
188
217
 
218
+ alias_method :own_entries, :entries
189
219
  ##
190
- # A map of all the files/directories contained in the RO crate, where the key is the destination path within the crate
220
+ # A map of all the files/directories contained in the RO-Crate, where the key is the destination path within the crate
191
221
  # and the value is an Entry where the source data can be read.
192
222
  #
193
223
  # @return [Hash{String => Entry}>]
@@ -195,9 +225,8 @@ module ROCrate
195
225
  entries = {}
196
226
 
197
227
  (default_entities | data_entities).each do |entity|
198
- next if entity == self
199
- entity.entries.each do |path, io|
200
- entries[path] = io
228
+ (entity == self ? own_entries : entity.entries).each do |path, entry|
229
+ entries[path] = entry
201
230
  end
202
231
  end
203
232
 
@@ -207,5 +236,11 @@ module ROCrate
207
236
  def get_binding
208
237
  binding
209
238
  end
239
+
240
+ private
241
+
242
+ def full_entry_path(relative_path)
243
+ relative_path
244
+ end
210
245
  end
211
246
  end
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to represent a "Data Entity" within an RO Crate.
3
+ # A class to represent a "Data Entity" within an RO-Crate.
4
4
  # Data Entities are the actual physical files and directories within the Crate.
5
5
  class DataEntity < Entity
6
6
  def self.format_id(id)
@@ -12,22 +12,18 @@ module ROCrate
12
12
  # Create a new Directory. PLEASE NOTE, the new directory will not be added to the crate. To do this, call
13
13
  # Crate#add_data_entity, or just use Crate#add_directory.
14
14
  #
15
- # @param crate [Crate] The RO crate that owns this directory.
15
+ # @param crate [Crate] The RO-Crate that owns this directory.
16
16
  # @param source_directory [String, Pathname, ::File, nil] The source directory that will be included in the crate.
17
- # @param crate_path [String] The relative path within the RO crate where this directory will be written.
17
+ # @param crate_path [String] The relative path within the RO-Crate where this directory will be written.
18
18
  # @param properties [Hash{String => Object}] A hash of JSON-LD properties to associate with this directory.
19
19
  def initialize(crate, source_directory = nil, crate_path = nil, properties = {})
20
20
  @directory_entries = {}
21
21
 
22
22
  if source_directory
23
- raise 'Not a directory' unless ::File.directory?(source_directory)
24
23
  source_directory = Pathname.new(::File.expand_path(source_directory))
24
+ @entry = Entry.new(source_directory)
25
+ populate_entries(source_directory)
25
26
  crate_path = source_directory.basename.to_s if crate_path.nil?
26
-
27
- Dir.chdir(source_directory) { Dir.glob('**/*') }.each do |rel_path|
28
- source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
29
- @directory_entries[rel_path] = Entry.new(source_path)
30
- end
31
27
  end
32
28
 
33
29
  super(crate, crate_path, properties)
@@ -40,9 +36,10 @@ module ROCrate
40
36
  # @return [Hash{String => Entry}>]
41
37
  def entries
42
38
  entries = {}
39
+ entries[filepath.chomp('/')] = @entry if @entry
43
40
 
44
41
  @directory_entries.each do |rel_path, entry|
45
- entries[::File.join(filepath, rel_path)] = entry
42
+ entries[full_entry_path(rel_path)] = entry
46
43
  end
47
44
 
48
45
  entries
@@ -50,6 +47,37 @@ module ROCrate
50
47
 
51
48
  private
52
49
 
50
+ ##
51
+ # Populate this directory with files/directories from a given source directory on disk.
52
+ #
53
+ # @param source_directory [Pathname] The source directory to populate from.
54
+ # @param include_hidden [Boolean] Whether to include hidden files, i.e. those prefixed by a `.` (period).
55
+ #
56
+ # @return [Hash{String => Entry}>] The files/directories that were populated.
57
+ # The key is the relative path of the file/directory, and the value is an Entry object where data can be read etc.
58
+ def populate_entries(source_directory, include_hidden: false)
59
+ raise 'Not a directory' unless ::File.directory?(source_directory)
60
+ @directory_entries = {}
61
+ list_all_files(source_directory, include_hidden: include_hidden).each do |rel_path|
62
+ source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
63
+ @directory_entries[rel_path] = Entry.new(source_path)
64
+ end
65
+
66
+ @directory_entries
67
+ end
68
+
69
+ def full_entry_path(relative_path)
70
+ ::File.join(filepath, relative_path)
71
+ end
72
+
73
+ def list_all_files(source_directory, include_hidden: false)
74
+ args = ['**/*']
75
+ args << ::File::FNM_DOTMATCH if include_hidden
76
+ Dir.chdir(source_directory) { Dir.glob(*args) }.reject do |path|
77
+ path == '.' || path == '..' || path.end_with?('/.')
78
+ end
79
+ end
80
+
53
81
  def default_properties
54
82
  super.merge(
55
83
  '@id' => "#{SecureRandom.uuid}/",
@@ -1,7 +1,7 @@
1
1
  module ROCrate
2
2
  ##
3
- # A generic "Entity" within an RO Crate. It has an identifier and a set of properties, and will be referenced in the
4
- # RO Crate Metadata's @graph.
3
+ # A generic "Entity" within an RO-Crate. It has an identifier and a set of properties, and will be referenced in the
4
+ # RO-Crate Metadata's @graph.
5
5
  class Entity
6
6
  attr_reader :crate
7
7
  attr_reader :properties
@@ -60,7 +60,7 @@ module ROCrate
60
60
  ##
61
61
  # Automatically replace an Entity or Array of Entities with a reference or Array of references. Also associates
62
62
  # the Entity/Entities with the current crate. This is useful for maintaining the flat @graph of entities that the
63
- # RO crate metadata file requires.
63
+ # RO-Crate metadata file requires.
64
64
  #
65
65
  # @param value [Entity, Array<Entity>, Object] A value that may be reference or array of references.
66
66
  # @return [Hash, Array<Hash>, Object] Return a reference, Array of references, or just the object itself if
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to represent a "physical" file or directory within an RO crate.
3
+ # A class to represent a "physical" file or directory within an RO-Crate.
4
4
  # It handles the actual reading/writing of bytes.
5
5
  class Entry
6
6
  attr_reader :source
@@ -8,9 +8,9 @@ module ROCrate
8
8
  # Create a new ROCrate::File. PLEASE NOTE, the new file will not be added to the crate. To do this, call
9
9
  # Crate#add_data_entity, or just use Crate#add_file.
10
10
  #
11
- # @param crate [Crate] The RO crate that owns this file.
11
+ # @param crate [Crate] The RO-Crate that owns this file.
12
12
  # @param source [String, Pathname, ::File, #read, URI, nil] The source on the disk (or on the internet if a URI) where this file will be read.
13
- # @param crate_path [String] The relative path within the RO crate where this file will be written.
13
+ # @param crate_path [String] The relative path within the RO-Crate where this file will be written.
14
14
  # @param properties [Hash{String => Object}] A hash of JSON-LD properties to associate with this file.
15
15
  def initialize(crate, source, crate_path = nil, properties = {})
16
16
  if crate_path.is_a?(Hash) && properties.empty?
@@ -1,6 +1,6 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to represent a reference within an RO crate, to a remote file held on the internet somewhere.
3
+ # A class to represent a reference within an RO-Crate, to a remote file held on the internet somewhere.
4
4
  # It handles the actual reading/writing of bytes.
5
5
  class RemoteEntry
6
6
  attr_reader :uri
@@ -1,13 +1,13 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to handle reading of RO Crates from Zip files or directories.
3
+ # A class to handle reading of RO-Crates from Zip files or directories.
4
4
  class Reader
5
5
  ##
6
- # Reads an RO Crate from a directory of zip file.
6
+ # Reads an RO-Crate from a directory of zip file.
7
7
  #
8
8
  # @param source [String, ::File, Pathname] The source location for the crate.
9
9
  # @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped (if its a Zip file).
10
- # @return [Crate] The RO Crate.
10
+ # @return [Crate] The RO-Crate.
11
11
  def self.read(source, target_dir: Dir.mktmpdir)
12
12
  raise "Not a directory!" unless ::File.directory?(target_dir)
13
13
  if ::File.directory?(source)
@@ -37,12 +37,12 @@ module ROCrate
37
37
  end
38
38
 
39
39
  ##
40
- # Reads an RO Crate from a zip file. It first extracts the Zip file to a temporary directory, and then calls
40
+ # Reads an RO-Crate from a zip file. It first extracts the Zip file to a temporary directory, and then calls
41
41
  # #read_directory.
42
42
  #
43
43
  # @param source [String, ::File, Pathname] The location of the zip file.
44
44
  # @param target_dir [String, ::File, Pathname] The target directory where the crate should be unzipped.
45
- # @return [Crate] The RO Crate.
45
+ # @return [Crate] The RO-Crate.
46
46
  def self.read_zip(source, target_dir: Dir.mktmpdir)
47
47
  unzip_to(source, target_dir)
48
48
 
@@ -50,10 +50,10 @@ module ROCrate
50
50
  end
51
51
 
52
52
  ##
53
- # Reads an RO Crate from a directory.
53
+ # Reads an RO-Crate from a directory.
54
54
  #
55
55
  # @param source [String, ::File, Pathname] The location of the directory.
56
- # @return [Crate] The RO Crate.
56
+ # @return [Crate] The RO-Crate.
57
57
  def self.read_directory(source)
58
58
  source = ::File.expand_path(source)
59
59
  metadata_file = Dir.entries(source).detect { |entry| entry == ROCrate::Metadata::IDENTIFIER ||
@@ -68,7 +68,7 @@ module ROCrate
68
68
  end
69
69
 
70
70
  ##
71
- # Extracts all the entities from the @graph of the RO Crate Metadata.
71
+ # Extracts all the entities from the @graph of the RO-Crate Metadata.
72
72
  #
73
73
  # @param metadata_json [String] A string containing the metadata JSON.
74
74
  # @return [Hash{String => Hash}] A Hash of all the entities, mapped by their @id.
@@ -99,12 +99,14 @@ module ROCrate
99
99
  # Create a crate from the given set of entities.
100
100
  #
101
101
  # @param entity_hash [Hash{String => Hash}] A Hash containing all the entities in the @graph, mapped by their @id.
102
- # @param source [String, ::File, Pathname] The location of the RO Crate being read.
103
- # @return [Crate] The RO Crate.
102
+ # @param source [String, ::File, Pathname] The location of the RO-Crate being read.
103
+ # @return [Crate] The RO-Crate.
104
104
  def self.build_crate(entity_hash, source)
105
105
  ROCrate::Crate.new.tap do |crate|
106
106
  crate.properties = entity_hash.delete(ROCrate::Crate::IDENTIFIER)
107
107
  crate.metadata.properties = entity_hash.delete(ROCrate::Metadata::IDENTIFIER)
108
+ preview_properties = entity_hash.delete(ROCrate::Preview::IDENTIFIER)
109
+ crate.preview.properties = preview_properties if preview_properties
108
110
  extract_data_entities(crate, source, entity_hash).each do |entity|
109
111
  crate.add_data_entity(entity)
110
112
  end
@@ -118,8 +120,8 @@ module ROCrate
118
120
  ##
119
121
  # Discover data entities from the `hasPart` property of a crate, and create DataEntity objects for them.
120
122
  # Entities are looked up in the given `entity_hash` (and then removed from it).
121
- # @param crate [Crate] The RO Crate being read.
122
- # @param source [String, ::File, Pathname] The location of the RO Crate being read.
123
+ # @param crate [Crate] The RO-Crate being read.
124
+ # @param source [String, ::File, Pathname] The location of the RO-Crate being read.
123
125
  # @param entity_hash [Hash] A Hash containing all the entities in the @graph, mapped by their @id.
124
126
  # @return [Array<ROCrate::File, ROCrate::Directory>] The extracted DataEntity objects.
125
127
  def self.extract_data_entities(crate, source, entity_hash)
@@ -135,7 +137,7 @@ module ROCrate
135
137
 
136
138
  ##
137
139
  # Create appropriately specialized ContextualEntity objects from the given hash of entities and their properties.
138
- # @param crate [Crate] The RO Crate being read.
140
+ # @param crate [Crate] The RO-Crate being read.
139
141
  # @param entity_hash [Hash] A Hash containing all the entities in the @graph, mapped by their @id.
140
142
  # @return [Array<ContextualEntity>] The extracted ContextualEntity objects.
141
143
  def self.extract_contextual_entities(crate, entity_hash)
@@ -152,8 +154,8 @@ module ROCrate
152
154
 
153
155
  ##
154
156
  # Create a DataEntity of the given class.
155
- # @param crate [Crate] The RO Crate being read.
156
- # @param source [String, ::File, Pathname] The location of the RO Crate being read.
157
+ # @param crate [Crate] The RO-Crate being read.
158
+ # @param source [String, ::File, Pathname] The location of the RO-Crate being read.
157
159
  # @param entity_props [Hash] A Hash containing the entity's properties, including its @id.
158
160
  # @return [ROCrate::File, ROCrate::Directory, nil] The DataEntity object,
159
161
  # or nil if it referenced a local file that wasn't found.
@@ -1,13 +1,13 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title><%= name || "New RO Crate" %></title>
4
+ <title><%= name || "New RO-Crate" %></title>
5
5
  <script type="application/ld+json"><%= metadata.generate %></script>
6
6
  <meta name="generator" content="https://github.com/fbacall/ro-crate-ruby">
7
- <meta name="keywords" content="RO Crate">
7
+ <meta name="keywords" content="RO-Crate">
8
8
  </head>
9
9
  <body>
10
- <h1><%= name || "New RO Crate" %></h1>
10
+ <h1><%= name || "New RO-Crate" %></h1>
11
11
  <% if url %>
12
12
  <a href="<%= url %>" target="_blank"><%= url %></a>
13
13
  <% end %>
@@ -1,10 +1,10 @@
1
1
  module ROCrate
2
2
  ##
3
- # A class to handle writing of RO Crates to Zip files or directories.
3
+ # A class to handle writing of RO-Crates to Zip files or directories.
4
4
  class Writer
5
5
  ##
6
6
  # Initialize a new Writer for the given Crate.
7
- # @param crate [Crate] The RO Crate to be written.
7
+ # @param crate [Crate] The RO-Crate to be written.
8
8
  def initialize(crate)
9
9
  @crate = crate
10
10
  end
@@ -35,7 +35,7 @@ module ROCrate
35
35
  ##
36
36
  # Write the crate to a zip file.
37
37
  #
38
- # @param destination [String, ::File] The destination where to write the RO Crate zip.
38
+ # @param destination [String, ::File] The destination where to write the RO-Crate zip.
39
39
  def write_zip(destination)
40
40
  Zip::File.open(destination, Zip::File::CREATE) do |zip|
41
41
  @crate.entries.each do |path, entry|
data/ro_crate.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ro-crate'
3
- s.version = '0.4.0'
4
- s.summary = 'Create, manipulate, read RO crates.'
3
+ s.version = '0.4.5'
4
+ s.summary = 'Create, manipulate, read RO-Crates.'
5
5
  s.authors = ['Finn Bacall']
6
6
  s.email = 'finn.bacall@manchester.ac.uk'
7
7
  s.files = `git ls-files`.split("\n")
data/test/crate_test.rb CHANGED
@@ -198,4 +198,99 @@ class CrateTest < Test::Unit::TestCase
198
198
  assert_equal file, new_crate.get('some/file.txt')
199
199
  assert_equal file, new_crate.get('http://mycoolwebsite.golf/ro_crate/some/file.txt')
200
200
  end
201
+
202
+ test 'can add an entire directory tree as data entities' do
203
+ crate = ROCrate::Crate.new
204
+ entities = crate.add_all(fixture_file('directory').path, include_hidden: true)
205
+
206
+ paths = crate.entries.keys
207
+ assert_equal 11, paths.length
208
+ assert_includes paths, 'data'
209
+ assert_includes paths, 'root.txt'
210
+ assert_includes paths, 'info.txt'
211
+ assert_includes paths, 'data/binary.jpg'
212
+ assert_includes paths, 'data/info.txt'
213
+ assert_includes paths, 'data/nested.txt'
214
+ assert_includes paths, '.dotfile'
215
+ assert_includes paths, '.dir'
216
+ assert_includes paths, '.dir/test.txt'
217
+ assert_includes paths, 'ro-crate-metadata.json'
218
+ assert_includes paths, 'ro-crate-preview.html'
219
+
220
+ assert_equal 9, entities.length
221
+ assert_equal 'ROCrate::Directory', crate.dereference('data/').class.name
222
+ assert_equal 'ROCrate::File', crate.dereference('root.txt').class.name
223
+ assert_equal 'ROCrate::File', crate.dereference('info.txt').class.name
224
+ assert_equal 'ROCrate::File', crate.dereference('data/binary.jpg').class.name
225
+ assert_equal 'ROCrate::File', crate.dereference('data/info.txt').class.name
226
+ assert_equal 'ROCrate::File', crate.dereference('data/nested.txt').class.name
227
+ assert_equal 'ROCrate::File', crate.dereference('.dotfile').class.name
228
+ assert_equal 'ROCrate::Directory', crate.dereference('.dir/').class.name
229
+ assert_equal 'ROCrate::File', crate.dereference('.dir/test.txt').class.name
230
+
231
+ assert_equal "5678\n", crate.dereference('data/info.txt').source.read
232
+ assert_equal "Am I included?\n", crate.dereference('.dotfile').source.read
233
+ end
234
+
235
+ test 'can create an RO-Crate using content from a given directory' do
236
+ crate = ROCrate::Crate.new
237
+ entities = crate.add_all(fixture_file('directory').path, false, include_hidden: true)
238
+
239
+ assert_empty entities
240
+
241
+ paths = crate.entries.keys
242
+ assert_equal 11, paths.length
243
+ assert_includes paths, 'data'
244
+ assert_includes paths, 'root.txt'
245
+ assert_includes paths, 'info.txt'
246
+ assert_includes paths, 'data/binary.jpg'
247
+ assert_includes paths, 'data/info.txt'
248
+ assert_includes paths, 'data/nested.txt'
249
+ assert_includes paths, '.dotfile'
250
+ assert_includes paths, '.dir'
251
+ assert_includes paths, '.dir/test.txt'
252
+ assert_includes paths, 'ro-crate-metadata.json'
253
+ assert_includes paths, 'ro-crate-preview.html'
254
+
255
+ # Should not create any data entities
256
+ assert_nil crate.dereference('data/')
257
+ assert_nil crate.dereference('root.txt')
258
+ assert_nil crate.dereference('info.txt')
259
+ assert_nil crate.dereference('data/binary.jpg')
260
+ assert_nil crate.dereference('data/info.txt')
261
+ assert_nil crate.dereference('data/nested.txt')
262
+ assert_nil crate.dereference('.dotfile')
263
+ end
264
+
265
+ test 'can create an RO-Crate using content from a given directory, excluding hidden files' do
266
+ crate = ROCrate::Crate.new
267
+ entities = crate.add_all(fixture_file('directory').path)
268
+
269
+ paths = crate.entries.keys
270
+ assert_equal 8, paths.length
271
+ assert_includes paths, 'data'
272
+ assert_includes paths, 'root.txt'
273
+ assert_includes paths, 'info.txt'
274
+ assert_includes paths, 'data/binary.jpg'
275
+ assert_includes paths, 'data/info.txt'
276
+ assert_includes paths, 'data/nested.txt'
277
+ assert_not_includes paths, '.dotfile'
278
+ assert_not_includes paths, '.dir'
279
+ assert_not_includes paths, '.dir/test.txt'
280
+ assert_includes paths, 'ro-crate-metadata.json'
281
+ assert_includes paths, 'ro-crate-preview.html'
282
+
283
+ assert_equal 6, entities.length
284
+ assert_equal 'ROCrate::Directory', crate.dereference('data/').class.name
285
+ assert_equal 'ROCrate::File', crate.dereference('root.txt').class.name
286
+ assert_equal 'ROCrate::File', crate.dereference('info.txt').class.name
287
+ assert_equal 'ROCrate::File', crate.dereference('data/binary.jpg').class.name
288
+ assert_equal 'ROCrate::File', crate.dereference('data/info.txt').class.name
289
+ assert_equal 'ROCrate::File', crate.dereference('data/nested.txt').class.name
290
+ assert_nil crate.dereference('.dotfile')
291
+ assert_nil crate.dereference('.dir/')
292
+ assert_nil crate.dereference('.dir/test.txt')
293
+
294
+ assert_equal "5678\n", crate.dereference('data/info.txt').source.read
295
+ end
201
296
  end
Binary file
@@ -0,0 +1 @@
1
+ 123
@@ -0,0 +1 @@
1
+ Am I included?
@@ -8,6 +8,13 @@
8
8
  "@id": "./"
9
9
  }
10
10
  },
11
+ {
12
+ "@id": "ro-crate-preview.html",
13
+ "@type": "CreativeWork",
14
+ "about": {
15
+ "@id": "./"
16
+ }
17
+ },
11
18
  {
12
19
  "@id": "./",
13
20
  "@type": "Dataset",
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>New RO-Crate</title>
5
+ <script type="application/ld+json">{
6
+ "@context": "https://w3id.org/ro/crate/1.1/context",
7
+ "@graph": [
8
+ {
9
+ "@id": "ro-crate-metadata.jsonld",
10
+ "@type": "CreativeWork",
11
+ "about": {
12
+ "@id": "./"
13
+ }
14
+ },
15
+ {
16
+ "@id": "ro-crate-preview.html",
17
+ "@type": "CreativeWork",
18
+ "about": {
19
+ "@id": "./"
20
+ }
21
+ },
22
+ {
23
+ "@id": "./",
24
+ "@type": "Dataset",
25
+ "hasPart": [
26
+ {
27
+ "@id": "fish/"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "@id": "fish/",
33
+ "@type": "Dataset"
34
+ }
35
+ ]
36
+ }</script>
37
+ <meta name="generator" content="https://github.com/fbacall/ro-crate-ruby">
38
+ <meta name="keywords" content="RO-Crate">
39
+ </head>
40
+ <body>
41
+ <h1>New RO-Crate</h1>
42
+
43
+ <p>
44
+
45
+ </p>
46
+ <dl>
47
+
48
+
49
+
50
+
51
+ </dl>
52
+
53
+ <h2>Contents</h2>
54
+ <ul>
55
+
56
+ <li id="__data_entity_fish/">
57
+
58
+ <strong>fish/</strong>
59
+
60
+
61
+
62
+ </li>
63
+
64
+ </ul>
65
+ </body>
66
+ </html>
data/test/reader_test.rb CHANGED
@@ -109,11 +109,13 @@ class ReaderTest < Test::Unit::TestCase
109
109
  test 'reading from directory with directories' do
110
110
  crate = ROCrate::Reader.read_directory(fixture_file('directory_crate').path)
111
111
 
112
+ assert crate.entries.values.all? { |e| e.is_a?(ROCrate::Entry) }
112
113
  assert crate.entries['fish/info.txt']
113
114
  assert_equal '1234', crate.entries['fish/info.txt'].source.read.chomp
114
- assert crate.entries['fish/root.txt']
115
+ refute crate.entries['fish/root.txt'].directory?
116
+ assert crate.entries['fish/data'].directory?
115
117
  assert crate.entries['fish/data/info.txt']
116
- assert crate.entries['fish/data/nested.txt']
118
+ refute crate.entries['fish/data/nested.txt'].remote?
117
119
  assert crate.entries['fish/data/binary.jpg']
118
120
  assert_equal ['./', 'fish/', 'ro-crate-metadata.jsonld', 'ro-crate-preview.html'], crate.entities.map(&:id).sort
119
121
  end
data/test/test_helper.rb CHANGED
@@ -2,7 +2,7 @@ require 'simplecov'
2
2
  SimpleCov.start
3
3
 
4
4
  require 'test/unit'
5
- require 'ro_crate_ruby'
5
+ require 'ro_crate'
6
6
  require 'webmock/test_unit'
7
7
 
8
8
  def fixture_file(name, *args)
data/test/writer_test.rb CHANGED
@@ -99,4 +99,17 @@ class WriterTest < Test::Unit::TestCase
99
99
  end
100
100
  end
101
101
  end
102
+
103
+ test 'should write out same contents that it was created with' do
104
+ crate = ROCrate::Crate.new
105
+ crate.add_all(fixture_file('directory').path, false)
106
+
107
+ Dir.mktmpdir do |dir|
108
+ ROCrate::Writer.new(crate).write(dir)
109
+ assert ::File.exist?(::File.join(dir, ROCrate::Metadata::IDENTIFIER))
110
+ assert ::File.exist?(::File.join(dir, ROCrate::Preview::IDENTIFIER))
111
+ assert_equal 5, ::File.size(::File.join(dir, 'info.txt'))
112
+ assert_equal 2529, ::File.size(::File.join(dir, 'data', 'binary.jpg'))
113
+ end
114
+ end
102
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ro-crate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Finn Bacall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-18 00:00:00.000000000 Z
11
+ date: 2021-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -123,6 +123,7 @@ files:
123
123
  - LICENSE
124
124
  - README.md
125
125
  - Rakefile
126
+ - lib/ro_crate.rb
126
127
  - lib/ro_crate/json_ld_hash.rb
127
128
  - lib/ro_crate/model/contact_point.rb
128
129
  - lib/ro_crate/model/contextual_entity.rb
@@ -140,7 +141,6 @@ files:
140
141
  - lib/ro_crate/reader.rb
141
142
  - lib/ro_crate/ro-crate-preview.html.erb
142
143
  - lib/ro_crate/writer.rb
143
- - lib/ro_crate_ruby.rb
144
144
  - ro_crate.gemspec
145
145
  - test/crate_test.rb
146
146
  - test/directory_test.rb
@@ -149,6 +149,8 @@ files:
149
149
  - test/fixtures/crate-spec1.1/ro-crate-metadata.json
150
150
  - test/fixtures/data.csv
151
151
  - test/fixtures/directory.zip
152
+ - test/fixtures/directory/.dir/test.txt
153
+ - test/fixtures/directory/.dotfile
152
154
  - test/fixtures/directory/data/binary.jpg
153
155
  - test/fixtures/directory/data/info.txt
154
156
  - test/fixtures/directory/data/nested.txt
@@ -160,6 +162,7 @@ files:
160
162
  - test/fixtures/directory_crate/fish/info.txt
161
163
  - test/fixtures/directory_crate/fish/root.txt
162
164
  - test/fixtures/directory_crate/ro-crate-metadata.jsonld
165
+ - test/fixtures/directory_crate/ro-crate-preview.html
163
166
  - test/fixtures/file with spaces.txt
164
167
  - test/fixtures/info.txt
165
168
  - test/fixtures/spaces/file with spaces.txt
@@ -2414,5 +2417,5 @@ requirements: []
2414
2417
  rubygems_version: 3.0.8
2415
2418
  signing_key:
2416
2419
  specification_version: 4
2417
- summary: Create, manipulate, read RO crates.
2420
+ summary: Create, manipulate, read RO-Crates.
2418
2421
  test_files: []