searchlink 2.3.86 → 2.3.88

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.
@@ -43,7 +43,9 @@ module SL
43
43
  return false
44
44
  end
45
45
 
46
- url = "https://customsearch.googleapis.com/customsearch/v1?cx=338419ee5ac894523&q=#{ERB::Util.url_encode(search_terms.gsub(/%22/, '"'))}&num=1&key=#{@api_key}"
46
+ url = "https://customsearch.googleapis.com/customsearch/v1?cx=338419ee5ac894523&q=#{ERB::Util.url_encode(search_terms.gsub(
47
+ '%22', '"'
48
+ ))}&num=1&key=#{@api_key}"
47
49
  json = Curl::Json.new(url).json
48
50
 
49
51
  if json["error"] && json["error"]["code"].to_i == 429
@@ -65,7 +67,7 @@ module SL
65
67
  output_title = result["title"]
66
68
  output_title.remove_seo!(output_url) if SL.config["remove_seo"]
67
69
 
68
- output_url = SL.first_image if search_type =~ /img$/
70
+ output_url = SL.first_image(output_url) if search_type =~ /img$/
69
71
 
70
72
  [output_url, output_title, link_text]
71
73
  rescue StandardError
@@ -41,7 +41,7 @@ module SL
41
41
  ["heh", "Edge History Search"],
42
42
  ["heb", "Edge Bookmark Search"],
43
43
  ["hehb", nil],
44
- ["hebh", nil]
44
+ ["hebh", nil],
45
45
  ],
46
46
  config: [
47
47
  {
@@ -65,9 +65,9 @@ module SL
65
65
  brave_history
66
66
  arc_history
67
67
  arc_bookmarks
68
- ]
69
- }
70
- ]
68
+ ],
69
+ },
70
+ ],
71
71
  }
72
72
  end
73
73
 
@@ -156,7 +156,7 @@ module SL
156
156
  end
157
157
 
158
158
  url, title = search_history(search_terms, types)
159
- link_text = title if link_text == "" || link_text == search_terms
159
+ link_text = title if link_text == ""
160
160
  [url, title, link_text]
161
161
  end
162
162
 
@@ -46,7 +46,7 @@ module SL
46
46
  end
47
47
 
48
48
  def get_linkding_bookmarks
49
- curl = TTY::Which.which("curl")
49
+ TTY::Which.which("curl")
50
50
  call = "/api/bookmarks/?limit=8000&format=json"
51
51
 
52
52
  json = get_json(call)
@@ -101,7 +101,7 @@ module SL
101
101
  cache = linkding_bookmarks
102
102
  save_linkding_cache(cache)
103
103
  end
104
- curl = TTY::Which.which("curl")
104
+ TTY::Which.which("curl")
105
105
  updated = get_json("/api/bookmarks/?limit=1&format=json")["results"][0]
106
106
  last_bookmark = Time.parse(updated["date_modified"])
107
107
  if cache&.key?("update_time")
@@ -11,7 +11,7 @@ module SL
11
11
  ["popa", "Popup Amazon Search"],
12
12
  ["popg", "Popup Google Search"],
13
13
  ["popw", "Popup Wikipedia Search"]
14
- ],
14
+ ]
15
15
  }
16
16
  end
17
17
 
@@ -20,20 +20,19 @@ module SL
20
20
 
21
21
  term = search_terms.url_encode
22
22
  url = case type
23
- when /g$/
24
- "https://www.google.com/search?hl=en&q=#{term}"
25
- when /a$/
26
- "https://www.amazon.com/s?k=#{term}"
27
- when /b$/
28
- "https://www.bing.com/search?q=#{term}"
29
- when /w$/
30
- "https://en.wikipedia.org/w/index.php?search=#{term}&title=Special%3ASearch&ns0=1"
31
- else
32
- "https://duckduckgo.com/?q=#{term}&ia=web"
33
- end
23
+ when /g$/
24
+ "https://www.google.com/search?hl=en&q=#{term}"
25
+ when /a$/
26
+ "https://www.amazon.com/s?k=#{term}"
27
+ when /b$/
28
+ "https://www.bing.com/search?q=#{term}"
29
+ when /w$/
30
+ "https://en.wikipedia.org/w/index.php?search=#{term}&title=Special%3ASearch&ns0=1"
31
+ else
32
+ "https://duckduckgo.com/?q=#{term}&ia=web"
33
+ end
34
34
 
