fileverse 0.1.2 → 0.1.4
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/README.md +6 -3
- data/lib/fileverse/cli.rb +36 -14
- data/lib/fileverse/files.rb +4 -0
- data/lib/fileverse/parser.rb +232 -212
- data/lib/fileverse/version.rb +1 -1
- data/lib/fileverse.rb +1 -7
- data/sample.gif +0 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b739dd6750e9f37a5720e9789800efa69c545abb67855d8f38630841f3c30870
|
4
|
+
data.tar.gz: d575e0eec8c760353b5b61d54f5e5e923cd6d261dd55d8a75533ed7079e7ecf4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c64c1dca0991f50667bf048d74f88971b0611da8e309a9287f7bb679b8b8332c7cfc221e63eb4b411a6ce144a29243ee512a25c3f48e5f75173a25fe0e382fb
|
7
|
+
data.tar.gz: f551ff2f97acabd6299fea567425425261822361b789ef6065a966a25edaebc413c6938ad0db52068ba9d8d4c1a4527ae180176acb9ed38cef95f6ac0dbde98b
|
data/README.md
CHANGED
@@ -12,14 +12,17 @@ A simple ruby cli tool for keeping different versions of a file.
|
|
12
12
|
|
13
13
|
## Commands / Shortcuts
|
14
14
|
- snap {file_path} (s)
|
15
|
-
- preview
|
16
|
-
- preview
|
15
|
+
- preview --bwd {file_path} (p)
|
16
|
+
- preview --fwd {file_path} (p)
|
17
17
|
- preview --name="" {file_path} (p)
|
18
18
|
- preview --index=0 {file_path} (p)
|
19
19
|
- reset {file_path} (x)
|
20
|
-
-
|
20
|
+
- summary {file_path} (sm)
|
21
21
|
- restore {file_path} (r)
|
22
22
|
|
23
|
+
## Sample
|
24
|
+

