searchlink 2.3.81 → 2.3.83

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: ce66d54f12c512c8e3e4508cf86d9dfde5e0be920a7bfe30bdc6071caceba54d
4
- data.tar.gz: 744eb155302ed0901f3eba23ed8c50b73e8834040389662cfd4ae715843041e3
3
+ metadata.gz: 9d9d44b58260a556b6834758e6782fe1b0b0d6ebb43ed79c88b3ecee9d53d124
4
+ data.tar.gz: a10d673938b4a58c907b2588fedaf4e71f021d5f85d392cbc17c144dea91c3b8
5
5
  SHA512:
6
- metadata.gz: c9210886c698b4e82e7bb6d5b56732febef66c612ebe90351e66e0a4fcd9b6494ecac4b2bac5422b288bde4b25ba2d40b7bcb8737af467e757fafc19c8827a69
7
- data.tar.gz: a36ba8e0be0f29f3f4cc31558ecdc0ba76b35e48cd2ecdd1a0ff35b9ce014dbfcc5063084111b1b26694e335b82ba86e391d63a855623cb6297c00e6560c3324
6
+ metadata.gz: e1a3d23ee5be311f69772b5f46a72a9c18b9684a22d62af561d6c1421ab13343df8b6f233e00ba6811748d5b2cf31c91886d45fae4fff94e797ecca10a285b65
7
+ data.tar.gz: 8100ed794563d9747bce2be4b1b2a13e6475331769ee5411a7c4c186089b01bde9536c17002bffdd8c4821db11d185590b9de3d6b8c42b27175540e2cdae945c
@@ -32,7 +32,9 @@ module SL
32
32
 
33
33
  def initialize(opt = {})
34
34
  SL.printout = opt[:echo] || false
35
- unless File.exist? config_file
35
+ if File.exist? config_file
36
+ write_new_plugin_config
37
+ else
36
38
  default_config = <<~ENDCONFIG
37
39
  # set to true to have an HTML comment included detailing any errors
38
40
  # Can be disabled per search with `--d`, or enabled with `++d`.
@@ -80,22 +82,6 @@ module SL
80
82
  # E.g. [](!g Search Text)
81
83
  empty_uses_page_title: false
82
84
 
83
- # Formatting for social links, use %service%, %user%, and %url%
84
- # E.g. "%user% on %service%" => "ttscoff on Twitter"
85
- # "%service%/%user%" => "Twitter/ttscoff"
86
- # "%url%" => "twitter.com/ttscoff"
87
- social_template: "%service%/%user%"
88
-
89
- # append affiliate link info to iTunes urls, empty quotes for none
90
- # example:
91
- # itunes_affiliate: "&at=10l4tL&ct=searchlink"
92
- itunes_affiliate: "&at=10l4tL&ct=searchlink"
93
-
94
- # to create Amazon affiliate links, set amazon_partner to your amazon
95
- # affiliate tag
96
- # amazon_partner: "bretttercom-20"
97
- amazon_partner: "bretttercom-20"
98
-
99
85
  # To create custom abbreviations for Google Site Searches,
100
86
  # add to (or replace) the hash below.
101
87
  # "abbreviation" => "site.url",
@@ -129,35 +115,11 @@ module SL
129
115
  dev: developer.apple.com
130
116
  nq: http://nerdquery.com/?media_only=0&query=$term&search=1&category=-1&catid=&type=and&results=50&db=0&prefix=0
131
117
  gs: http://scholar.google.com/scholar?btnI&hl=en&q=$term&btnG=&as_sdt=80006
132
- # Remove or comment (with #) history searches you don't want
133
- # performed by `!h`. You can force-enable them per search, e.g.
134
- # `!hsh` (Safari History only), `!hcb` (Chrome Bookmarks only),
135
- # etc. Multiple types can be strung together: !hshcb (Safari
136
- # History and Chrome bookmarks).
137
- history_types:
138
- - safari_bookmarks
139
- - safari_history
140
- # - chrome_history
141
- # - chrome_bookmarks
142
- # - firefox_bookmarks
143
- # - firefox_history
144
- # - edge_bookmarks
145
- # - edge_history
146
- # - brave_bookmarks
147
- # - brave_history
148
- # - arc_history
149
- # - arc_bookmarks
150
- # Pinboard search
151
- # You can find your api key here: https://pinboard.in/settings/password
152
- pinboard_api_key: ''
153
- # Generate an access token at https://app.bitly.com/settings/api/
154
- bitly_access_token: ''
155
- bitly_domain: 'bit.ly'
156
- # Custom Google API key to use Google search (free for 100 queries/day)
157
- google_api_key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
158
118
 
