searchlink 2.3.70 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94434b4c63f4188ca00e93ad4c2be7765b61a2fdbccd3b7e706482bf1e09b618
4
- data.tar.gz: 4af48f283d1a693bed323cdbbb91121ee5b4616225d4ecef46f80302016227ff
3
+ metadata.gz: d6e6eec4235b7ab5dd818a599ccd7ece852d6328233d2a81b8738447a581e046
4
+ data.tar.gz: 2e11a49af2da708369bde197c02b247875c41d6591fedbbb8e2b80a339819332
5
5
  SHA512:
6
- metadata.gz: 3fa2094dbbf341680baefae73f98aba890ace10c6f6d44198b7902c28810b9e3cc8121199b9ba26a1da0243dcf779c3f018ebaaa6f1e794456d72106fafe5ad6
7
- data.tar.gz: 7a39a40fbc8e8466c3652e236eee03091b027dd83aebd481b31dcb3acaa3a53124d362887d4cbe33bc22699fadd4e7adfe40f4f40db48cb8f69754584d84ae70
6
+ metadata.gz: a7c755596c600f2ce59a02a7b4e4199efa726613ae085cb0cd1f9998fec0fae7d384597f57d5b1c5258ba45d9d2abfb7cd148d533ec35406d01fcb186385b77c
7
+ data.tar.gz: 461e781699e0f1f04eaf46d28215b0fecf1447da6784025505c2d4c1f700ca768a513ea07c2660cd8cd983d8704d63230689637f061d4f4ec4defbdb1c655ecc
@@ -424,6 +424,14 @@ module SL
424
424
  @url, title, @link_text = do_search(search_type, search_terms, @link_text, @search_count)
425
425
  end
426
426
 
427
+ if (@link_text == '' || @link_text == '%') && @url
428
+ if title
429
+ @link_text = title
430
+ else
431
+ add_title(@url)
432
+ end
433
+ end
434
+
427
435
  if @url
428
436
  title = SL::URL.title(@url) if SL.titleize && title == ''
429
437
 
@@ -68,7 +68,7 @@ module SL
68
68
  end
69
69
 
70
70
  def find_script(script)
71
- return script if File.exist?(File.expand_path(script))
71
+ return File.expand_path(script) if File.exist?(File.expand_path(script))
72
72
 
73
73
  base = File.expand_path('~/.config/searchlink/plugins')
74
74
  first = File.join(base, script)
@@ -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
- # terms and link text. If link text is not provided, the
138
- # first result will be returned. The search will timeout
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
- # use
143
- # @param link_text [String] The text of the
144
- # link to search for
145
- # @param timeout [Integer] The timeout for
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/?t%')")
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
@@ -9,7 +9,7 @@ module SL
9
9
  end
10
10
 
11
11
  def load_searches
12
- Dir.glob(File.join(File.dirname(__FILE__), 'searches', '*.rb')).sort.each { |f| require f }
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
- .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] }
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
- '<thead><td>Shortcut</td><td>Search Type</td></thead>',
51
- '<tbody>']
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(',')})" : s[0]}
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(['</tbody>', '</table>']).join("\n")
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
- out += "!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..-1].join(',')})" : s[0]}#{s[0].spacer}#{s[1]}"
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: '', start_word: false) > 8 }
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['custom_site_searches'].keys.sort)
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? ? '' : ", did you mean #{matches.map { |m| "!#{m}" }.join(', ')}?"
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['custom_site_searches'].keys.include? term
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) unless klass.respond_to? :settings
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('~/.local/searchlink/plugins')
125
- new_plugins_folder = File.expand_path('~/.config/searchlink/plugins')
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, '**/*.rb')).sort.each do |plugin|
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, '**/*.rb')).sort.each do |plugin|
144
+ Dir.glob(File.join(new_plugins_folder, "**/*.rb")).sort.each do |plugin|
138
145
  require plugin
139
146
  end
140
147
 
@@ -142,24 +149,25 @@ module SL
142
149
  end
143
150
 
144
151
  def load_custom_scripts(plugins_folder)