35
- path = File.expand_path("~/Library/Services/Preview URL.workflow")
36
- res = `automator -i "#{url}" "#{path}"`.strip
35
+ res = `automator -i "#{url}" "#{SL::Util.popup_path}"`.strip
37
36
 
38
37
  begin
39
38
  if res.empty?
@@ -54,7 +53,7 @@ module SL
54
53
  private
55
54
 
56
55
  def workflow_exist?
57
- unless File.exist?(File.expand_path("~/Library/Services/Preview URL.workflow"))
56
+ unless SL::Util.popup_path
58
57
  SL.add_error("Missing Service", "Preview URL Service not installed")
59
58
  return false
60
59
  end
@@ -65,7 +65,9 @@ module SL
65
65
  end
66
66
 
67
67
  def process_link(link, search_terms, link_text)
68
- SL::URL.valid_link?(link, 2) && [link, search_terms, link_text] || SL.ddg("site:setapp.com #{search_terms}", link_text)
68
+ SL::URL.valid_link?(link,
69
+ 2) && [link, search_terms,
70
+ link_text] || SL.ddg("site:setapp.com #{search_terms}", link_text)
69
71
  end
70
72
 
71
73
  def process_search_type(search_type, link, title, link_text)
@@ -18,22 +18,20 @@ module SL
18
18
  # @return [Boolean] True if the user confirms, false otherwise.
19
19
  #
20
20
  def confirm?(url, title: "Confirm URL?")
21
- if File.exist?(File.expand_path("~/Library/Services/Preview URL.workflow"))
22
- cmd = %(osascript -e "display dialog \\"#{url}\\" with title \\"#{title}\\" buttons {\\"Cancel\\", \\"Confirm\\", \\"Preview\\"}")
21
+
22
+ if SL::Util.popup_path
23
+ cmd = %(osascript -e 'display dialog "#{url}" with title "#{title}" buttons {"Cancel", "Confirm", "Preview"}')
23
24
 
24
25
  res = `#{cmd}`.strip
25
26
 
26
- if res =~ /Preview/
27
- path = File.expand_path("~/Library/Services/Preview URL.workflow")
28
- res = `automator -i "#{url}" "#{path}"`.strip
27
+ return res =~ /Confirm/ unless res =~ /Preview/
28
+
29
+ res = `automator -i "#{url}" "#{SL::Util.popup_path}"`.strip
29
30
 
30
- return res.empty? ? false : res
31
- else
32
- return res =~ /Confirm/
33
- end
31
+ return res.empty? ? false : res
34
32
  end
35
33
 
36
- res = system(%(osascript -e "display dialog \"#{url}\" with title \"#{title}\" buttons {\"Cancel\", \"Confirm\"}"))
34
+ res = system(%(osascript -e 'display dialog "#{url}" with title "#{title}" buttons {"Cancel", "Confirm"}'))
37
35
 
38
36
  res == 0
39
37
  end
@@ -55,12 +53,14 @@ module SL
55
53
  known_shorteners = %i[tinyurl bitly isgd]
56
54
  return url unless known_shorteners.include?(shortener)
57
55
 
58
- # Confirm shortening the URL
59
- res = SL::Shortener.confirm?(url)
56
+ unless NO_CONFIRM
57
+ # Confirm shortening the URL
58
+ res = SL::Shortener.confirm?(url, title: "Shorten URL?")
60
59
 
61
- return url unless res
60
+ return url unless res
62
61
 
63
- url = res if res.is_a?(String)
62
+ url = res if res.is_a?(String)
63
+ end
64
64
 
65
65
  return url unless SL::URL.url?(url)
66
66
 
@@ -58,7 +58,8 @@ module SL
58
58
  "long_url" => url,
59
59
  "domain" => domain
60
60
  }
61
- data = Curl::Json.new("https://api-ssl.bitly.com/v4/shorten", data: data_obj.to_json, headers: headers, symbolize_names: true)
61
+ data = Curl::Json.new("https://api-ssl.bitly.com/v4/shorten", data: data_obj.to_json, headers: headers,
62
+ symbolize_names: true)
62
63
 
63
64
  return false unless data.json.key?(:link)