159
119
  ENDCONFIG
160
120
 
121
+ default_config = get_plugin_configs(default_config)
122
+
161
123
  File.open(config_file, "w") do |f|
162
124
  f.puts default_config
163
125
  end
@@ -222,15 +184,107 @@ module SL
222
184
 
223
185
  # use notification center to show progress
224
186
  config["notifications"] ||= false
225
- config["pinboard_api_key"] ||= false
226
- config["google_api_key"] ||= false
227
187
 
228
188
  SL.line_num = nil
229
189
  SL.match_column = nil
230
190
  SL.match_length = nil
231
191
  SL.config = config
192
+
193
+ add_plugin_configs(config)
194
+ end
195
+
196
+ # Add plugin configurations to config object
197
+ #
198
+ # @param config [Hash] Hash of plugin configurations
199
+ #
200
+ # @note applies configurations to SL.config
201
+ #
202
+ def add_plugin_configs(config)
203
+ SL::Searches.plugins[:search].each_value do |plugin|
204
+ next unless plugin.key?(:config) && !plugin[:config].nil? && !plugin[:config].empty?
205
+
206
+ plugin[:config].each do |cfg|
207
+ SL.config[cfg[:key]] = config[cfg[:key]] if config.key?(cfg[:key])
208
+ end
209
+ end
210
+ end
211
+
212
+ # Add new keys to config if don't exist
213
+ def write_new_plugin_config
214
+ default_config = IO.read(config_file)
215
+ new_config = ""
216
+ SL::Searches.plugins[:search].each_value do |plugin|
217
+ next unless plugin.key?(:config) && !plugin[:config].nil? && !plugin[:config].empty?
218
+
219
+ plugin[:config].each do |cfg|
220
+ next if default_config =~ /^(# *)?#{cfg[:key]}:/
221
+
222
+ new_config += get_plugin_config(cfg)
223
+ end
224
+ end
225
+
226
+ return if new_config.empty?
227
+
228
+ File.open(config_file, "w") { |f| f.puts default_config + new_config }
229
+ end
230
+
231
+ #
232
+ # Get plugin configs
233
+ #
234
+ # @param default_config [String] Existing configuration
235
+ #
236
+ # @return [String] default_config with plugin configurations added
237
+ #
238
+ def get_plugin_configs(default_config)
239
+ SL::Searches.plugins[:search].each_value do |plugin|
240
+ next unless plugin.key?(:config) && !plugin[:config].nil? && !plugin[:config].empty?
241
+
242
+ plugin[:config].each do |cfg|
243
+ new_config = get_plugin_config(cfg)
244
+
245
+ default_config += new_config
246
+ end
247
+ end
248
+ default_config
249
+ end
250
+
251
+ #
252
+ # Get a single plugin configuration
253
+ #
254
+ # @param cfg [Hash] Hash of single plugin config
255
+ #
256
+ # @return [String] String representation of config
257
+ #
258
+ def get_plugin_config(cfg)
259
+ key = cfg[:key]
260
+ value = cfg[:value]
261
+ required = cfg[:required]
262
+ description = cfg[:description]
263
+ description = "\n#{description}" if description
264
+ description = description.word_wrap(60, "# ") if description
265
+ key = required ? key : "# #{key}"
266
+ if value.is_a?(Array)
267
+ array_value = "\n"
268
+ value.each do |v|
269
+ array_value += required ? "- #{v.yaml_val}" : "# - #{v.yaml_val}\n"
270
+ end
271
+ value = array_value
272
+ elsif value.is_a?(Hash)
273
+ hash_value = "\n"
274
+ value.each do |k, v|
275
+ hash_value += required ? " #{k}: #{v.yaml_val}" : "# #{k}: #{v.yaml_val}"
276
+ end
277
+ value = hash_value
278
+ else
279
+ value = value.yaml_val
280
+ end
281
+ new_config = ""
282
+ new_config += description if description
283
+
284
+ new_config + "#{key}: #{value}"
232
285
  end
233
286
 
287
+ # Reset configuration
234
288
  def restore_prev_config
235
289
  @prev_config&.each do |k, v|
236
290
  SL.config[k] = v
@@ -261,7 +261,11 @@ module SL
261
261
  el_rx = /(\s*(?:[-+*]|\d+\.)?\s+)?(!\S+ )?(\w.*?)$/
262
262
  if l =~ el_rx
263
263
  els = l.match(el_rx)
264
- search = els[2] ? els[2].strip : (m[6] ? m[6] : "!g")
264
+ search = if els[2]
265
+ els[2].strip
266
+ else
267
+ m[6] || "!g"
268
+ end
265
269
  "#{els[1]}[#{els[3].strip}](#{search})"
266
270
  else
267
271
  l
@@ -305,6 +309,7 @@ module SL
305
309
 
306
310
  line.gsub!(/\[(.*?)\]\((.*?)\)/) do |match|
307
311
  this_match = Regexp.last_match
312
+
308
313
  SL.match_column = this_match.begin(0) - @cursor_difference
309
314
  @match_string = this_match.to_s
310
315
  SL.match_length = @match_string.length
@@ -9,6 +9,14 @@ module SL
9
9
  trigger: "a",
10
10
  searches: [
11
11
  ["a", "Amazon Search"]
12
+ ],
13
+ config: [
14
+ {
15
+ key: "amazon_partner",
16
+ value: "bretttercom-20",
17
+ description: "To create Amazon affiliate links, set amazon_partner to your amazon affiliate tag.",
18
+ required: true
19
+ }
12
20
  ]
13
21
  }