145
- Dir.glob(File.join(plugins_folder, '**/*.{json,yml,yaml}')).each do |file|
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)
155
+
148
156
  cfg = case ext
149
- when /^y/i
150
- YAML.safe_load(config)
151
- else
152
- JSON.parse(config)
153
- end
154
- cfg['filename'] = File.basename(file)
155
- cfg['path'] = file.shorten_path
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
156
164
  SL::ScriptSearch.new(cfg)
157
165
  end
158
166
  end
159
167
 
160
- def do_search(search_type, search_terms, link_text, timeout: SL.config['timeout'])
168
+ def do_search(search_type, search_terms, link_text, timeout: SL.config["timeout"])
161
169
  plugins[:search].each do |_title, plugin|
162
- trigger = plugin[:trigger].gsub(/(^\^|\$$)/, '')
170
+ trigger = plugin[:trigger].gsub(/(^\^|\$$)/, "")
163
171
  if search_type =~ /^#{trigger}$/
164
172
  search = proc { plugin[:class].search(search_type, search_terms, link_text) }
165
173
  return SL::Util.search_with_timeout(search, timeout)
@@ -171,64 +179,67 @@ module SL
171
179
  end
172
180
 
173
181
  # import
174
- require_relative 'searches/applemusic'
182
+ require_relative "searches/applemusic"
175
183
 
176
184
  # import
177
- require_relative 'searches/itunes'
185
+ require_relative "searches/itunes"
178
186
 
179
187
  # import
180
- require_relative 'searches/amazon'
188
+ require_relative "searches/amazon"
181
189
 
182
190
  # import
183
- require_relative 'searches/bitly'
191
+ require_relative "searches/bitly"
184
192
 
185
193
  # import
186
- require_relative 'searches/definition'
194
+ require_relative "searches/definition"
187
195
 
188
196
  # import
189
- require_relative 'searches/duckduckgo'
197
+ require_relative "searches/duckduckgo"
190
198
 
191
199
  # import
192
- require_relative 'searches/github'
200
+ require_relative "searches/github"
193
201
 
194
202
  # import
195
- require_relative 'searches/google'
203
+ require_relative "searches/google"
196
204
 
197
205
  # import
198
- require_relative 'searches/history'
206
+ require_relative "searches/history"
199
207
 
200
208
  # import
201
- require_relative 'searches/hook'
209
+ require_relative "searches/hook"
202
210
 
203
211
  # import
204
- require_relative 'searches/lastfm'
212
+ require_relative "searches/lastfm"
205
213
 
206
214
  # import
207
- require_relative 'searches/pinboard'
215
+ require_relative "searches/pinboard"
208
216
 
209
217
  # import
210
- require_relative 'searches/social'
218
+ require_relative "searches/social"
211
219
 
212
220
  # import
213
- require_relative 'searches/software'
221
+ require_relative "searches/software"
214
222
 
215
223
  # import
216
- require_relative 'searches/spelling'
224
+ require_relative "searches/spelling"
217
225
 
218
226
  # import
219
- require_relative 'searches/spotlight'
227
+ require_relative "searches/spotlight"
220
228
 
221
229
  # import
222
- require_relative 'searches/tmdb'
230
+ require_relative "searches/tmdb"
223
231
 
224
232
  # import
225
- require_relative 'searches/twitter'
233
+ require_relative "searches/twitter"
226
234
 
227
235
  # import
228
- require_relative 'searches/wikipedia'
236
+ require_relative "searches/wikipedia"
229
237
 
230
238
  # import
231
- require_relative 'searches/youtube'
239
+ require_relative "searches/youtube"
232
240
 
233
241
  # import
234
- require_relative 'searches/stackoverflow'
242
+ require_relative "searches/stackoverflow"
243
+
244
+ #import
245
+ require_relative "searches/linkding"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SL
4
- VERSION = '2.3.70'
4
+ VERSION = '2.3.72'
5
5
  end
6
6
 
7
7
  # Main module
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.70
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-08-10 00:00:00.000000000 Z
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.15
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.