64
65
 
@@ -44,7 +44,8 @@ module SL
44
44
  data_obj = {
45
45
  "url" => url
46
46
  }
47
- data = Curl::Json.new("https://tinyurl.ph/api/url/add", data: data_obj.to_json, headers: headers, symbolize_names: true)
47
+ data = Curl::Json.new("https://tinyurl.ph/api/url/add", data: data_obj.to_json, headers: headers,
48
+ symbolize_names: true)
48
49
 
49
50
  if data.json[:error].positive?
50
51
  SL.add_error("Error creating tinyurl", data.json[:error])
@@ -11,7 +11,7 @@ module SL
11
11
  ["@f", "Facebook Handle"],
12
12
  ["@i", "Instagram Handle"],
13
13
  ["@l", "LinkedIn Handle"],
14
- ["@m", "Mastodon Handle"],
14
+ ["@m", "Mastodon Handle"]
15
15
  ],
16
16
  config: [
17
17
  description: "Formatting for social links, use %service%, %user%, and %url%
@@ -27,33 +27,38 @@ module SL
27
27
 
28
28
  def search(search_type, search_terms, link_text = "")
29
29
  type = case search_type
30
- when /^@t/ # twitter-ify username
31
- unless search_terms.strip =~ /^@?[0-9a-z_$]+$/i
32
- return [false, "#{search_terms} is not a valid Twitter handle", link_text]
33
- end
34
-
35
- "t"
36
- when /^@fb?/ # fb-ify username
37
- return [false, "#{search_terms} is not a valid Facebook username", link_text] unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
38
-
39
- "f"
40
- when /^@i/ # intagramify username
41
- return [false, "#{search_terms} is not a valid Instagram username", link_text] unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
42
-
43
- "i"
44
- when /^@l/ # linked-inify username
45
- unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
46
- return [false, "#{search_terms} is not a valid LinkedIn username", link_text]
47
- end
48
-
49
- "l"
50
- when /^@m/ # mastodonify username
51
- return [false, "#{search_terms} is not a valid Mastodon username", link_text] unless search_terms.strip =~ /^@?[0-9a-z_]+@[0-9a-z_.]+$/i
52
-
53
- "m"
54
- else
55
- "t"
56
- end
30
+ when /^@t/ # twitter-ify username
31
+ return [false, "#{search_terms} is not a valid Twitter handle", link_text] unless search_terms.strip =~ /^@?[0-9a-z_$]+$/i
32
+
33
+ "t"
34
+ when /^@fb?/ # fb-ify username
35
+ unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
36
+ return [false, "#{search_terms} is not a valid Facebook username",
37
+ link_text]
38
+ end
39
+
40
+ "f"
41
+ when /^@i/ # intagramify username
42
+ unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
43
+ return [false, "#{search_terms} is not a valid Instagram username",
44
+ link_text]
45
+ end
46
+
47
+ "i"
48
+ when /^@l/ # linked-inify username
49
+ return [false, "#{search_terms} is not a valid LinkedIn username", link_text] unless search_terms.strip =~ /^@?[0-9a-z_]+$/i
50
+
51
+ "l"
52
+ when /^@m/ # mastodonify username
53
+ unless search_terms.strip =~ /^@?[0-9a-z_]+@[0-9a-z_.]+$/i
54
+ return [false, "#{search_terms} is not a valid Mastodon username",
55
+ link_text]
56
+ end
57
+
58
+ "m"
59
+ else
60
+ "t"
61
+ end
57
62
 
58
63
  url, title = social_handle(type, search_terms)
59
64
  link_text = title if link_text == ""
@@ -26,19 +26,18 @@ module SL
26
26
 
27
27
  def twitter_embed(tweet)
28
28
  res = `curl -sSL 'https://publish.twitter.com/oembed?url=#{tweet.url_encode}'`.strip
29
- if res
30
- begin
31
- json = JSON.parse(res)
32
- url = "embed"
33
- title = json["html"]
34
- rescue StandardError
35
- SL.add_error("Tweet Error", "Error retrieving tweet")
36
- url = false
37
- title = tweet
38
- end
39
- else
40
- return [false, "Error retrieving tweet"]
29
+ return [false, "Error retrieving tweet"] unless res
30
+
31
+ begin
32
+ json = JSON.parse(res)
33
+ url = "embed"
34
+ title = json["html"]
35
+ rescue StandardError
36
+ SL.add_error("Tweet Error", "Error retrieving tweet")
37
+ url = false
38
+ title = tweet
41
39
  end
40
+
42
41
  [url, title]
43
42
  end
44
43
  end
@@ -43,9 +43,9 @@ 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
50
  "<thead><td>Shortcut</td><td>Search Type</td></thead>",
51
51
  "<tbody>"]