|
25
|
+
|
23
26
|
## Development
|
24
27
|
|
25
28
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/fileverse/cli.rb
CHANGED
@@ -6,32 +6,32 @@ module Fileverse
|
|
6
6
|
# CLI class
|
7
7
|
class CLI < Thor
|
8
8
|
desc "snap file content", "store current file content"
|
9
|
+
options template: :boolean, name: :string
|
9
10
|
def snap(path)
|
10
11
|
setup path
|
11
12
|
@parser.parse
|
12
|
-
@parser.add_snapshot(Files.read(@path))
|
13
|
+
@parser.add_snapshot(Files.read(@path), options[:name])
|
13
14
|
Files.write_content(@path)
|
14
15
|
Files.write_content(@hidden_path, @parser.to_writable_lines)
|
15
16
|
end
|
16
17
|
map "s" => "snap"
|
17
18
|
|
18
19
|
desc "restore content", "restore content in the current cursor"
|
20
|
+
options template: :boolean, name: :string
|
19
21
|
def restore(path)
|
20
22
|
setup path
|
21
23
|
@parser.parse
|
22
|
-
|
23
|
-
@parser.remove_cursor_snapshot
|
24
|
-
Files.write_content(@hidden_path, @parser.to_writable_lines)
|
24
|
+
options[:template] ? restore_template : restore_snapshot
|
25
25
|
end
|
26
26
|
map "r" => "restore"
|
27
27
|
|
28
28
|
desc "preview snapshot", "preview snapshot at different index or name"
|
29
|
-
options bwd: :boolean, fwd: :boolean, index: :numeric, name: :string
|
29
|
+
options bwd: :boolean, fwd: :boolean, index: :numeric, name: :string, template: :boolean
|
30
30
|
def preview(path)
|
31
31
|
setup path
|
32
32
|
@parser.parse
|
33
33
|
@previewer.parse
|
34
|
-
|
34
|
+
@previewer.preview_content = preview_content
|
35
35
|
Files.write_content(@path, @previewer.to_writable_lines)
|
36
36
|
Files.write_content(@hidden_path, @parser.to_writable_lines)
|
37
37
|
end
|
@@ -49,24 +49,46 @@ module Fileverse
|
|
49
49
|
end
|
50
50
|
map "x" => "reset"
|
51
51
|
|
52
|
+
desc "summary", "return all the summary of snapshots"
|
53
|
+
def summary(path)
|
54
|
+
setup path
|
55
|
+
@parser.parse_head
|
56
|
+
puts @parser.summary
|
57
|
+
end
|
58
|
+
map "sm" => "summary"
|
59
|
+
|
52
60
|
private
|
53
61
|
|
54
62
|
def setup(path)
|
55
63
|
@path = Files.expand_path(path)
|
56
|
-
@hidden_path = Files.expand_hidden_path(path)
|
57
|
-
@parser = Parser
|
64
|
+
@hidden_path = options[:template] ? Files.template_path : Files.expand_hidden_path(path)
|
65
|
+
@parser = Parser.new(@hidden_path)
|
58
66
|
@previewer = Previewer.new(@path)
|
59
67
|
end
|
60
68
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
69
|
+
def restore_snapshot
|
70
|
+
Files.write_content(@path, @parser.cursor_content)
|
71
|
+
@parser.remove_cursor_snapshot
|
72
|
+
Files.write_content(@hidden_path, @parser.to_writable_lines)
|
73
|
+
end
|
74
|
+
|
75
|
+
def restore_template
|
76
|
+
template_content = @parser.snapshot_content_by_name(options[:name])
|
77
|
+
return if template_content.nil?
|
78
|
+
|
79
|
+
Files.write_content(@path, template_content)
|
80
|
+
end
|
81
|
+
|
82
|
+
def preview_content
|
83
|
+
if options[:name]
|
84
|
+
@parser.snapshot_content_by_name(options[:name])
|
85
|
+
elsif options[:bwd]
|
86
|
+
@parser.snapshot_content_backward
|
64
87
|
elsif options[:fwd]
|
65
|
-
@parser.
|
88
|
+
@parser.snapshot_content_forward
|
66
89
|
elsif options[:index]
|
67
|
-
@parser.
|
90
|
+
@parser.snapshot_content_by_index(options[:index])
|
68
91
|
end
|
69
|
-
@previewer.preview_content = @parser.cursor_content
|
70
92
|
end
|
71
93
|
end
|
72
94
|
end
|
data/lib/fileverse/files.rb
CHANGED
data/lib/fileverse/parser.rb
CHANGED
@@ -1,260 +1,280 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Fileverse
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
@snapshots = []
|
81
|
-
@templates = []
|
82
|
-
end
|
4
|
+
# Fileverse::Parser : is the main parser for the storage file.
|
5
|
+
# Lets take a storage file example:
|
6
|
+
#
|
7
|
+
# == Storage file Example content
|
8
|
+
#
|
9
|
+
# <######0
|
10
|
+
# shot> 6 ~> 9
|
11
|
+
# 9 ~> 12
|
12
|
+
# 12 ~> 15
|
13
|
+
# 15 ~> 18
|
14
|
+
# ######>
|
15
|
+
# // New file
|
16
|
+
# // Write here
|
17
|
+
# // When you can
|
18
|
+
# File 1
|
19
|
+
# Content 1 of file 1
|
20
|
+
# Content 2 of file 1
|
21
|
+
# File 2
|
22
|
+
# Content 1 of file 2
|
23
|
+
# Content 2 of file 2
|
24
|
+
# File 3
|
25
|
+
# Content 1 of file 3
|
26
|
+
# Content 2 of file 3
|
27
|
+
#
|
28
|
+
#
|
29
|
+
# == Example end
|
30
|
+
#
|
31
|
+
# It uses the head section which is what is between "<######{cursor}" and "######>" as the table to parse the file.
|
32
|
+
# Each line is a range represented like "{name}> {start} ~> {stop}". the "{name}>" part is optional.
|
33
|
+
# so the above example will parse as follows:
|
34
|
+
#
|
35
|
+
# - shot> 6 ~> 9
|
36
|
+
#
|
37
|
+
# =======================================
|
38
|
+
# | // New file
|
39
|
+
# | // Write here
|
40
|
+
# | // When you can
|
41
|
+
# ======================================
|
42
|
+
#
|
43
|
+
# - 9 ~> 12
|
44
|
+
#
|
45
|
+
# =======================================
|
46
|
+
# | File 1
|
47
|
+
# | Content 1 of file 1
|
48
|
+
# | Content 2 of file 1
|
49
|
+
# ======================================
|
50
|
+
#
|
51
|
+
# - 12 ~> 15
|
52
|
+
#
|
53
|
+
# =======================================
|
54
|
+
# | File 2
|
55
|
+
# | Content 1 of file 2
|
56
|
+
# | Content 2 of file 2
|
57
|
+
# ======================================
|
58
|
+
#
|
59
|
+
# - 15 ~> 18
|
60
|
+
#
|
61
|
+
# =======================================
|
62
|
+
# | File 3
|
63
|
+
# | Content 1 of file 3
|
64
|
+
# | Content 2 of file 3
|
65
|
+
# ======================================
|
66
|
+
#
|
67
|
+
class Parser # rubocop:disable Metrics/ClassLength
|
68
|
+
START_TAG = "<######"
|
69
|
+
CLOSE_TAG = "######>"
|
70
|
+
|
71
|
+
attr_reader :path, :cursor, :line_index
|
72
|
+
|
73
|
+
def initialize(path)
|
74
|
+
@path = path
|
75
|
+
@iterator = File.foreach(path, chomp: true)
|
76
|
+
@line_index = 0
|
77
|
+
@cursor = -1
|
78
|
+
@snapshots = []
|
79
|
+
end
|
83
80
|
|
84
|
-
|
85
|
-
|
81
|
+
def parse
|
82
|
+
return unless File.exist?(@path) && !peek_line.nil?
|
86
83
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
parse_snapshots
|
84
|
+
verify_first_header
|
85
|
+
parse_header_snapshot_lines
|
86
|
+
parse_snapshots
|
91
87
|
|
92
|
-
|
93
|
-
|
88
|
+
raise CorruptFormat, " Content remains after parsing." unless peek_line.nil?
|
89
|
+
end
|
94
90
|
|
95
|
-
|
96
|
-
|
97
|
-
|
91
|
+
def snapshot_count
|
92
|
+
@snapshots.length
|
93
|
+
end
|
98
94
|
|
99
|
-
|
100
|
-
|
101
|
-
start = last_snapshot&.stop || 3
|
102
|
-
snapshot = Snapshot.new(start, start + content.length)
|
103
|
-
snapshot.content = content
|
104
|
-
last_snapshot&.next_snapshot = snapshot
|
105
|
-
@snapshots.push(snapshot)
|
106
|
-
reset
|
107
|
-
end
|
95
|
+
def add_snapshot(content, name = nil)
|
96
|
+
return if name && update_named_snapshot(name, content)
|
108
97
|
|
109
|
-
|
110
|
-
|
111
|
-
|
98
|
+
prev_snapshot = @snapshots[-1]
|
99
|
+
start = prev_snapshot&.stop || 3
|
100
|
+
snapshot = Snapshot.new(start, start + content.length, name)
|
101
|
+
snapshot.content = content
|
102
|
+
prev_snapshot&.next_snapshot = snapshot
|
103
|
+
@snapshots.push(snapshot)
|
104
|
+
reset
|
105
|
+
end
|
112
106
|
|
113
|
-
|
114
|
-
|
115
|
-
return unless snapshot
|
107
|
+
def cursor_content
|
108
|
+
raise InvalidCursorPointer if @cursor.negative? || @cursor > @snapshots.length
|
116
109
|
|
117
|
-
|
118
|
-
|
119
|
-
@snapshots = @snapshots[0, @cursor].concat(@snapshots[@cursor + 1..])
|
120
|
-
reset
|
121
|
-
end
|
110
|
+
@snapshots[@cursor].content
|
111
|
+
end
|
122
112
|
|
123
|
-
|
124
|
-
|
125
|
-
|
113
|
+
def snapshot_content_by_name(name)
|
114
|
+
find_named_snapshot(name)&.content
|
115
|
+
end
|
126
116
|
|
127
|
-
|
128
|
-
|
117
|
+
def snapshot_content_by_index(index)
|
118
|
+
raise InvalidCursorPointer if index.negative? || index > @snapshots.length
|
129
119
|
|
130
|
-
|
131
|
-
|
120
|
+
@cursor = value
|
121
|
+
cursor_content
|
122
|
+
end
|
132
123
|
|
133
|
-
|
134
|
-
|
124
|
+
def snapshot_content_backward
|
125
|
+
decrement_cursor
|
126
|
+
cursor_content
|
127
|
+
end
|
135
128
|
|
136
|
-
|
137
|
-
|
129
|
+
def snapshot_content_forward
|
130
|
+
increment_cursor
|
131
|
+
cursor_content
|
132
|
+
end
|
138
133
|
|
139
|
-
|
140
|
-
|
134
|
+
def remove_cursor_snapshot
|
135
|
+
snapshot = @snapshots[@cursor]
|
136
|
+
return unless snapshot
|
141
137
|
|
142
|
-
|
143
|
-
|
138
|
+
snapshot_before = @snapshots[@cursor - 1]
|
139
|
+
snapshot_before.next_snapshot = snapshot.next_snapshot if snapshot_before
|
140
|
+
@snapshots = @snapshots[0, @cursor].concat(@snapshots[@cursor + 1..])
|
141
|
+
reset
|
142
|
+
end
|
144
143
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
144
|
+
def to_writable_lines
|
145
|
+
[*head_lines, *snapshot_lines]
|
146
|
+
end
|
149
147
|
|
150
|
-
|
148
|
+
def reset
|
149
|
+
@cursor = @snapshots.length - 1
|
150
|
+
@snapshots[0]&.update_start @snapshots.length + 2
|
151
|
+
end
|
151
152
|
|
152
|
-
|
153
|
-
|
154
|
-
/\A<\#{6}(?<cursor>-?\d+)\z/ =~ first_line
|
155
|
-
raise CorruptFormat, " Error parsing header" unless cursor
|
153
|
+
def parse_head
|
154
|
+
return unless File.exist?(@path) && !peek_line.nil?
|
156
155
|
|
157
|
-
|
158
|
-
|
156
|
+
verify_first_header
|
157
|
+
parse_header_snapshot_lines
|
158
|
+
end
|
159
159
|
|
160
|
-
|
161
|
-
loop do
|
162
|
-
break unless /\A\s*template>(?<name>\w+)>\s*(?<start>\d+)\s*~>\s*(?<stop>\d+)\s*\z/ =~ peek_line
|
160
|
+
private
|
163
161
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
end
|
162
|
+
def update_named_snapshot(name, content)
|
163
|
+
snapshot = find_named_snapshot(name)
|
164
|
+
return false unless snapshot
|
168
165
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
break if line == CLOSE_TAG
|
166
|
+
snapshot.content = content
|
167
|
+
reset
|
168
|
+
true
|
169
|
+
end
|
174
170
|
|
175
|
-
|
176
|
-
|
177
|
-
|
171
|
+
def find_named_snapshot(name)
|
172
|
+
@snapshots.find { |snapshot| snapshot.name == name }
|
173
|
+
end
|
178
174
|
|
179
|
-
|
180
|
-
|
181
|
-
|
175
|
+
def decrement_cursor
|
176
|
+
raise InvalidCursorPointer if (@cursor - 1).negative?
|
177
|
+
|
178
|
+
@cursor -= 1
|
179
|
+
end
|
180
|
+
|
181
|
+
def increment_cursor
|
182
|
+
raise InvalidCursorPointer if @cursor + 1 >= @snapshots.length
|
182
183
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
184
|
+
@cursor += 1
|
185
|
+
end
|
186
|
+
|
187
|
+
def verify_first_header
|
188
|
+
first_line = next_line
|
189
|
+
/\A<\#{6}(?<cursor>-?\d+)\z/ =~ first_line
|
190
|
+
raise CorruptFormat, " Error parsing header" unless cursor
|
191
|
+
|
192
|
+
@cursor = cursor.to_i
|
193
|
+
end
|
187
194
|
|
188
|
-
|
195
|
+
def parse_header_snapshot_lines
|
196
|
+
loop do
|
197
|
+
line = next_line
|
198
|
+
unless /\A\s*(?<name>\w*>)?\s*(?<start>\d+)\s*~>\s*(?<stop>\d+)\s*\z/ =~ line
|
199
|
+
break if line == CLOSE_TAG
|
189
200
|
|
190
|
-
|
191
|
-
last_snap = snap
|
201
|
+
raise CorruptFormat, "Unknow format found."
|
192
202
|
end
|
193
|
-
|
203
|
+
raise CorruptFormat, "Start index cannot be larger than stop." if stop.to_i < start.to_i
|
194
204
|
|
195
|
-
|
196
|
-
result = []
|
197
|
-
(snap.stop - snap.start).times { result.push next_line }
|
198
|
-
result
|
205
|
+
@snapshots.push Snapshot.new(start.to_i, stop.to_i, name&.chomp(">"))
|
199
206
|
end
|
207
|
+
end
|
200
208
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
raise CorruptFormat, " No content to parse."
|
206
|
-
end
|
209
|
+
def parse_snapshots
|
210
|
+
last_snap = nil
|
211
|
+
[*@snapshots].each do |snap|
|
212
|
+
raise CorruptFormat, " Wrong indexing in header." if line_index != snap.start
|
207
213
|
|
208
|
-
|
209
|
-
@iterator.peek
|
210
|
-
rescue StopIteration
|
211
|
-
nil
|
212
|
-
end
|
214
|
+
snap.content = parse_snap_content(snap)
|
213
215
|
|
214
|
-
|
215
|
-
|
216
|
-
"#{START_TAG}#{cursor}",
|
217
|
-
*@templates.map { |template| "template>#{template.name}> #{template.start} ~> #{template.stop}" },
|
218
|
-
*@snapshots.map { |snap| "#{snap.start} ~> #{snap.stop}" },
|
219
|
-
CLOSE_TAG
|
220
|
-
]
|
216
|
+
last_snap&.next_snapshot = snap
|
217
|
+
last_snap = snap
|
221
218
|
end
|
219
|
+
end
|
222
220
|
|
223
|
-
|
224
|
-
|
225
|
-
|
221
|
+
def parse_snap_content(snap)
|
222
|
+
result = []
|
223
|
+
(snap.stop - snap.start).times { result.push next_line }
|
224
|
+
result
|
225
|
+
end
|
226
226
|
|
227
|
-
|
228
|
-
|
229
|
-
|
227
|
+
def next_line
|
228
|
+
@line_index += 1
|
229
|
+
@iterator.next
|
230
|
+
rescue StopIteration
|
231
|
+
raise CorruptFormat, " No content to parse."
|
232
|
+
end
|
230
233
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
234
|
+
def peek_line
|
235
|
+
@iterator.peek
|
236
|
+
rescue StopIteration
|
237
|
+
nil
|
238
|
+
end
|
235
239
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
240
|
+
def head_lines
|
241
|
+
[
|
242
|
+
"#{START_TAG}#{cursor}",
|
243
|
+
*@snapshots.map { |snap| "#{snap.name ? "#{snap.name}>" : ""}#{snap.start} ~> #{snap.stop}" },
|
244
|
+
CLOSE_TAG
|
245
|
+
]
|
246
|
+
end
|
241
247
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
end
|
248
|
+
def snapshot_lines
|
249
|
+
@snapshots.map(&:content).flatten
|
250
|
+
end
|
246
251
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
252
|
+
# Snapshot for each file
|
253
|
+
class Snapshot
|
254
|
+
attr_reader :start, :stop, :name, :content
|
255
|
+
attr_accessor :next_snapshot
|
251
256
|
|
252
|
-
|
257
|
+
def initialize(start, stop, name = nil)
|
258
|
+
@start = start
|
259
|
+
@stop = stop
|
260
|
+
@name = name
|
261
|
+
end
|
253
262
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
263
|
+
def content=(value)
|
264
|
+
@content = value
|
265
|
+
update_stop
|
266
|
+
end
|
267
|
+
|
268
|
+
def update_start(new_start)
|
269
|
+
@start = new_start
|
270
|
+
update_stop
|
271
|
+
end
|
272
|
+
|
273
|
+
private
|
274
|
+
|
275
|
+
def update_stop
|
276
|
+
@stop = start + content.length
|
277
|
+
next_snapshot&.update_start @stop
|
258
278
|
end
|
259
279
|
end
|
260
280
|
end
|
data/lib/fileverse/version.rb
CHANGED
data/lib/fileverse.rb
CHANGED
@@ -7,12 +7,6 @@ require_relative "fileverse/parser"
|
|
7
7
|
require_relative "fileverse/previewer"
|
8
8
|
|
9
9
|
# Parent module
|
10
|
-
module Fileverse
|
11
|
-
def self.create_hidden_file(path)
|
12
|
-
File.open(path, "w") do |writer|
|
13
|
-
writer.write(inital_header)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
10
|
+
module Fileverse; end
|
17
11
|
|
18
12
|
require_relative "fileverse/cli"
|
data/sample.gif
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fileverse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unegbu Kingsley
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -49,6 +49,7 @@ files:
|
|
49
49
|
- lib/fileverse/parser.rb
|
50
50
|
- lib/fileverse/previewer.rb
|
51
51
|
- lib/fileverse/version.rb
|
52
|
+
- sample.gif
|
52
53
|
- sig/fileverse.rbs
|
53
54
|
homepage: https://github.com/urchmaney/fileverse
|
54
55
|
licenses:
|