14
22
  end
@@ -10,6 +10,19 @@ module SL
10
10
  searches: [
11
11
  ["bl", "bit.ly Shorten"],
12
12
  ["bitly", "bit.ly shorten"]
13
+ ],
14
+ config: [
15
+ {
16
+ key: "bitly_access_token",
17
+ value: "xxxx",
18
+ required: false,
19
+ description: "Generate an access token at https://app.bitly.com/settings/api/"
20
+ },
21
+ {
22
+ key: "bitly_domain",
23
+ value: "bit.ly",
24
+ required: false
25
+ }
13
26
  ]
14
27
  }
15
28
  end
@@ -41,6 +41,8 @@ module SL
41
41
  terms = "%5C#{search_terms.url_encode}"
42
42
  page = Curl::Html.new("https://duckduckgo.com/?q=#{terms}", compressed: true)
43
43
 
44
+ return false if page.meta["refresh"].nil?
45
+
44
46
  locs = page.meta["refresh"].match(%r{/l/\?uddg=(.*?)$})
45
47
  locs = page.body.match(%r{/l/\?uddg=(.*?)'}) if locs.nil?
46
48
  locs = page.body.match(/url=(.*?)'/) if locs.nil?
@@ -12,6 +12,14 @@ module SL
12
12
  ["ghu", "GitHub User Search"],
13
13
  ["gist", "Gist Search"],
14
14
  ["giste", "Gist Embed"]
15
+ ],
16
+ config: [
17
+ {
18
+ key: "github_token",
19
+ value: "github_patxxxxxxx",
20
+ require: false,
21
+ description: "GitHub Personal Access Token (optional)"
22
+ }
15
23
  ]
16
24
  }
17
25
  end
@@ -12,6 +12,14 @@ module SL
12
12
  searches: [
13
13
  ["gg", "Google Search"],
14
14
  ["img", "First image from result"]
15
+ ],
16
+ config: [
17
+ {
18
+ key: "google_api_key",
19
+ value: "xxxxxx",
20
+ required: false,
21
+ description: "Custom Google API key to use Google search (free for 100 queries/day)"
22
+ }
15
23
  ]
16
24
  }
17
25
  end
@@ -43,6 +51,8 @@ module SL
43
51
  return SL.ddg(terms, link_text, google: false, image: image)
44
52
  end
45
53
 
54
+ return false if json["error"] || json["queries"]["request"][0]["totalResults"].to_i.zero? || json["items"].nil?
55
+
46
56
  unless json["queries"]["request"][0]["totalResults"].to_i.positive?
47
57
  SL.notify("no results", "Google returned no results, defaulting to DuckDuckGo")
48
58
  return SL.ddg(terms, link_text, google: false, image: image)
@@ -42,6 +42,32 @@ module SL
42
42
  ["heb", "Edge Bookmark Search"],
43
43
  ["hehb", nil],
44
44
  ["hebh", nil]
45
+ ],
46
+ config: [
47
+ {
48
+ description:
49
+ ["Remove or comment (with #) history searches you don't want",
50
+ "performed by `!h`. You can force-enable them per search, e.g.",
51
+ "`!hsh` (Safari History only), `!hcb` (Chrome Bookmarks only)",
52
+ "etc. Multiple types can be strung together: !hshcb (Safari",
53
+ "History and Chrome bookmarks)"].join(" "),
54
+ required: false,
55
+ key: "history_types",
56
+ value: %w[
57
+ safari_bookmarks
58
+ safari_history
59
+ chrome_history
60
+ chrome_bookmarks
61
+ firefox_bookmarks
62
+ firefox_history
63
+ edge_bookmarks
64
+ edge_history
65
+ brave_bookmarks
66
+ brave_history
67
+ arc_history
68
+ arc_bookmarks
69
+ ]
70
+ }
45
71
  ]