@@ -53,7 +53,7 @@ module SL
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..].join(",")})" : s[0]}
56
+ <code>!#{s[0].is_a?(Array) ? "#{s[0][0]} (#{s[0][1..].join(',')})" : s[0]}
57
57
  </code>
58
58
  </td><td>#{s[1]}</td></tr>"
59
59
  end
@@ -72,10 +72,10 @@ module SL
72
72
 
73
73
  searches.each do |s|
74
74
  shortcut = if s[0].is_a?(Array)
75
- "#{s[0][0]} (#{s[0][1..].join(",")})"
76
- else
77
- s[0]
78
- end
75
+ "#{s[0][0]} (#{s[0][1..].join(',')})"
76
+ else
77
+ s[0]
78
+ end
79
79
 
80
80
  out << "!#{shortcut}#{shortcut.spacer}#{s[1]}"
81
81
  end
@@ -95,7 +95,7 @@ module SL
95
95
 
96
96
  def did_you_mean(term)
97
97
  matches = best_search_match(term)
98
- matches.empty? ? "" : ", did you mean #{matches.map { |m| "!#{m}" }.join(", ")}?"
98
+ matches.empty? ? "" : ", did you mean #{matches.map { |m| "!#{m}" }.join(', ')}?"
99
99
  end
100
100
 
101
101
  def valid_searches
@@ -106,7 +106,7 @@ module SL
106
106
 
107
107
  def valid_search?(term)
108
108
  valid = false
