browser.rb 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +516 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +116 -0
  6. data/Rakefile +182 -0
  7. data/browser.rb.gemspec +54 -0
  8. data/lib/Browser/Base.rb +50 -0
  9. data/lib/Browser/Bookmark.rb +41 -0
  10. data/lib/Browser/Bookmarks.rb +112 -0
  11. data/lib/Browser/Brave.rb +16 -0
  12. data/lib/Browser/Chrome.rb +16 -0
  13. data/lib/Browser/Chromium.rb +16 -0
  14. data/lib/Browser/ChromiumBased.rb +48 -0
  15. data/lib/Browser/Firefox.rb +16 -0
  16. data/lib/Browser/FirefoxBased.rb +86 -0
  17. data/lib/Browser/History.rb +41 -0
  18. data/lib/Browser/Rendering.rb +108 -0
  19. data/lib/Browser/Safari.rb +48 -0
  20. data/lib/Browser/TorBrowser.rb +26 -0
  21. data/lib/Browser/Unreadable.rb +11 -0
  22. data/lib/Browser/VERSION.rb +6 -0
  23. data/lib/browser-classes.rb +12 -0
  24. data/lib/browser.rb +29 -0
  25. data/test/Browser/Bookmark_test.rb +72 -0
  26. data/test/Browser/Brave_test.rb +143 -0
  27. data/test/Browser/Chrome_test.rb +143 -0
  28. data/test/Browser/Chromium_test.rb +143 -0
  29. data/test/Browser/Firefox_test.rb +205 -0
  30. data/test/Browser/Rendering_test.rb +68 -0
  31. data/test/Browser/Safari_test.rb +152 -0
  32. data/test/Browser/TorBrowser_test.rb +147 -0
  33. data/test/browser_test.rb +33 -0
  34. data/test/fixtures/Brave_bookmarks.json +47 -0
  35. data/test/fixtures/ChromiumBased_history.sqlite +0 -0
  36. data/test/fixtures/Chromium_bookmarks.json +47 -0
  37. data/test/fixtures/FirefoxBased_places.sqlite +0 -0
  38. data/test/fixtures/Safari_bookmarks.plist +0 -0
  39. data/test/fixtures/Safari_history.sqlite +0 -0
  40. data/test/gemspec_test.rb +42 -0
  41. data/test/loading_test.rb +35 -0
  42. metadata +194 -0