46
72
  }
47
73
  end
@@ -17,6 +17,14 @@ module SL
17
17
  ["itud", "iOS App Store Developer Link"],
18
18
  ["mas", "Mac App Store Search"],
19
19
  ["masd", "Mac App Store Developer Link"]
20
+ ],
21
+ config: [
22
+ {
23
+ description: "append affiliate link info to iTunes urls, empty quotes for none\nexample:\nitunes_affiliate: '&at=10l4tL&ct=searchlink'",
24
+ key: "itunes_affiliate",
25
+ value: "&at=10l4tL&ct=searchlink",
26
+ required: true
27
+ }
20
28
  ]
21
29
  }
22
30
  end
@@ -21,6 +21,25 @@ module SL
21
21
  ["lyrice", "Song Lyrics Embed"],
22
22
  ["lyricjs", "Song Lyrics JS Embed"]
23
23
  ]
24
+ #
25
+ # # The config block is optional, but can be used to define any
26
+ # # configuration options that the plugin requires. New configuration
27
+ # # options that don't exist in current config will be appended
28
+ # config: [
29
+ # {
30
+ # # Description that will appear above the option in config.yaml
31
+ # description: "Genius API"
32
+ # # the configuration key
33
+ # key: "genius_token",
34
+ # # the default value
35
+ # value: "''",
36
+ # # whether the configuration is required. If
37
+ # # false (meaning optional), it will be added
38
+ # # with a # in front of the key in the config
39
+ # # file, making it a comment.
40
+ # required: false
41
+ # }
42
+ # ]
24
43
  }
25
44
  end
26
45
 
@@ -9,8 +9,16 @@ module SL
9
9
  {
10
10
  trigger: "pb",
11
11
  searches: [
12
- ["pb", "Pinboard Bookmark Search"],
12
+ ["pb", "Pinboard Bookmark Search"]
13
13
  ],
14
+ config: [
15
+ {
16
+ description: "Pinboard API key.\nYou can find your api key here: https://pinboard.in/settings/password",
17
+ key: "pinboard_api_key",
18
+ value: "''",
19
+ required: true
20
+ }
21
+ ]
14
22
  }
15
23
  end
16
24
 
@@ -125,7 +133,7 @@ module SL
125
133
  bookmarks.each do |bm|
126
134
  text = [bm["description"], bm["extended"], bm["tags"]].join(" ")
127
135
 
128
- return [bm["href"], bm["description"]] if text.matches_exact(search_terms)
136
+ return [bm["href"], bm["description"], link_text] if text.matches_exact(search_terms)
129
137
  end
130
138
 
131
139
  return false
@@ -148,16 +156,16 @@ module SL
148
156
  full_text = [bm["description"], bm["extended"], bm["tags"]].join(" ")
149
157
 
150
158
  score = if title_tags.matches_exact(search_terms)
151
- 14.0
152
- elsif full_text.matches_exact(search_terms)
153
- 13.0
154
- elsif full_text.matches_any(search_terms)
155
- full_text.matches_score(search_terms)
156
- else
157
- 0
158
- end
159
+ 14.0
160
+ elsif full_text.matches_exact(search_terms)
161
+ 13.0
162
+ elsif full_text.matches_any(search_terms)
163
+ full_text.matches_score(search_terms)
164
+ else
165
+ 0
166
+ end
159
167
 
160
- return [bm["href"], bm["description"]] if score == 14
168
+ return [bm["href"], bm["description"], link_text] if score == 14
161
169
 
162
170
  next unless score.positive?
163
171
 
@@ -165,7 +173,7 @@ module SL
165
173
  score: score,
166
174
  href: bm["href"],
167
175
  title: bm["description"],
168
- date: bm["time"],
176
+ date: bm["time"]
169
177
  })
170
178
  end
171
179
 
@@ -13,6 +13,15 @@ module SL
13
13
  ["@l", "LinkedIn Handle"],
14
14
  ["@m", "Mastodon Handle"],
15
15
  ],
16
+ config: [
17
+ description: "Formatting for social links, use %service%, %user%, and %url%
18
+ E.g. \"%user% on %service%\" => \"ttscoff on Twitter\"
19
+ \"%service%/%user%\" => \"Twitter/ttscoff\"
20
+ \"%url%\" => \"twitter.com/ttscoff\"",
21
+ key: "social_template",
22
+ value: "%service%/%user%",
23
+ required: true
24
+ ]
16
25
  }
