ro-crate 0.4.1 → 0.4.2
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 +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +11 -7
- data/lib/ro_crate/json_ld_hash.rb +1 -1
- data/lib/ro_crate/model/contextual_entity.rb +1 -1
- data/lib/ro_crate/model/crate.rb +38 -10
- data/lib/ro_crate/model/data_entity.rb +1 -1
- data/lib/ro_crate/model/directory.rb +21 -8
- data/lib/ro_crate/model/entity.rb +3 -3
- data/lib/ro_crate/model/entry.rb +1 -1
- data/lib/ro_crate/model/file.rb +2 -2
- data/lib/ro_crate/model/remote_entry.rb +1 -1
- data/lib/ro_crate/reader.rb +17 -15
- data/lib/ro_crate/ro-crate-preview.html.erb +3 -3
- data/lib/ro_crate/writer.rb +3 -3
- data/ro_crate.gemspec +2 -2
- data/test/crate_test.rb +30 -0
- data/test/fixtures/directory.zip +0 -0
- data/test/fixtures/directory_crate/ro-crate-metadata.jsonld +7 -0
- data/test/fixtures/directory_crate/ro-crate-preview.html +66 -0
- data/test/writer_test.rb +13 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 174513e7c0e8ec6ac0cf6c8bf1ca80dda57f4d95669681d15821a5e1290b5a70
|
4
|
+
data.tar.gz: 835ad728feca6614b81368b3d3428ffe4f7ad8614863bfdbaf669597bc8abbc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c87db2e02ed875d80e1a5ef4a8c5a3e63fedeb67a20b3a94762f6e8a47f79430e970b525ada5510cd3b86d64b955691dde0e267c856ca53eb24e311017f4a59b
|
7
|
+
data.tar.gz: bbd587d78f67f043917b128f78ad9a94e4044e7096bd9d1540a28e47313fb427a8196b8e531b7123ee7ba1dac686cb5a4de4114d9418ae415f384b3d27847f7e
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.6.6
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# ro-crate-ruby
|
2
2
|
|
3
|
-
This is a WIP gem for creating, manipulating and reading RO
|
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
|
6
|
-
* RO
|
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
|
|
@@ -31,13 +31,17 @@ 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
|
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
|
59
|
-
A simple HTML preview page is generated when an RO
|
60
|
-
metadata. This preview is written to `ro-crate-preview.html` at the root of the RO
|
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
|
|
@@ -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
|
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
|
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)
|
data/lib/ro_crate/model/crate.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module ROCrate
|
2
2
|
##
|
3
|
-
# A Ruby abstraction of an RO
|
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
|
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
|
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
|
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,34 @@ 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
|
+
#
|
72
|
+
# @return [Array<DataEntity>] Any entities that were created from the directory contents. Will be empty if `create_entities` was false.
|
73
|
+
def add_all(source_directory, create_entities = true)
|
74
|
+
added = []
|
75
|
+
|
76
|
+
Dir.chdir(source_directory) { Dir.glob('**/*') }.each do |rel_path|
|
77
|
+
source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
|
78
|
+
if create_entities
|
79
|
+
if source_path.directory?
|
80
|
+
added << add_directory(source_path, rel_path)
|
81
|
+
else
|
82
|
+
added << add_file(source_path, rel_path)
|
83
|
+
end
|
84
|
+
else
|
85
|
+
populate_entries(Pathname.new(::File.expand_path(source_directory)))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
added
|
90
|
+
end
|
91
|
+
|
64
92
|
##
|
65
93
|
# Create a new ROCrate::Person and add it to the crate
|
66
94
|
#
|
@@ -119,7 +147,7 @@ module ROCrate
|
|
119
147
|
end
|
120
148
|
|
121
149
|
##
|
122
|
-
# The RO
|
150
|
+
# The RO-Crate metadata file
|
123
151
|
#
|
124
152
|
# @return [Metadata]
|
125
153
|
def metadata
|
@@ -127,7 +155,7 @@ module ROCrate
|
|
127
155
|
end
|
128
156
|
|
129
157
|
##
|
130
|
-
# The RO
|
158
|
+
# The RO-Crate preview file
|
131
159
|
#
|
132
160
|
# @return [Preview]
|
133
161
|
def preview
|
@@ -143,7 +171,7 @@ module ROCrate
|
|
143
171
|
end
|
144
172
|
|
145
173
|
##
|
146
|
-
# Entities for the metadata file and crate itself, which should be present in all RO
|
174
|
+
# Entities for the metadata file and crate itself, which should be present in all RO-Crates.
|
147
175
|
#
|
148
176
|
# @return [Array<Entity>]
|
149
177
|
def default_entities
|
@@ -186,8 +214,9 @@ module ROCrate
|
|
186
214
|
entity.class.new(crate, entity.id, entity.raw_properties)
|
187
215
|
end
|
188
216
|
|
217
|
+
alias_method :own_entries, :entries
|
189
218
|
##
|
190
|
-
# A map of all the files/directories contained in the RO
|
219
|
+
# A map of all the files/directories contained in the RO-Crate, where the key is the destination path within the crate
|
191
220
|
# and the value is an Entry where the source data can be read.
|
192
221
|
#
|
193
222
|
# @return [Hash{String => Entry}>]
|
@@ -195,8 +224,7 @@ module ROCrate
|
|
195
224
|
entries = {}
|
196
225
|
|
197
226
|
(default_entities | data_entities).each do |entity|
|
198
|
-
|
199
|
-
entity.entries.each do |path, io|
|
227
|
+
(entity == self ? own_entries : entity.entries).each do |path, io|
|
200
228
|
entries[path] = io
|
201
229
|
end
|
202
230
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ROCrate
|
2
2
|
##
|
3
|
-
# A class to represent a "Data Entity" within an RO
|
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,17 @@ 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
|
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
|
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
|
+
populate_entries(source_directory)
|
25
25
|
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
26
|
end
|
32
27
|
|
33
28
|
super(crate, crate_path, properties)
|
@@ -50,6 +45,24 @@ module ROCrate
|
|
50
45
|
|
51
46
|
private
|
52
47
|
|
48
|
+
##
|
49
|
+
# Populate this directory with files/directories from a given source directory on disk.
|
50
|
+
#
|
51
|
+
# @param source_directory [Pathname] The source directory to populate from.
|
52
|
+
#
|
53
|
+
# @return [Hash{String => Entry}>] The files/directories that were populated.
|
54
|
+
# The key is the relative path of the file/directory, and the value is an Entry object where data can be read etc.
|
55
|
+
def populate_entries(source_directory)
|
56
|
+
raise 'Not a directory' unless ::File.directory?(source_directory)
|
57
|
+
@directory_entries = {}
|
58
|
+
Dir.chdir(source_directory) { Dir.glob('**/*') }.each do |rel_path|
|
59
|
+
source_path = Pathname.new(::File.join(source_directory, rel_path)).expand_path
|
60
|
+
@directory_entries[rel_path] = Entry.new(source_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
@directory_entries
|
64
|
+
end
|
65
|
+
|
53
66
|
def default_properties
|
54
67
|
super.merge(
|
55
68
|
'@id' => "#{SecureRandom.uuid}/",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ROCrate
|
2
2
|
##
|
3
|
-
# A generic "Entity" within an RO
|
4
|
-
# RO
|
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
|
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
|
data/lib/ro_crate/model/entry.rb
CHANGED
data/lib/ro_crate/model/file.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
data/lib/ro_crate/reader.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
module ROCrate
|
2
2
|
##
|
3
|
-
# A class to handle reading of RO
|
3
|
+
# A class to handle reading of RO-Crates from Zip files or directories.
|
4
4
|
class Reader
|
5
5
|
##
|
6
|
-
# Reads an RO
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
103
|
-
# @return [Crate] The RO
|
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
|
122
|
-
# @param source [String, ::File, Pathname] The location of the RO
|
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
|
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
|
156
|
-
# @param source [String, ::File, Pathname] The location of the RO
|
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
|
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
|
7
|
+
<meta name="keywords" content="RO-Crate">
|
8
8
|
</head>
|
9
9
|
<body>
|
10
|
-
<h1><%= name || "New RO
|
10
|
+
<h1><%= name || "New RO-Crate" %></h1>
|
11
11
|
<% if url %>
|
12
12
|
<a href="<%= url %>" target="_blank"><%= url %></a>
|
13
13
|
<% end %>
|
data/lib/ro_crate/writer.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module ROCrate
|
2
2
|
##
|
3
|
-
# A class to handle writing of RO
|
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
|
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
|
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.
|
4
|
-
s.summary = 'Create, manipulate, read RO
|
3
|
+
s.version = '0.4.2'
|
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,34 @@ 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)
|
205
|
+
|
206
|
+
assert_equal 6, entities.length
|
207
|
+
assert_equal 'ROCrate::Directory', crate.dereference('data/').class.name
|
208
|
+
assert_equal 'ROCrate::File', crate.dereference('root.txt').class.name
|
209
|
+
assert_equal 'ROCrate::File', crate.dereference('info.txt').class.name
|
210
|
+
assert_equal 'ROCrate::File', crate.dereference('data/binary.jpg').class.name
|
211
|
+
assert_equal 'ROCrate::File', crate.dereference('data/info.txt').class.name
|
212
|
+
assert_equal 'ROCrate::File', crate.dereference('data/nested.txt').class.name
|
213
|
+
|
214
|
+
assert_equal "5678\n", crate.dereference('data/info.txt').source.read
|
215
|
+
end
|
216
|
+
|
217
|
+
test 'can create an RO-Crate using content from a given directory' do
|
218
|
+
crate = ROCrate::Crate.new
|
219
|
+
entities = crate.add_all(fixture_file('directory').path, false)
|
220
|
+
|
221
|
+
assert_empty entities
|
222
|
+
|
223
|
+
# Should not create any data entities
|
224
|
+
assert_nil crate.dereference('data/')
|
225
|
+
assert_nil crate.dereference('root.txt')
|
226
|
+
assert_nil crate.dereference('info.txt')
|
227
|
+
assert_nil crate.dereference('data/binary.jpg')
|
228
|
+
assert_nil crate.dereference('data/info.txt')
|
229
|
+
assert_nil crate.dereference('data/nested.txt')
|
230
|
+
end
|
201
231
|
end
|
data/test/fixtures/directory.zip
CHANGED
Binary file
|
@@ -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/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.
|
4
|
+
version: 0.4.2
|
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-
|
11
|
+
date: 2021-02-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- test/fixtures/directory_crate/fish/info.txt
|
161
161
|
- test/fixtures/directory_crate/fish/root.txt
|
162
162
|
- test/fixtures/directory_crate/ro-crate-metadata.jsonld
|
163
|
+
- test/fixtures/directory_crate/ro-crate-preview.html
|
163
164
|
- test/fixtures/file with spaces.txt
|
164
165
|
- test/fixtures/info.txt
|
165
166
|
- test/fixtures/spaces/file with spaces.txt
|
@@ -2414,5 +2415,5 @@ requirements: []
|
|
2414
2415
|
rubygems_version: 3.0.8
|
2415
2416
|
signing_key:
|
2416
2417
|
specification_version: 4
|
2417
|
-
summary: Create, manipulate, read RO
|
2418
|
+
summary: Create, manipulate, read RO-Crates.
|
2418
2419
|
test_files: []
|