searchlink 2.3.71 → 2.3.72
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/lib/searchlink/searches/duckduckgo.rb +19 -10
- data/lib/searchlink/searches/helpers/safari.rb +1 -1
- data/lib/searchlink/searches/linkding.rb +213 -0
- data/lib/searchlink/searches.rb +62 -52
- data/lib/searchlink/version.rb +1 -1
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6e6eec4235b7ab5dd818a599ccd7ece852d6328233d2a81b8738447a581e046
|
4
|
+
data.tar.gz: 2e11a49af2da708369bde197c02b247875c41d6591fedbbb8e2b80a339819332
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7c755596c600f2ce59a02a7b4e4199efa726613ae085cb0cd1f9998fec0fae7d384597f57d5b1c5258ba45d9d2abfb7cd148d533ec35406d01fcb186385b77c
|
7
|
+
data.tar.gz: 461e781699e0f1f04eaf46d28215b0fecf1447da6784025505c2d4c1f700ca768a513ea07c2660cd8cd983d8704d63230689637f061d4f4ec4defbdb1c655ecc
|
@@ -133,17 +133,15 @@ module SL
|
|
133
133
|
SL::Util.search_with_timeout(search, timeout)
|
134
134
|
end
|
135
135
|
|
136
|
-
# Performs a DuckDuckGo search with the given search
|
137
|
-
#
|
138
|
-
#
|
139
|
-
# after the given number of seconds.
|
136
|
+
# Performs a DuckDuckGo search with the given search terms and link text. If
|
137
|
+
# link text is not provided, the first result will be returned. The search
|
138
|
+
# will timeout after the given number of seconds.
|
140
139
|
#
|
141
|
-
# @param search_terms [String] The search terms to
|
142
|
-
#
|
143
|
-
# @param
|
144
|
-
#
|
145
|
-
# @param
|
146
|
-
# the search in seconds
|
140
|
+
# @param search_terms [String] The search terms to use
|
141
|
+
# @param link_text [String] The text of the link to search for
|
142
|
+
# @param timeout [Integer] The timeout for the search in seconds
|
143
|
+
# @param google [Boolean] Use Google if API key installed
|
144
|
+
# @param image [Boolean] Image search
|
147
145
|
# @return [SL::Searches::Result] The search result
|
148
146
|
#
|
149
147
|
def ddg(search_terms, link_text = nil, timeout: SL.config['timeout'], google: true, image: false)
|
@@ -159,6 +157,17 @@ module SL
|
|
159
157
|
SL::Util.search_with_timeout(search, timeout)
|
160
158
|
end
|
161
159
|
|
160
|
+
##
|
161
|
+
## Perform a site-specific search
|
162
|
+
##
|
163
|
+
## @param site [String] The site to search
|
164
|
+
## @param search_terms [String] The search terms
|
165
|
+
## @param link_text [String] The link text
|
166
|
+
##
|
167
|
+
def site_search(site, search_terms, link_text)
|
168
|
+
ddg("site:#{site} #{search_terms}", link_text)
|
169
|
+
end
|
170
|
+
|
162
171
|
def first_image(url)
|
163
172
|
images = Curl::Html.new(url).images
|
164
173
|
images.filter { |img| img[:type] == 'img' }.first[:src]
|
@@ -29,7 +29,7 @@ module SL
|
|
29
29
|
terms.push("(url NOT LIKE '%search/?%'
|
30
30
|
AND url NOT LIKE '%?q=%' AND url NOT LIKE '%?s=%'
|
31
31
|
AND url NOT LIKE '%/search?%'
|
32
|
-
AND url NOT LIKE '%duckduckgo.com
|
32
|
+
AND url NOT LIKE '%duckduckgo.com%')")
|
33
33
|
if exact_match
|
34
34
|
terms.push("(url LIKE '%#{term.strip.downcase}%' OR title LIKE '%#{term.strip.downcase}%')")
|
35
35
|
else
|
@@ -0,0 +1,213 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SL
|
4
|
+
class LinkdingSearch
|
5
|
+
LINKDING_CACHE = SL::Util.cache_file_for("linkding")
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def settings
|
9
|
+
{
|
10
|
+
trigger: "(ld|ding)",
|
11
|
+
searches: [
|
12
|
+
[["ld", "ding"], "Linkding Bookmark Search"],
|
13
|
+
],
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_json(call)
|
18
|
+
curl = TTY::Which.which("curl")
|
19
|
+
bookmarks = `#{curl} -SsL -H "Authorization: Token #{SL.config["linkding_api_key"]}" "#{SL.config["linkding_server"]}#{call}"`
|
20
|
+
|
21
|
+
bookmarks = bookmarks.force_encoding("utf-8")
|
22
|
+
bookmarks.gsub!(/[^[:ascii:]]/) do |non_ascii|
|
23
|
+
non_ascii.force_encoding("utf-8")
|
24
|
+
.encode("utf-16be")
|
25
|
+
.unpack("H*")[0]
|
26
|
+
.gsub(/(....)/, '\u\1')
|
27
|
+
end
|
28
|
+
|
29
|
+
bookmarks.gsub!(/[\u{1F600}-\u{1F6FF}]/, "")
|
30
|
+
|
31
|
+
JSON.parse(bookmarks)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_linkding_bookmarks
|
35
|
+
curl = TTY::Which.which("curl")
|
36
|
+
call = "/api/bookmarks/?limit=8000&format=json"
|
37
|
+
|
38
|
+
json = get_json(call)
|
39
|
+
bookmarks = json["results"]
|
40
|
+
offset = 0
|
41
|
+
|
42
|
+
while json["next"]
|
43
|
+
offset += 8000
|
44
|
+
json = get_json(call + "&offset=#{offset}")
|
45
|
+
bookmarks.concat(json["results"])
|
46
|
+
end
|
47
|
+
|
48
|
+
bookmarks
|
49
|
+
end
|
50
|
+
|
51
|
+
def linkding_bookmarks
|
52
|
+
bookmarks = get_linkding_bookmarks
|
53
|
+
updated = Time.now
|
54
|
+
{ "update_time" => updated, "bookmarks" => bookmarks }
|
55
|
+
end
|
56
|
+
|
57
|
+
def save_linkding_cache(cache)
|
58
|
+
cachefile = LINKDING_CACHE
|
59
|
+
|
60
|
+
# file = File.new(cachefile,'w')
|
61
|
+
# file = Zlib::GzipWriter.new(File.new(cachefile,'w'))
|
62
|
+
begin
|
63
|
+
File.open(cachefile, "wb") { |f| f.write(Marshal.dump(cache)) }
|
64
|
+
rescue IOError
|
65
|
+
SL.add_error("Linkding cache error", "Failed to write stash to disk")
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
true
|
69
|
+
end
|
70
|
+
|
71
|
+
def linkding_cache
|
72
|
+
refresh_cache = false
|
73
|
+
cachefile = LINKDING_CACHE
|
74
|
+
|
75
|
+
if File.exist?(cachefile)
|
76
|
+
begin
|
77
|
+
# file = IO.read(cachefile) # Zlib::GzipReader.open(cachefile)
|
78
|
+
# cache = Marshal.load file
|
79
|
+
cache = Marshal.load(File.binread(cachefile))
|
80
|
+
# file.close
|
81
|
+
rescue IOError # Zlib::GzipFile::Error
|
82
|
+
SL.add_error("Error loading linkding cache", "IOError reading #{cachefile}")
|
83
|
+
cache = linkding_bookmarks
|
84
|
+
save_linkding_cache(cache)
|
85
|
+
rescue StandardError
|
86
|
+
SL.add_error("Error loading linkding cache", "StandardError reading #{cachefile}")
|
87
|
+
cache = linkding_bookmarks
|
88
|
+
save_linkding_cache(cache)
|
89
|
+
end
|
90
|
+
curl = TTY::Which.which("curl")
|
91
|
+
updated = get_json("/api/bookmarks/?limit=1&format=json")["results"][0]
|
92
|
+
last_bookmark = Time.parse(updated["date_modified"])
|
93
|
+
if cache&.key?("update_time")
|
94
|
+
last_update = cache["update_time"]
|
95
|
+
refresh_cache = true if last_update < last_bookmark
|
96
|
+
else
|
97
|
+
refresh_cache = true
|
98
|
+
end
|
99
|
+
else
|
100
|
+
refresh_cache = true
|
101
|
+
end
|
102
|
+
|
103
|
+
if refresh_cache
|
104
|
+
cache = linkding_bookmarks
|
105
|
+
save_linkding_cache(cache)
|
106
|
+
end
|
107
|
+
|
108
|
+
cache
|
109
|
+
end
|
110
|
+
|
111
|
+
# Search pinboard bookmarks
|
112
|
+
# Begin query with '' to force exact matching (including description text)
|
113
|
+
# Regular matching searches for each word of query and scores the bookmarks
|
114
|
+
# exact matches in title get highest score
|
115
|
+
# exact matches in description get second highest score
|
116
|
+
# other bookmarks are scored based on the number of words that match
|
117
|
+
#
|
118
|
+
# After sorting by score, bookmarks will be sorted by date and the most recent
|
119
|
+
# will be returned
|
120
|
+
#
|
121
|
+
# Exact matching is case and punctuation insensitive
|
122
|
+
def search(_, search_terms, link_text)
|
123
|
+
unless SL.config["linkding_server"]
|
124
|
+
SL.add_error("Missing Linkding server",
|
125
|
+
"add it to your configuration (linkding_server: https://YOUR_SERVER)")
|
126
|
+
return false
|
127
|
+
end
|
128
|
+
|
129
|
+
unless SL.config["linkding_api_key"]
|
130
|
+
SL.add_error("Missing Linkding API token",
|
131
|
+
"Find your api key at https://your_server/settings/integrations and add it
|
132
|
+
to your configuration (linkding_api_key: YOURKEY)")
|
133
|
+
return false
|
134
|
+
end
|
135
|
+
|
136
|
+
exact_match = false
|
137
|
+
match_phrases = []
|
138
|
+
|
139
|
+
# If search terms start with ''term, only search for exact string matches
|
140
|
+
case search_terms
|
141
|
+
when /^ *'/
|
142
|
+
exact_match = true
|
143
|
+
search_terms.gsub!(/(^ *'+|'+ *$)/, "")
|
144
|
+
when /%22(.*?)%22/
|
145
|
+
match_phrases = search_terms.scan(/%22(\S.*?\S)%22/)
|
146
|
+
search_terms.gsub!(/%22(\S.*?\S)%22/, "")
|
147
|
+
end
|
148
|
+
|
149
|
+
cache = linkding_cache
|
150
|
+
# cache = linkding_bookmarks
|
151
|
+
bookmarks = cache["bookmarks"]
|
152
|
+
|
153
|
+
if exact_match
|
154
|
+
bookmarks.each do |bm|
|
155
|
+
text = [bm["title"], bm["description"], bm["tag_names"].join(" ")].join(" ")
|
156
|
+
|
157
|
+
return [bm["url"], bm["title"]] if text.matches_exact(search_terms)
|
158
|
+
end
|
159
|
+
|
160
|
+
return false
|
161
|
+
end
|
162
|
+
|
163
|
+
unless match_phrases.empty?
|
164
|
+
bookmarks.delete_if do |bm|
|
165
|
+
matched = tru
|
166
|
+
full_text = [bm["title"], bm["description"], bm["tag_names"].join(" ")].join(" ")
|
167
|
+
match_phrases.each do |phrase|
|
168
|
+
matched = false unless full_text.matches_exact(phrase)
|
169
|
+
end
|
170
|
+
!matched
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
matches = []
|
175
|
+
bookmarks.each do |bm|
|
176
|
+
title_tags = [bm["title"], bm["description"]].join(" ")
|
177
|
+
full_text = [bm["title"], bm["description"], bm["tag_names"].join(" ")].join(" ")
|
178
|
+
|
179
|
+
score = if title_tags.matches_exact(search_terms)
|
180
|
+
14.0
|
181
|
+
elsif full_text.matches_exact(search_terms)
|
182
|
+
13.0
|
183
|
+
elsif full_text.matches_any(search_terms)
|
184
|
+
full_text.matches_score(search_terms)
|
185
|
+
else
|
186
|
+
0
|
187
|
+
end
|
188
|
+
|
189
|
+
return [bm["url"], bm["title"]] if score == 14
|
190
|
+
|
191
|
+
next unless score.positive?
|
192
|
+
|
193
|
+
matches.push({
|
194
|
+
score: score,
|
195
|
+
href: bm["url"],
|
196
|
+
title: bm["title"],
|
197
|
+
date: bm["date_added"],
|
198
|
+
})
|
199
|
+
end
|
200
|
+
|
201
|
+
return false if matches.empty?
|
202
|
+
|
203
|
+
top = matches.max_by { |bm| [bm[:score], bm[:date]] }
|
204
|
+
|
205
|
+
return false unless top
|
206
|
+
|
207
|
+
[top[:href], top[:title], link_text]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
SL::Searches.register "linkding", :search, self
|
212
|
+
end
|
213
|
+
end
|
data/lib/searchlink/searches.rb
CHANGED
@@ -9,7 +9,7 @@ module SL
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def load_searches
|
12
|
-
Dir.glob(File.join(File.dirname(__FILE__),
|
12
|
+
Dir.glob(File.join(File.dirname(__FILE__), "searches", "*.rb")).sort.each { |f| require f }
|
13
13
|
end
|
14
14
|
|
15
15
|
#
|
@@ -43,21 +43,21 @@ module SL
|
|
43
43
|
#
|
44
44
|
def available_searches_html
|
45
45
|
searches = plugins[:search]
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
.flat_map { |_, plugin| plugin[:searches] }
|
47
|
+
.reject { |s| s[1].nil? }
|
48
|
+
.sort_by { |s| s[0].is_a?(Array) ? s[0][0] : s[0] }
|
49
49
|
out = ['<table id="searches">',
|
50
|
-
|
51
|
-
|
50
|
+
"<thead><td>Shortcut</td><td>Search Type</td></thead>",
|
51
|
+
"<tbody>"]
|
52
52
|
|
53
53
|
searches.each do |s|
|
54
54
|
out << "<tr>
|
55
55
|
<td>
|
56
|
-
<code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(
|
56
|
+
<code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(",")})" : s[0]}
|
57
57
|
</code>
|
58
58
|
</td><td>#{s[1]}</td></tr>"
|
59
59
|
end
|
60
|
-
out.concat([
|
60
|
+
out.concat(["</tbody>", "</table>"]).join("\n")
|
61
61
|
end
|
62
62
|
|
63
63
|
#
|
@@ -69,26 +69,33 @@ module SL
|
|
69
69
|
searches = []
|
70
70
|
plugins[:search].each_value { |plugin| searches.concat(plugin[:searches].delete_if { |s| s[1].nil? }) }
|
71
71
|
out = []
|
72
|
+
|
72
73
|
searches.each do |s|
|
73
|
-
|
74
|
+
shortcut = if s[0].is_a?(Array)
|
75
|
+
"#{s[0][0]} (#{s[0][1..-1].join(",")})"
|
76
|
+
else
|
77
|
+
s[0]
|
78
|
+
end
|
79
|
+
|
80
|
+
out << "!#{shortcut}#{shortcut.spacer}#{s[1]}"
|
74
81
|
end
|
75
82
|
out.join("\n")
|
76
83
|
end
|
77
84
|
|
78
85
|
def best_search_match(term)
|
79
86
|
searches = all_possible_searches.dup
|
80
|
-
searches.flatten.select { |s| s.matches_score(term, separator:
|
87
|
+
searches.flatten.select { |s| s.matches_score(term, separator: "", start_word: false) > 8 }
|
81
88
|
end
|
82
89
|
|
83
90
|
def all_possible_searches
|
84
91
|
searches = []
|
85
92
|
plugins[:search].each_value { |plugin| plugin[:searches].each { |s| searches.push(s[0]) } }
|
86
|
-
searches.concat(SL.config[
|
93
|
+
searches.concat(SL.config["custom_site_searches"].keys.sort)
|
87
94
|
end
|
88
95
|
|
89
96
|
def did_you_mean(term)
|
90
97
|
matches = best_search_match(term)
|
91
|
-
matches.empty? ?
|
98
|
+
matches.empty? ? "" : ", did you mean #{matches.map { |m| "!#{m}" }.join(", ")}?"
|
92
99
|
end
|
93
100
|
|
94
101
|
def valid_searches
|
@@ -99,14 +106,14 @@ module SL
|
|
99
106
|
|
100
107
|
def valid_search?(term)
|
101
108
|
valid = false
|
102
|
-
valid = true if term =~ /^(#{valid_searches.join(
|
103
|
-
valid = true if SL.config[
|
109
|
+
valid = true if term =~ /^(#{valid_searches.join("|")})$/
|
110
|
+
valid = true if SL.config["custom_site_searches"].keys.include? term
|
104
111
|
# SL.notify("Invalid search#{did_you_mean(term)}", term) unless valid
|
105
112
|
valid
|
106
113
|
end
|
107
114
|
|
108
115
|
def register_plugin(title, type, klass)
|
109
|
-
raise PluginError.new("Plugin has no settings method", plugin: title)
|
116
|
+
raise PluginError.new("Plugin has no settings method", plugin: title) unless klass.respond_to? :settings
|
110
117
|
|
111
118
|
settings = klass.settings
|
112
119
|
|
@@ -116,16 +123,16 @@ module SL
|
|
116
123
|
plugins[type][title] = {
|
117
124
|
trigger: settings.fetch(:trigger, title).normalize_trigger,
|
118
125
|
searches: settings[:searches],
|
119
|
-
class: klass
|
126
|
+
class: klass,
|
120
127
|
}
|
121
128
|
end
|
122
129
|
|
123
130
|
def load_custom
|
124
|
-
plugins_folder = File.expand_path(
|
125
|
-
new_plugins_folder = File.expand_path(
|
131
|
+
plugins_folder = File.expand_path("~/.local/searchlink/plugins")
|
132
|
+
new_plugins_folder = File.expand_path("~/.config/searchlink/plugins")
|
126
133
|
|
127
134
|
if File.directory?(plugins_folder) && !File.directory?(new_plugins_folder)
|
128
|
-
Dir.glob(File.join(plugins_folder,
|
135
|
+
Dir.glob(File.join(plugins_folder, "**/*.rb")).sort.each do |plugin|
|
129
136
|
require plugin
|
130
137
|
end
|
131
138
|
|
@@ -134,7 +141,7 @@ module SL
|
|
134
141
|
|
135
142
|
return unless File.directory?(new_plugins_folder)
|
136
143
|
|
137
|
-
Dir.glob(File.join(new_plugins_folder,
|
144
|
+
Dir.glob(File.join(new_plugins_folder, "**/*.rb")).sort.each do |plugin|
|
138
145
|
require plugin
|
139
146
|
end
|
140
147
|
|
@@ -142,25 +149,25 @@ module SL
|
|
142
149
|
end
|
143
150
|
|
144
151
|
def load_custom_scripts(plugins_folder)
|
145
|
-
Dir.glob(File.join(plugins_folder,
|
146
|
-
ext = File.extname(file).sub(/^\./,
|
152
|
+
Dir.glob(File.join(plugins_folder, "**/*.{json,yml,yaml}")).each do |file|
|
153
|
+
ext = File.extname(file).sub(/^\./, "")
|
147
154
|
config = IO.read(file)
|
148
155
|
|
149
156
|
cfg = case ext
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
cfg[
|
156
|
-
cfg[
|
157
|
+
when /^y/i
|
158
|
+
YAML.safe_load(config)
|
159
|
+
else
|
160
|
+
JSON.parse(config)
|
161
|
+
end
|
162
|
+
cfg["filename"] = File.basename(file)
|
163
|
+
cfg["path"] = file.shorten_path
|
157
164
|
SL::ScriptSearch.new(cfg)
|
158
165
|
end
|
159
166
|
end
|
160
167
|
|
161
|
-
def do_search(search_type, search_terms, link_text, timeout: SL.config[
|
168
|
+
def do_search(search_type, search_terms, link_text, timeout: SL.config["timeout"])
|
162
169
|
plugins[:search].each do |_title, plugin|
|
163
|
-
trigger = plugin[:trigger].gsub(/(^\^|\$$)/,
|
170
|
+
trigger = plugin[:trigger].gsub(/(^\^|\$$)/, "")
|
164
171
|
if search_type =~ /^#{trigger}$/
|
165
172
|
search = proc { plugin[:class].search(search_type, search_terms, link_text) }
|
166
173
|
return SL::Util.search_with_timeout(search, timeout)
|
@@ -172,64 +179,67 @@ module SL
|
|
172
179
|
end
|
173
180
|
|
174
181
|
# import
|
175
|
-
require_relative
|
182
|
+
require_relative "searches/applemusic"
|
176
183
|
|
177
184
|
# import
|
178
|
-
require_relative
|
185
|
+
require_relative "searches/itunes"
|
179
186
|
|
180
187
|
# import
|
181
|
-
require_relative
|
188
|
+
require_relative "searches/amazon"
|
182
189
|
|
183
190
|
# import
|
184
|
-
require_relative
|
191
|
+
require_relative "searches/bitly"
|
185
192
|
|
186
193
|
# import
|
187
|
-
require_relative
|
194
|
+
require_relative "searches/definition"
|
188
195
|
|
189
196
|
# import
|
190
|
-
require_relative
|
197
|
+
require_relative "searches/duckduckgo"
|
191
198
|
|
192
199
|
# import
|
193
|
-
require_relative
|
200
|
+
require_relative "searches/github"
|
194
201
|
|
195
202
|
# import
|
196
|
-
require_relative
|
203
|
+
require_relative "searches/google"
|
197
204
|
|
198
205
|
# import
|
199
|
-
require_relative
|
206
|
+
require_relative "searches/history"
|
200
207
|
|
201
208
|
# import
|
202
|
-
require_relative
|
209
|
+
require_relative "searches/hook"
|
203
210
|
|
204
211
|
# import
|
205
|
-
require_relative
|
212
|
+
require_relative "searches/lastfm"
|
206
213
|
|
207
214
|
# import
|
208
|
-
require_relative
|
215
|
+
require_relative "searches/pinboard"
|
209
216
|
|
210
217
|
# import
|
211
|
-
require_relative
|
218
|
+
require_relative "searches/social"
|
212
219
|
|
213
220
|
# import
|
214
|
-
require_relative
|
221
|
+
require_relative "searches/software"
|
215
222
|
|
216
223
|
# import
|
217
|
-
require_relative
|
224
|
+
require_relative "searches/spelling"
|
218
225
|
|
219
226
|
# import
|
220
|
-
require_relative
|
227
|
+
require_relative "searches/spotlight"
|
221
228
|
|
222
229
|
# import
|
223
|
-
require_relative
|
230
|
+
require_relative "searches/tmdb"
|
224
231
|
|
225
232
|
# import
|
226
|
-
require_relative
|
233
|
+
require_relative "searches/twitter"
|
227
234
|
|
228
235
|
# import
|
229
|
-
require_relative
|
236
|
+
require_relative "searches/wikipedia"
|
230
237
|
|
231
238
|
# import
|
232
|
-
require_relative
|
239
|
+
require_relative "searches/youtube"
|
233
240
|
|
234
241
|
# import
|
235
|
-
require_relative
|
242
|
+
require_relative "searches/stackoverflow"
|
243
|
+
|
244
|
+
#import
|
245
|
+
require_relative "searches/linkding"
|
data/lib/searchlink/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchlink
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.3.
|
4
|
+
version: 2.3.72
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -220,6 +220,20 @@ dependencies:
|
|
220
220
|
- - "~>"
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: 0.9.5
|
223
|
+
- !ruby/object:Gem::Dependency
|
224
|
+
name: plist
|
225
|
+
requirement: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - "~>"
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: 3.7.1
|
230
|
+
type: :development
|
231
|
+
prerelease: false
|
232
|
+
version_requirements: !ruby/object:Gem::Requirement
|
233
|
+
requirements:
|
234
|
+
- - "~>"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: 3.7.1
|
223
237
|
description: macOS System Service for inline web searches
|
224
238
|
email:
|
225
239
|
- me@brettterpstra.com
|
@@ -258,6 +272,7 @@ files:
|
|
258
272
|
- lib/searchlink/searches/hook.rb
|
259
273
|
- lib/searchlink/searches/itunes.rb
|
260
274
|
- lib/searchlink/searches/lastfm.rb
|
275
|
+
- lib/searchlink/searches/linkding.rb
|
261
276
|
- lib/searchlink/searches/lyrics.rb
|
262
277
|
- lib/searchlink/searches/pinboard.rb
|
263
278
|
- lib/searchlink/searches/social.rb
|
@@ -295,7 +310,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
295
310
|
- !ruby/object:Gem::Version
|
296
311
|
version: '0'
|
297
312
|
requirements: []
|
298
|
-
rubygems_version: 3.2.
|
313
|
+
rubygems_version: 3.2.16
|
299
314
|
signing_key:
|
300
315
|
specification_version: 4
|
301
316
|
summary: Create Markdown links from web searches without leaving your editor.
|