17
26
  end
18
27
 
@@ -123,6 +123,7 @@ module SL
123
123
  plugins[type][title] = {
124
124
  trigger: settings.fetch(:trigger, title).normalize_trigger,
125
125
  searches: settings[:searches],
126
+ config: settings[:config],
126
127
  class: klass
127
128
  }
128
129
  end
@@ -3,6 +3,30 @@
3
3
  module SL
4
4
  # String helpers
5
5
  class ::String
6
+ # Quote a YAML value if needed
7
+ def yaml_val
8
+ yaml = YAML.safe_load("key: '#{self}'")
9
+ YAML.dump(yaml).match(/key: (.*?)$/)[1]
10
+ end
11
+
12
+ # Word wrap a string not exceeding max width.
13
+ # CREDIT: Gavin Kistner, Dayne Broderson
14
+ #
15
+ def word_wrap!(col_width = 60, prefix = "")
16
+ replace dup.word_wrap(col_width, prefix)
17
+ end
18
+
19
+ # As with #word_wrap, but modifies the string in place.
20
+ #
21
+ # CREDIT: Gavin Kistner, Dayne Broderson
22
+ #
23
+ def word_wrap(col_width = 60, prefix = "")
24
+ str = dup
25
+ str.gsub!(/(\S{#{col_width}})(?=\S)/, "#{prefix}\\1")
26
+ str.gsub!(/(.{1,#{col_width}})(?:\s+|$)/, "#{prefix}\\1\n")
27
+ str
28
+ end
29
+
6
30
  # Scrub invalid characters from string
7
31
  def scrubup
8
32
  encode("utf-16", invalid: :replace).encode("utf-8").gsub(/\u00A0/, " ")
@@ -239,7 +263,6 @@ module SL
239
263
 
240
264
  SL.add_error("Invalid URL", "Could not remove SEO for #{url}")
241
265
  return self
242
-
243
266
  end
244
267
 
245
268
  path = url.path
@@ -269,7 +292,6 @@ module SL
269
292
  dead_switch = 0
270
293
 
271
294
  while title.downcase.gsub(/[^a-z]/i, "") =~ /#{site_re}/i
272
-
273
295
  break if dead_switch > 5
274
296
 
275
297
  seo_title_separators.each_with_index do |sep, i|
@@ -411,12 +433,12 @@ module SL
411
433
  (1..n).each do |j|
412
434
  (1..m).each do |i|
413
435
  d[i][j] = if s[i - 1] == t[j - 1] # adjust index into string
414
- d[i - 1][j - 1] # no operation required
436
+ d[i - 1][j - 1] # no operation required
415
437
  else
416
438
  [d[i - 1][j] + 1, # deletion
417
439
  d[i][j - 1] + 1, # insertion
418
440
  d[i - 1][j - 1] + 1 # substitution
419
- ].min
441
+ ].min
420
442
  end
421
443
  end
422
444
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SL
4
- VERSION = "2.3.81"
4
+ VERSION = '2.3.83'
5
5
  end
6
6
 
7
7
  # Main module
@@ -46,7 +46,7 @@ module SL
46
46
  }
47
47
  if defined? Secrets::GH_AUTH_TOKEN
48
48
  headers["Authorization"] = "Bearer #{Secrets::GH_AUTH_TOKEN}"
49
- elsif SL.config['github_token']
49
+ elsif SL.config["github_token"]
50
50
  headers["Authorization"] = "Bearer #{SL.settings["github_token"]}"
51
51
  end
52
52
 
data/lib/tokens.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Secrets
2
+ GH_AUTH_TOKEN = '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'
3
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchlink
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.81
4
+ version: 2.3.83
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-01-05 00:00:00.000000000 Z
10
+ date: 2025-03-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -319,6 +319,7 @@ files:
319
319
  - lib/searchlink/util.rb
320
320
  - lib/searchlink/version.rb
321
321
  - lib/searchlink/which.rb
322
+ - lib/tokens.rb
322
323
  homepage: https://github.com/ttscoff/searchlink
323
324
  licenses:
324
325
  - MIT
@@ -337,7 +338,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
337
338
  - !ruby/object:Gem::Version
338
339
  version: '0'
339
340
  requirements: []
340
- rubygems_version: 3.6.2
341
+ rubygems_version: 3.6.6
341
342
  specification_version: 4
342
343
  summary: Create Markdown links from web searches without leaving your editor.
343
344
  test_files: []