@@ -0,0 +1,147 @@
1
+ # TorBrowser_test.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+ require 'rspec/expectations/minitest_integration'
9
+
10
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', 'lib'))
11
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'browser'
14
+
15
+ describe Browser::TorBrowser do
16
+ let(:places_fixtures_location){File.expand_path("#{__FILE__}/../../fixtures/FirefoxBased_places.sqlite")}
17
+ let(:expected_bookmarks_sql){'SELECT moz_bookmarks.id, moz_bookmarks.parent, moz_bookmarks.position, moz_bookmarks.type, moz_bookmarks.title, moz_bookmarks.guid, moz_places.url FROM moz_bookmarks LEFT JOIN moz_places ON moz_bookmarks.fk = moz_places.id ORDER BY moz_bookmarks.parent, moz_bookmarks.position;'}
18
+ let(:expected_history_sql){'SELECT moz_historyvisits.id, moz_places.url, moz_places.title, moz_historyvisits.visit_date FROM moz_historyvisits LEFT JOIN moz_places ON moz_historyvisits.place_id = moz_places.id ORDER BY moz_historyvisits.visit_date DESC;'}
19
+
20
+ describe '.default_profile_name' do
21
+ let(:profiles_ini){"[Profile0]\nName=default\nIsRelative=1\nPath=abcd1234.default\nDefault=1\n\n[General]\nStartWithLastProfile=1\nVersion=2\n"}
22
+
23
+ it "is the one profile Tor Browser flags, which sits beside profiles.ini rather than under Profiles" do
24
+ expect(Browser::TorBrowser.default_profile_name(profiles_ini)).to eq('abcd1234.default')
25
+ end
26
+ end
27
+
28
+ let(:profile_name){'abcd1234.default'}
29
+
30
+ context "class methods" do
31
+ subject{Browser::TorBrowser}
32
+
33
+ describe '.bookmarks_location' do
34
+ let(:expected_bookmarks_location){File.expand_path('~/Library/Application Support/TorBrowser-Data/Browser/abcd1234.default/places.sqlite')}
35
+
36
+ it "contains the correct bookmarks location" do
37
+ expect(subject.bookmarks_location(profile_name: profile_name)).to eq(expected_bookmarks_location)
38
+ end
39
+ end
40
+
41
+ describe '.history_location' do
42
+ let(:expected_history_location){File.expand_path('~/Library/Application Support/TorBrowser-Data/Browser/abcd1234.default/places.sqlite')}
43
+
44
+ it "contains the correct history location" do
45
+ expect(subject.history_location(profile_name: profile_name)).to eq(expected_history_location)
46
+ end
47
+ end
48
+
49
+ describe ".bookmarks_sql" do
50
+ it "returns the bookmarks sql" do
51
+ expect(subject.send(:bookmarks_sql)).to eq(expected_bookmarks_sql)
52
+ end
53
+ end
54
+
55
+ describe ".history_sql" do
56
+ it "returns the history sql" do
57
+ expect(subject.send(:history_sql)).to eq(expected_history_sql)
58
+ end
59
+ end
60
+ end
61
+
62
+ context "instance methods" do
63
+ subject{Browser::TorBrowser.new(bookmarks_location: places_fixtures_location, history_location: places_fixtures_location, profile_name: profile_name)}
64
+
65
+ let(:browser_name){'TorBrowser'}
66
+ let(:expected_history) do
67
+ [
68
+ {'id' => 1, 'url' => 'https://addons.mozilla.org/en-US/firefox/', 'title' => 'Extension Starter Pack', 'visit_date' => 1787449152741667},
69
+ ]
70
+ end
71
+
72
+ describe "#initialize" do
73
+ it "returns an instance of Browser" do
74
+ expect(subject).to be_a(Browser::TorBrowser)
75
+ end
76
+
77
+ it "assigns @bookmarks_location" do
78
+ expect(subject.instance_variable_get(:@bookmarks_location)).to eq(places_fixtures_location)
79
+ end
80
+
81
+ it "assigns @history_location" do
82
+ expect(subject.instance_variable_get(:@history_location)).to eq(places_fixtures_location)
83
+ end
84
+
85
+ it "assigns @profile_name" do
86
+ expect(subject.instance_variable_get(:@profile_name)).to eq(profile_name)
87
+ end
88
+ end
89
+
90
+ describe "#name" do
91
+ it "returns name" do
92
+ expect(subject.name).to eq(browser_name)
93
+ end
94
+ end
95
+
96
+ let(:expected_bookmarks) do
97
+ [
98
+ {title: 'Get Help', url: 'https://support.mozilla.org/products/firefox', folder: 'Bookmarks Menu/Mozilla Firefox'},
99
+ {title: 'Customize Firefox', url: 'https://support.mozilla.org/kb/customize-firefox-controls-buttons-and-toolbars', folder: 'Bookmarks Menu/Mozilla Firefox'},
100
+ {title: 'Get Involved', url: 'https://www.mozilla.org/contribute/', folder: 'Bookmarks Menu/Mozilla Firefox'},
101
+ {title: 'About Us', url: 'https://www.mozilla.org/about/', folder: 'Bookmarks Menu/Mozilla Firefox'},
102
+ {title: 'Extension Starter Pack', url: 'https://addons.mozilla.org/en-US/firefox/', folder: 'Bookmarks Toolbar'},
103
+ ]
104
+ end
105
+
106
+ describe "#bookmarks" do
107
+ it "returns an instance of Browser::Bookmarks" do
108
+ expect(subject.bookmarks).to be_a(Browser::Bookmarks)
109
+ end
110
+
111
+ it "returns the bookmarks" do
112
+ expect(subject.bookmarks.to_objects).to eq(expected_bookmarks)
113
+ end
114
+ end
115
+
116
+ describe "#history" do
117
+ it "returns an instance of Browser::History" do
118
+ expect(subject.history).to be_a(Browser::History)
119
+ end
120
+
121
+ it "returns the history" do
122
+ expect(subject.history.to_json).to eq(expected_history.to_json)
123
+ end
124
+ end
125
+
126
+ describe "#readable?" do
127
+ it "is true when the data is there" do
128
+ expect(subject.bookmarks.readable?).to be(true)
129
+ expect(subject.history.readable?).to be(true)
130
+ end
131
+ end
132
+
133
+ context "WHEN the data is not there" do
134
+ subject{Browser::TorBrowser.new(bookmarks_location: '/nonexistent/file', history_location: '/nonexistent/file')}
135
+
136
+ it "is not readable" do
137
+ expect(subject.bookmarks.readable?).to be(false)
138
+ expect(subject.history.readable?).to be(false)
139
+ end
140
+
141
+ it "raises Browser::Unreadable" do
142
+ expect{subject.bookmarks.to_json}.to raise_error(Browser::Unreadable)
143
+ expect{subject.history.to_json}.to raise_error(Browser::Unreadable)
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,33 @@
1
+ # Browser_test.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+ require 'rspec/expectations/minitest_integration'
9
+
10
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
11
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'browser'
14
+
15
+ describe Browser do
16
+ describe Browser::LIST do
17
+ it "contains the expected list of browsers" do
18
+ expect(Browser::LIST).to eq(%w{
19
+ Brave
20
+ Chrome
21
+ Chromium
22
+ Firefox
23
+ Safari
24
+ TorBrowser
25
+ })
26
+ end
27
+ end
28
+
29
+ Browser::LIST.each do |browser|
30
+ browser_test_filename = File.expand_path("#{__FILE__}/../Browser/#{browser}_test")
31
+ require browser_test_filename
32
+ end
33
+ end
@@ -0,0 +1,47 @@
1
+ {
2
+ "checksum": "1f23f6aebb42e587a2171e6563b63893",
3
+ "roots": {
4
+ "bookmark_bar": {
5
+ "children": [ {
6
+ "date_added": "13314548862466117",
7
+ "date_last_used": "0",
8
+ "guid": "205d9fcc-e76c-4cbf-bb7e-8e9de7847eaa",
9
+ "id": "5",
10
+ "meta_info": {
11
+ "power_bookmark_meta": ""
12
+ },
13
+ "name": "Welcome to Brave",
14
+ "type": "url",
15
+ "url": "chrome://welcome/"
16
+ } ],
17
+ "date_added": "13314548615807175",
18
+ "date_last_used": "0",
19
+ "date_modified": "13314548862466117",
20
+ "guid": "0bc5d13f-2cba-5d74-951f-3f233fe6c908",
21
+ "id": "1",
22
+ "name": "Bookmarks bar",
23
+ "type": "folder"
24
+ },
25
+ "other": {
26
+ "children": [ ],
27
+ "date_added": "13314548615807200",
28
+ "date_last_used": "0",
29
+ "date_modified": "0",
30
+ "guid": "82b081ec-3dd3-529c-8475-ab6c344590dd",
31
+ "id": "2",
32
+ "name": "Other Bookmarks",
33
+ "type": "folder"
34
+ },
35
+ "synced": {
36
+ "children": [ ],
37
+ "date_added": "13314548615807201",
38
+ "date_last_used": "0",
39
+ "date_modified": "0",
40
+ "guid": "4cf2e351-0e85-532b-bb37-df045d8f8d0f",
41
+ "id": "3",
42
+ "name": "Mobile Bookmarks",
43
+ "type": "folder"
44
+ }
45
+ },
46
+ "version": 1
47
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "checksum": "4ac0a80dc7d6a7daa73deb6c6731bca1",
3
+ "roots": {
4
+ "bookmark_bar": {
5
+ "children": [ {
6
+ "date_added": "13314699512289860",
7
+ "date_last_used": "0",
8
+ "guid": "2a8fdff0-de3b-4c0a-8364-74e44677cfbb",
9
+ "id": "5",
10
+ "meta_info": {
11
+ "power_bookmark_meta": ""
12
+ },
13
+ "name": "Home",
14
+ "type": "url",
15
+ "url": "https://www.chromium.org/chromium-projects/"
16
+ } ],
17
+ "date_added": "13314699403179560",
18
+ "date_last_used": "0",
19
+ "date_modified": "13314699512289860",
20
+ "guid": "0bc5d13f-2cba-5d74-951f-3f233fe6c908",
21
+ "id": "1",
22
+ "name": "Bookmarks Bar",
23
+ "type": "folder"
24
+ },
25
+ "other": {
26
+ "children": [ ],
27
+ "date_added": "13314699403179566",
28
+ "date_last_used": "0",
29
+ "date_modified": "0",
30
+ "guid": "82b081ec-3dd3-529c-8475-ab6c344590dd",
31
+ "id": "2",
32
+ "name": "Other Bookmarks",
33
+ "type": "folder"
34
+ },
35
+ "synced": {
36
+ "children": [ ],
37
+ "date_added": "13314699403179569",
38
+ "date_last_used": "0",
39
+ "date_modified": "0",
40
+ "guid": "4cf2e351-0e85-532b-bb37-df045d8f8d0f",
41
+ "id": "3",
42
+ "name": "Mobile Bookmarks",
43
+ "type": "folder"
44
+ }
45
+ },
46
+ "version": 1
47
+ }
Binary file
@@ -0,0 +1,42 @@
1
+ # gemspec_test.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+ require 'rspec/expectations/minitest_integration'
9
+
10
+ lib_dir = File.expand_path(File.join(__FILE__, '..', '..', 'lib'))
11
+ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'browser'
14
+
15
+ describe 'browser.rb.gemspec' do
16
+ let(:spec){Gem::Specification.load(File.expand_path('../browser.rb.gemspec', __dir__))}
17
+
18
+ it "is a valid specification" do
19
+ expect(spec.validate).to be(true)
20
+ end
21
+
22
+ it "does not pin a date" do
23
+ expect(spec.date).to eq(Gem::Specification.new.date)
24
+ end
25
+
26
+ it "takes its version from Browser::VERSION" do
27
+ expect(spec.version.to_s).to eq(Browser::VERSION)
28
+ end
29
+
30
+ it "declares its runtime dependencies" do
31
+ expect(spec.runtime_dependencies.map(&:name).sort).to eq(%w{CFPropertyList csv json sqlite3})
32
+ end
33
+
34
+ it "declares its development dependencies" do
35
+ expect(spec.development_dependencies.map(&:name).sort).to eq(%w{minitest minitest-spec-context rake rspec-expectations})
36
+ end
37
+
38
+ it "ships the files a consumer reads, and no file which is not there" do
39
+ expect(spec.files).to include('README.md', 'CHANGELOG', 'LICENSE')
40
+ expect(spec.files.reject{|file| File.exist?(File.expand_path("../#{file}", __dir__))}).to eq([])
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ # loading_test.rb
2
+
3
+ gem 'minitest'
4
+ gem 'minitest-spec-context'
5
+
6
+ require 'minitest/autorun'
7
+ require 'minitest-spec-context'
8
+ require 'rspec/expectations/minitest_integration'
9
+
10
+ # Each of these wants a process of its own, with nothing on the load path but lib and no
11
+ # RUBYLIB, which is what a consumer of the gem has: within this one everything is loaded
12
+ # already, so nothing here could tell a require which works from one which was never run.
13
+
14
+ describe 'loading' do
15
+ def ruby(source, *flags)
16
+ lib = File.expand_path('../lib', __dir__)
17
+ IO.popen({'RUBYLIB' => nil}, ['ruby', *flags, "-I#{lib}", '-e', source], err: [:child, :out]){|io| io.read}.strip
18
+ end
19
+
20
+ it "defines Browser::VERSION on require 'browser'" do
21
+ expect(ruby('require "browser"; print Browser::VERSION')).to match(/\A\d+\.\d+\.\d+\z/)
22
+ end
23
+
24
+ it "patches no core class, nothing under lib/Array or lib/String remaining" do
25
+ expect(ruby('require "browser"; print $LOADED_FEATURES.grep(%r{/lib/(Array|String)/}).size')).to eq('0')
26
+ end
27
+
28
+ it "gives the top-level names on require 'browser-classes'" do
29
+ expect(ruby('require "browser-classes"; print Chrome.equal?(Browser::Chrome)')).to eq('true')
30
+ end
31
+
32
+ it "loads without warning under -w" do
33
+ expect(ruby('require "browser"; require "browser-classes"; print "ok"', '-w')).to eq('ok')
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: browser.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.16.0
5
+ platform: ruby
6
+ authors:
7
+ - thoran
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: CFPropertyList
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: csv
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: json
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: sqlite3
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: minitest
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: minitest-spec-context
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec-expectations
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ description: Read the bookmarks and history of the web browsers on a machine, Brave,
125
+ Chrome, Chromium, Firefox, Safari and Tor Browser, and render them to CSV, JSON
126
+ or a property list. Bookmarks come through as one representation whatever the browser;
127
+ history as each browser stores it.
128
+ email: code@thoran.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - CHANGELOG
134
+ - Gemfile
135
+ - LICENSE
136
+ - README.md
137
+ - Rakefile
138
+ - browser.rb.gemspec
139
+ - lib/Browser/Base.rb
140
+ - lib/Browser/Bookmark.rb
141
+ - lib/Browser/Bookmarks.rb
142
+ - lib/Browser/Brave.rb
143
+ - lib/Browser/Chrome.rb
144
+ - lib/Browser/Chromium.rb
145
+ - lib/Browser/ChromiumBased.rb
146
+ - lib/Browser/Firefox.rb
147
+ - lib/Browser/FirefoxBased.rb
148
+ - lib/Browser/History.rb
149
+ - lib/Browser/Rendering.rb
150
+ - lib/Browser/Safari.rb
151
+ - lib/Browser/TorBrowser.rb
152
+ - lib/Browser/Unreadable.rb
153
+ - lib/Browser/VERSION.rb
154
+ - lib/browser-classes.rb
155
+ - lib/browser.rb
156
+ - test/Browser/Bookmark_test.rb
157
+ - test/Browser/Brave_test.rb
158
+ - test/Browser/Chrome_test.rb
159
+ - test/Browser/Chromium_test.rb
160
+ - test/Browser/Firefox_test.rb
161
+ - test/Browser/Rendering_test.rb
162
+ - test/Browser/Safari_test.rb
163
+ - test/Browser/TorBrowser_test.rb
164
+ - test/browser_test.rb
165
+ - test/fixtures/Brave_bookmarks.json
166
+ - test/fixtures/ChromiumBased_history.sqlite
167
+ - test/fixtures/Chromium_bookmarks.json
168
+ - test/fixtures/FirefoxBased_places.sqlite
169
+ - test/fixtures/Safari_bookmarks.plist
170
+ - test/fixtures/Safari_history.sqlite
171
+ - test/gemspec_test.rb
172
+ - test/loading_test.rb
173
+ homepage: https://github.com/thoran/browser
174
+ licenses:
175
+ - MIT
176
+ metadata: {}
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '3.2'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubygems_version: 4.0.21
192
+ specification_version: 4
193
+ summary: Read web browser bookmarks and history with Ruby.
194
+ test_files: []