109
- valid = true if term =~ /^(#{valid_searches.join("|")})$/
109
+ valid = true if term =~ /^(#{valid_searches.join('|')})$/
110
110
  valid = true if SL.config["custom_site_searches"].keys.include? term
111
111
  # SL.notify("Invalid search#{did_you_mean(term)}", term) unless valid
112
112
  valid
@@ -124,7 +124,7 @@ module SL
124
124
  trigger: settings.fetch(:trigger, title).normalize_trigger,
125
125
  searches: settings[:searches],
126
126
  config: settings[:config],
127
- class: klass,
127
+ class: klass
128
128
  }
129
129
  end
130
130
 
@@ -155,11 +155,11 @@ module SL
155
155
  config = IO.read(file)
156
156
 
157
157
  cfg = case ext
158
- when /^y/i
159
- YAML.safe_load(config)
160
- else
161
- JSON.parse(config)
162
- end
158
+ when /^y/i
159
+ YAML.safe_load(config)
160
+ else
161
+ JSON.parse(config)
162
+ end
163
163
  cfg["filename"] = File.basename(file)
164
164
  cfg["path"] = file.shorten_path
165
165
  SL::ScriptSearch.new(cfg)
@@ -190,7 +190,7 @@ require_relative "searches/itunes"
190
190
  # import
191
191
  require_relative "searches/amazon"
192
192
 
193
- #import
193
+ # import
194
194
  require_relative "searches/shortener"
195
195
 
196
196
  # import
@@ -3,6 +3,32 @@
3
3
  module SL
4
4
  # String helpers
5
5
  class ::String
6
+ # Scan a string for links
7
+ # @return [Hash] Hash of links
8
+ def scan_links
9
+ links = {}
10
+ scan(/\[(.*?)\]:\s+(.*?)\n/).each { |match| links[match[1].strip] = match[0] }
11
+ links
12
+ end
13
+
14
+ # Count the indent level of a string
15
+ # @return [Integer] The indent level
16
+ def indent_level
17
+ return 0 if empty?
18
+
19
+ gsub!(/^ /, "\t") while self =~ /^ /
20
+ indent = match(/^\t+/)
21
+ return 0 unless indent
22
+
23
+ indent[0].length
24
+ end
25
+
26
+ # Count the links in a string
27
+ # @return [Integer] The number of links
28
+ def count_links
29
+ scan(/\[(.*?)\]\((.*?)\)/).length
30
+ end
31
+
6
32
  # Quote a YAML value if needed
7
33
  def yaml_val
8
34
  yaml = YAML.safe_load("key: '#{self}'")
@@ -59,15 +85,15 @@ module SL
59
85
 
60
86
  shortener = split(/_/).last
61
87
  SL.shortener = case shortener
62
- when /i/i
63
- :isgd
64
- when /b/i
65
- :bitly
66
- when /t/i
67
- :tinyurl
68
- else
69
- :none
70
- end
88
+ when /i/i
89
+ :isgd
90
+ when /b/i
91
+ :bitly
92
+ when /t/i
93
+ :tinyurl
94
+ else
95
+ :none
96
+ end
71
97
 
72
98
  sub(/_[ibt]$/i, "")
73
99
  end
@@ -89,10 +115,10 @@ module SL
89
115
  query = SL.query.map { |k, v| "#{k}=#{v}" }.join("&")
90
116
 
91
117
  query = if self =~ /\?[^= ]+=\S+/
92
- "&#{query}"
93
- else
94
- "?#{query}"
95
- end
118
+ "&#{query}"
119
+ else
120
+ "?#{query}"
121
+ end
96
122
 
97
123
  "#{self}#{query}"
98
124
  end
@@ -151,23 +177,23 @@ module SL
151
177
  output = " "
152
178
  m[2].split("").each do |arg|
153
179
  output += case arg
154
- when "c"
155
- "--#{bool}confirm"
156
- when "d"
157
- "--#{bool}debug "
158
- when "i"
159
- "--#{bool}inline "
160
- when "r"
161
- "--#{bool}prefix_random "
162
- when "t"
163
- "--#{bool}include_titles "
164
- when "v"
165
- "--#{bool}validate_links "
166
- when "s"
167
- "--#{bool}remove_seo "
168
- else
169
- ""
170
- end
180
+ when "c"
181
+ "--#{bool}confirm"
182
+ when "d"
183
+ "--#{bool}debug "
184
+ when "i"
185
+ "--#{bool}inline "
186
+ when "r"
187
+ "--#{bool}prefix_random "
188
+ when "t"
189
+ "--#{bool}include_titles "
190
+ when "v"
191
+ "--#{bool}validate_links "
192
+ when "s"
193
+ "--#{bool}remove_seo "
194
+ else
195
+ ""
196
+ end
171
197
  end
172
198
 
173
199
  output
@@ -310,7 +336,7 @@ module SL
310
336
  "‘" => "’",
311
337
  "[" => "]",
312
338
  "(" => ")",
313
- "<" => ">",
339
+ "<" => ">"
314
340
  }
315
341
 
316
342
  left_punct = []
@@ -380,7 +406,7 @@ module SL
380
406
  # p_re = path.path_elements.map{|seg| seg.downcase.split(//).join('.?') }.join('|')
381
407
  # re_parts.push(p_re) if p_re.length > 0
382
408
 
383
- site_re = "(#{re_parts.join("|")})"
409
+ site_re = "(#{re_parts.join('|')})"
384
410
 
385
411
  dead_switch = 0
386
412
 
@@ -405,14 +431,14 @@ module SL
405
431
  end
406
432
 
407
433
  title = if parts.empty?
408
- longest
409
- elsif parts.length < 2
410
- parts.join(sep)
411
- elsif parts.length > 2
412
- parts.longest_element.strip
413
- else
414
- parts.join(sep)
415
- end
434
+ longest
435
+ elsif parts.length < 2
436
+ parts.join(sep)
437
+ elsif parts.length > 2
438
+ parts.longest_element.strip
439
+ else
440
+ parts.join(sep)
441
+ end
416
442
  end
417
443
  dead_switch += 1
418
444
  end
@@ -423,7 +449,7 @@ module SL
423
449
  return self
424
450
  end
425
451
 
426
- seps = Regexp.new(" *[#{seo_title_separators.map { |s| Regexp.escape(s) }.join("")}] +")
452
+ seps = Regexp.new(" *[#{seo_title_separators.map { |s| Regexp.escape(s) }.join('')}] +")
427
453
  if title =~ seps
428
454
  seo_parts = title.split(seps)
429
455
  title = seo_parts.longest_element.strip if seo_parts.length.positive?
@@ -526,13 +552,13 @@ module SL
526
552
  (1..n).each do |j|
527
553
  (1..m).each do |i|
528
554
  d[i][j] = if s[i - 1] == t[j - 1] # adjust index into string
529
- d[i - 1][j - 1] # no operation required
530
- else
531
- [d[i - 1][j] + 1, # deletion
532
- d[i][j - 1] + 1, # insertion
533
- d[i - 1][j - 1] + 1 # substitution
534
- ].min
535
- end
555
+ d[i - 1][j - 1] # no operation required
556
+ else
557
+ [d[i - 1][j] + 1, # deletion
558
+ d[i][j - 1] + 1, # insertion
559
+ d[i - 1][j - 1] + 1 # substitution
560
+ ].min
561
+ end
536
562
  end
537
563
  end
538
564
  d[m][n]
@@ -545,7 +571,7 @@ module SL
545
571
  ##
546
572
  def matches_exact(string)
547
573
  comp = gsub(/[^a-z0-9 ]/i, "")
548
- comp =~ /\b#{string.gsub(/[^a-z0-9 ]/i, "").split(/ +/).map { |s| Regexp.escape(s) }.join(" +")}/i
574
+ comp =~ /\b#{string.gsub(/[^a-z0-9 ]/i, '').split(/ +/).map { |s| Regexp.escape(s) }.join(' +')}/i
549
575
  end
550
576
 
551
577
  ##
@@ -593,7 +619,7 @@ module SL
593
619
  def to_rx_array(separator: " ", start_word: true)
594
620
  bound = start_word ? '\b' : ""
595
621
  str = gsub(/(#{separator})+/, separator)
596
- str.split(/#{separator}/).map { |arg| /#{bound}#{arg.gsub(/[^a-z0-9]/i, ".?")}/i }
622
+ str.split(/#{separator}/).map { |arg| /#{bound}#{arg.gsub(/[^a-z0-9]/i, '.?')}/i }
597
623
  end
598
624
 
599
625
  ##
@@ -66,7 +66,7 @@ module SL
66
66
  end
67
67
 
68
68
  def only_url?(input)
69
- input =~ %r{(?i)^((http|https)://)?([\w\-_]+(\.[\w\-_]+)+)([\w\-.,@?^=%&amp;:/~+#]*[\w\-@^=%&amp;/~+#])?$}
69
+ input =~ %r{(?i)^(https?://)?([\w-]+(\.[\w-]+)+)([\w\-.,@?^=%&amp;:/~+#]*[\w\-@^=%&amp;/~+#])?$}
70
70
  end
71
71
 
72
72
  def ref_title_for_url(url)
@@ -110,7 +110,10 @@ module SL
110
110
  def amazon_affiliatize(url, amazon_partner)
111
111
  return url if amazon_partner.nil? || amazon_partner.empty?
112
112
 
113
- return [url, ""] unless url =~ %r{https?://(?<subdomain>.*?)amazon.com/(?:(?<title>.*?)/)?(?<type>[dg])p/(?<id>[^?]+)}
113
+ unless url =~ %r{https?://(?<subdomain>.*?)amazon.com/(?:(?<title>.*?)/)?(?<type>[dg])p/(?<id>[^?]+)}
114
+ return [url,
115
+ ""]
116
+ end
114
117
 
115
118
  m = Regexp.last_match
116
119
  sd = m["subdomain"]
@@ -86,6 +86,19 @@ module SL
86
86
  FileUtils.mkdir_p(cache_folder) unless File.directory?(cache_folder)
87
87
  File.join(cache_folder, filename.sub(/(\.cache)?$/, ".cache"))
88
88
  end
89
+
90
+ # Checks if the Preview URL.workflow exists, return path if it does.
91
+ def popup_path
92
+ begin
93
+ path = File.expand_path(File.join(__dir__, "../../helpers/Preview URL.workflow"))
94
+ path = File.expand_path("~/Library/Services/Preview URL.workflow") unless File.exist?(path)
95
+ rescue
96
+ path = File.expand_path("~/Library/Services/Preview URL.workflow")
97
+ end
98
+ return false unless File.exist?(path)
99
+
100
+ path
101
+ end
89
102
  end
90
103
  end
91
104
  end