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.
- checksums.yaml +4 -4
- data/bin/searchlink +20 -19
- data/lib/searchlink/config.rb +1 -1
- data/lib/searchlink/curl/html.rb +24 -21
- data/lib/searchlink/curl/json.rb +5 -7
- data/lib/searchlink/help.rb +6 -2
- data/lib/searchlink/output.rb +28 -16
- data/lib/searchlink/parse.rb +425 -405
- data/lib/searchlink/plist/generator.rb +178 -0
- data/lib/searchlink/plist/parser.rb +263 -0
- data/lib/searchlink/plist/version.rb +5 -0
- data/lib/searchlink/plist.rb +12 -202
- data/lib/searchlink/script_plugin.rb +1 -3
- data/lib/searchlink/search.rb +1 -5
- data/lib/searchlink/searches/duckduckgo.rb +2 -1
- data/lib/searchlink/searches/google.rb +4 -2
- data/lib/searchlink/searches/history.rb +5 -5
- data/lib/searchlink/searches/linkding.rb +2 -2
- data/lib/searchlink/searches/popup.rb +14 -15
- data/lib/searchlink/searches/setapp.rb +3 -1
- data/lib/searchlink/searches/shortener.rb +14 -14
- data/lib/searchlink/searches/shorteners/bitly.rb +2 -1
- data/lib/searchlink/searches/shorteners/tinyurl.rb +2 -1
- data/lib/searchlink/searches/social.rb +33 -28
- data/lib/searchlink/searches/twitter.rb +11 -12
- data/lib/searchlink/searches.rb +17 -17
- data/lib/searchlink/string.rb +76 -50
- data/lib/searchlink/url.rb +5 -2
- data/lib/searchlink/util.rb +13 -0
- data/lib/searchlink/version.rb +4 -4
- data/lib/searchlink.rb +3 -3
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d1e0567872f0b80b0d51b37a4522c91cd70f3af268b07ee9d2ed35e56ee3288
|
4
|
+
data.tar.gz: a5327a1f2e2d355b3f1ba7c5818f9b51c640207e3e0e48374527038e4e2d049e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bbf35b751bbdfc03e990ef90de99b62117183759640c0ffc102d606be0aed4e8982bec6d1bfaec7ffc67e0dd4670252174307ef2d8953752402f6789e388953
|
7
|
+
data.tar.gz: 1f2e05c2e4220b8f38a6bebe99c1ca019474d8dde50e2c61ecf57e557c265ad2536d317a5d7e47ad5583dc065ae983fa475f215650e1ceeb24c24b1e07440618
|
data/bin/searchlink
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
|
-
SILENT = ENV
|
5
|
-
|
4
|
+
SILENT = ENV.fetch("SL_SILENT", nil) =~ /false/i ? false : true
|
5
|
+
NO_CONFIRM = ENV.fetch("SL_NO_CONFIRM", nil) =~ /true/i ? true : false
|
6
|
+
$LOAD_PATH.unshift File.join(__dir__, "..")
|
6
7
|
|
7
8
|
# import
|
8
|
-
require
|
9
|
+
require "lib/searchlink"
|
9
10
|
|
10
11
|
if RUBY_VERSION.to_f > 1.9
|
11
12
|
Encoding.default_external = Encoding::UTF_8
|
@@ -20,9 +21,19 @@ SL::Searches.load_custom
|
|
20
21
|
# SL::Searches.load_searches
|
21
22
|
|
22
23
|
overwrite = true
|
23
|
-
backup = SL.config[
|
24
|
+
backup = SL.config["backup"]
|
24
25
|
|
25
|
-
if
|
26
|
+
if ARGV.empty?
|
27
|
+
input = $stdin.read.scrubup
|
28
|
+
sl.parse(input)
|
29
|
+
output = SL.output&.join
|
30
|
+
|
31
|
+
if SL.clipboard
|
32
|
+
print input
|
33
|
+
else
|
34
|
+
print output
|
35
|
+
end
|
36
|
+
else
|
26
37
|
files = []
|
27
38
|
ARGV.each do |arg|
|
28
39
|
case arg
|
@@ -30,7 +41,7 @@ if !ARGV.empty?
|
|
30
41
|
print SL.version_check
|
31
42
|
puts
|
32
43
|
sl.help_cli
|
33
|
-
$stdout.puts
|
44
|
+
$stdout.puts "See https://github.com/ttscoff/searchlink/wiki for help"
|
34
45
|
Process.exit 0
|
35
46
|
when /^(--?)?v(er(s(ion)?)?)?$/
|
36
47
|
print SL.version_check
|
@@ -46,7 +57,7 @@ if !ARGV.empty?
|
|
46
57
|
|
47
58
|
files.each do |file|
|
48
59
|
if File.exist?(file) && `file -b "#{file}"|grep -c text`.to_i.positive?
|
49
|
-
input =
|
60
|
+
input = File.read(file).scrubup
|
50
61
|
|
51
62
|
backup_file = "#{file}.bak"
|
52
63
|
backup_file = "#{file}.bak 1" if File.exist?(backup_file)
|
@@ -55,12 +66,12 @@ if !ARGV.empty?
|
|
55
66
|
FileUtils.cp(file, backup_file) if backup && overwrite
|
56
67
|
|
57
68
|
sl.parse(input)
|
58
|
-
output = SL.output&.join
|
69
|
+
output = SL.output&.join
|
59
70
|
|
60
71
|
next unless output
|
61
72
|
|
62
73
|
if overwrite
|
63
|
-
File.open(file,
|
74
|
+
File.open(file, "w") do |f|
|
64
75
|
f.puts output
|
65
76
|
end
|
66
77
|
else
|
@@ -70,14 +81,4 @@ if !ARGV.empty?
|
|
70
81
|
warn "Error reading #{file}"
|
71
82
|
end
|
72
83
|
end
|
73
|
-
else
|
74
|
-
input = $stdin.read.scrubup
|
75
|
-
sl.parse(input)
|
76
|
-
output = SL.output&.join('')
|
77
|
-
|
78
|
-
if SL.clipboard
|
79
|
-
print input
|
80
|
-
else
|
81
|
-
print output
|
82
|
-
end
|
83
84
|
end
|
data/lib/searchlink/config.rb
CHANGED
@@ -184,7 +184,7 @@ module SL
|
|
184
184
|
# hash can override existing search triggers.
|
185
185
|
config["custom_site_searches"] ||= {
|
186
186
|
"bt" => "brettterpstra.com",
|
187
|
-
"imdb" => "imdb.com"
|
187
|
+
"imdb" => "imdb.com"
|
188
188
|
}
|
189
189
|
|
190
190
|
# confirm existence of links generated from custom search replacements
|
data/lib/searchlink/curl/html.rb
CHANGED
@@ -90,7 +90,7 @@ module Curl
|
|
90
90
|
tag: tag,
|
91
91
|
source: tag_source,
|
92
92
|
attrs: attrs,
|
93
|
-
content: contents
|
93
|
+
content: contents
|
94
94
|
}
|
95
95
|
end
|
96
96
|
|
@@ -142,12 +142,12 @@ module Curl
|
|
142
142
|
def images
|
143
143
|
output = []
|
144
144
|
%w[og:image twitter:image].each do |src|
|
145
|
-
next unless @meta
|
145
|
+
next unless @meta&.key?(src)
|
146
146
|
|
147
147
|
output << {
|
148
148
|
type: "opengraph",
|
149
149
|
attrs: nil,
|
150
|
-
src: @meta[src]
|
150
|
+
src: @meta[src]
|
151
151
|
}
|
152
152
|
end
|
153
153
|
images = tags(%w[img source])
|
@@ -162,21 +162,21 @@ module Curl
|
|
162
162
|
image, media = s.split(/ /)
|
163
163
|
srcset << {
|
164
164
|
src: image,
|
165
|
-
media: media
|
165
|
+
media: media
|
166
166
|
}
|
167
167
|
end
|
168
168
|
end
|
169
169
|
output << {
|
170
170
|
type: "srcset",
|
171
171
|
attrs: img[:attrs],
|
172
|
-
images: srcset
|
172
|
+
images: srcset
|
173
173
|
}
|
174
174
|
end
|
175
175
|
when /img/
|
176
176
|
output << {
|
177
177
|
type: "img",
|
178
178
|
src: img[:attrs].filter { |a| a[:key] =~ /src/i }.first[:value],
|
179
|
-
attrs: img[:attrs]
|
179
|
+
attrs: img[:attrs]
|
180
180
|
}
|
181
181
|
end
|
182
182
|
end
|
@@ -189,7 +189,7 @@ module Curl
|
|
189
189
|
links = @links.nil? ? 0 : @links.count
|
190
190
|
[
|
191
191
|
%(<HTMLCurl: @code="#{@code}" @url="#{@url}" @title="#{@title}"),
|
192
|
-
%(@description=#{@description} @headers:#{headers} @meta:#{meta} @links:#{links}>)
|
192
|
+
%(@description=#{@description} @headers:#{headers} @meta:#{meta} @links:#{links}>)
|
193
193
|
].join(" ")
|
194
194
|
end
|
195
195
|
|
@@ -202,11 +202,13 @@ module Curl
|
|
202
202
|
##
|
203
203
|
def h(level = '\d')
|
204
204
|
res = []
|
205
|
-
headlines = @body.to_enum(:scan, %r{<h(?<level>#{level})(?<tag> .*?)?>(?<text>.*?)</h#{level}>}i).map
|
205
|
+
headlines = @body.to_enum(:scan, %r{<h(?<level>#{level})(?<tag> .*?)?>(?<text>.*?)</h#{level}>}i).map do
|
206
|
+
Regexp.last_match
|
207
|
+
end
|
206
208
|
headlines.each do |m|
|
207
209
|
headline = { level: m["level"] }
|
208
210
|
if m["tag"].nil?
|
209
|
-
|
211
|
+
nil
|
210
212
|
else
|
211
213
|
attrs = m["tag"].to_enum(:scan, /(?<attr>\w+)=(?<quot>["'])(?<content>.*?)\k<quot>/).map { Regexp.last_match }
|
212
214
|
attrs.each { |a| headline[a["attr"].to_sym] = a["content"] }
|
@@ -256,10 +258,10 @@ module Curl
|
|
256
258
|
|
257
259
|
attrs.map! do |a|
|
258
260
|
val = if a["key"] =~ /^(class|rel)$/
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
261
|
+
a["value"].nil? ? "" : a["value"].split(/ /)
|
262
|
+
else
|
263
|
+
a["value"]
|
264
|
+
end
|
263
265
|
{ key: a["key"], value: val }
|
264
266
|
end
|
265
267
|
end
|
@@ -268,7 +270,7 @@ module Curl
|
|
268
270
|
source: tag.to_s,
|
269
271
|
attrs: attrs,
|
270
272
|
content: tag["content"],
|
271
|
-
tags: content_tags(tag["content"])
|
273
|
+
tags: content_tags(tag["content"])
|
272
274
|
}
|
273
275
|
end
|
274
276
|
end
|
@@ -359,7 +361,7 @@ module Curl
|
|
359
361
|
title: title,
|
360
362
|
rel: rel,
|
361
363
|
text: text,
|
362
|
-
class: link_class
|
364
|
+
class: link_class
|
363
365
|
}
|
364
366
|
links << link
|
365
367
|
end
|
@@ -402,9 +404,7 @@ module Curl
|
|
402
404
|
headers = headers.nil? ? "" : headers.map { |h, v| %(-H "#{h}: #{v}") }.join(" ")
|
403
405
|
compress = compressed ? "--compressed" : ""
|
404
406
|
source = `#{@curl} -#{flags} #{compress} #{headers} '#{url}' 2>/dev/null`
|
405
|
-
if source.nil? || source.empty?
|
406
|
-
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null`
|
407
|
-
end
|
407
|
+
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null` if source.nil? || source.empty?
|
408
408
|
|
409
409
|
return false if source.nil? || source.empty?
|
410
410
|
|
@@ -425,18 +425,21 @@ module Curl
|
|
425
425
|
end
|
426
426
|
|
427
427
|
if headers["content-type"] =~ /json/
|
428
|
-
return { url: url, code: code, headers: headers, meta: nil, links: nil, head: nil, body: source.strip,
|
428
|
+
return { url: url, code: code, headers: headers, meta: nil, links: nil, head: nil, body: source.strip,
|
429
|
+
source: source.strip, body_links: nil, body_images: nil }
|
429
430
|
end
|
430
431
|
|
431
432
|
head = source.match(%r{(?<=<head>)(.*?)(?=</head>)}mi)
|
432
433
|
|
433
434
|
if head.nil?
|
434
|
-
{ url: url, code: code, headers: headers, meta: nil, links: nil, head: nil, body: source.strip,
|
435
|
+
{ url: url, code: code, headers: headers, meta: nil, links: nil, head: nil, body: source.strip,
|
436
|
+
source: source.strip, body_links: nil, body_images: nil }
|
435
437
|
else
|
436
438
|
meta = meta_tags(head[1])
|
437
439
|
links = link_tags(head[1])
|
438
440
|
body = source.match(%r{<body.*?>(.*?)</body>}mi)[1]
|
439
|
-
{ url: url, code: code, headers: headers, meta: meta, links: links, head: head[1], body: body,
|
441
|
+
{ url: url, code: code, headers: headers, meta: meta, links: links, head: head[1], body: body,
|
442
|
+
source: source.strip, body_links: body_links, body_images: body_images }
|
440
443
|
end
|
441
444
|
end
|
442
445
|
|
data/lib/searchlink/curl/json.rb
CHANGED
@@ -28,10 +28,10 @@ module Curl
|
|
28
28
|
target = json
|
29
29
|
parts.each do |part|
|
30
30
|
target = if part =~ /(?<key>[^\[]+)\[(?<int>\d+)\]/
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
target[key][int.to_i]
|
32
|
+
else
|
33
|
+
target[part]
|
34
|
+
end
|
35
35
|
end
|
36
36
|
|
37
37
|
target
|
@@ -58,9 +58,7 @@ module Curl
|
|
58
58
|
compress = compressed ? "--compressed" : ""
|
59
59
|
|
60
60
|
source = `#{@curl} -#{flags} #{compress} #{headers} #{data} "#{url}" 2>/dev/null`
|
61
|
-
if source.nil? || source.empty?
|
62
|
-
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null`
|
63
|
-
end
|
61
|
+
source = `#{@curl} -#{flags} #{compress} -A "#{agent}" #{headers} '#{url}' 2>/dev/null` if source.nil? || source.empty?
|
64
62
|
|
65
63
|
return false if source.nil? || source.empty?
|
66
64
|
|
data/lib/searchlink/help.rb
CHANGED
@@ -67,7 +67,9 @@ module SL
|
|
67
67
|
|
68
68
|
if SL.config["custom_site_searches"]
|
69
69
|
text += "\n-- [Custom Searches] ----------------------\n"
|
70
|
-
SL.config["custom_site_searches"].sort_by
|
70
|
+
SL.config["custom_site_searches"].sort_by do |l, _s|
|
71
|
+
l
|
72
|
+
end.each { |label, site| text += "!#{label}#{label.spacer} #{site}\n" }
|
71
73
|
end
|
72
74
|
text
|
73
75
|
end
|
@@ -80,7 +82,9 @@ module SL
|
|
80
82
|
out << '<table id="custom">'
|
81
83
|
out << "<thead><td>Shortcut</td><td>Search Type</td></thead>"
|
82
84
|
out << "<tbody>"
|
83
|
-
SL.config["custom_site_searches"].each
|
85
|
+
SL.config["custom_site_searches"].each do |label, site|
|
86
|
+
out << "<tr><td><code>!#{label}</code></td><td>#{site}</td></tr>"
|
87
|
+
end
|
84
88
|
out << "</tbody>"
|
85
89
|
out << "</table>"
|
86
90
|
out.join("\n")
|
data/lib/searchlink/output.rb
CHANGED
@@ -3,14 +3,19 @@
|
|
3
3
|
module SL
|
4
4
|
class << self
|
5
5
|
attr_writer :titleize, :clipboard, :output, :footer, :line_num,
|
6
|
-
:match_column, :match_length, :originput, :errors, :
|
7
|
-
:shortener
|
6
|
+
:match_column, :match_length, :originput, :errors, :error_count,
|
7
|
+
:report, :printout, :shortener
|
8
8
|
|
9
9
|
# Whether or not to add a title to the output
|
10
10
|
def titleize
|
11
11
|
@titleize ||= false
|
12
12
|
end
|
13
13
|
|
14
|
+
# Count of errors
|
15
|
+
def error_count
|
16
|
+
@error_count ||= 0
|
17
|
+
end
|
18
|
+
|
14
19
|
# Whether or not to copy results to clipbpard
|
15
20
|
def clipboard
|
16
21
|
@clipboard ||= false
|
@@ -106,11 +111,17 @@ module SL
|
|
106
111
|
# @return [String] The link.
|
107
112
|
#
|
108
113
|
def make_link(type, text, url, title: false, force_title: false)
|
109
|
-
|
110
|
-
|
111
|
-
|
114
|
+
url.sub!(%r{^//}, "https://")
|
115
|
+
is_image = url =~ /(gif|jpe?g|png|webp)(?:\?.*?)?$/ ? true : false
|
116
|
+
if is_image
|
117
|
+
title = text || File.basename(url).sub(/\?.*$/, "")
|
118
|
+
text = title if text.nil? || text.strip.empty?
|
119
|
+
else
|
120
|
+
title = title.gsub(/\P{Print}|\p{Cf}/, "") if title
|
121
|
+
text = title || SL::URL.title(url) if SL.titleize && (!text || text.strip.empty?)
|
122
|
+
text = text ? text.strip : title
|
123
|
+
end
|
112
124
|
title = title && (SL.config["include_titles"] || force_title) ? %( "#{title.clean}") : ""
|
113
|
-
|
114
125
|
title = title.gsub(/[ \t]+/, " ")
|
115
126
|
|
116
127
|
url.add_query_string!
|
@@ -123,8 +134,7 @@ module SL
|
|
123
134
|
when :ref_link
|
124
135
|
%([#{text}][#{url}])
|
125
136
|
when :inline
|
126
|
-
|
127
|
-
%(#{image}[#{text}](#{url}#{title}))
|
137
|
+
%(#{is_image ? '!' : ''}[#{text}](#{url}#{title}))
|
128
138
|
end
|
129
139
|
end
|
130
140
|
|
@@ -214,6 +224,8 @@ module SL
|
|
214
224
|
end
|
215
225
|
SL.errors[type] ||= []
|
216
226
|
SL.errors[type].push("(#{position}): #{str}")
|
227
|
+
SL.error_count ||= 0
|
228
|
+
SL.error_count += 1
|
217
229
|
end
|
218
230
|
|
219
231
|
# Add to query string
|
@@ -248,10 +260,10 @@ module SL
|
|
248
260
|
|
249
261
|
out = ""
|
250
262
|
inline = if SL.originput.split(/\n/).length > 1
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
263
|
+
false
|
264
|
+
else
|
265
|
+
SL.config["inline"] || SL.originput.split(/\n/).length == 1
|
266
|
+
end
|
255
267
|
|
256
268
|
SL.errors.each do |k, v|
|
257
269
|
next if v.empty?
|
@@ -259,10 +271,10 @@ module SL
|
|
259
271
|
v.each_with_index do |err, i|
|
260
272
|
out += "(#{k}) #{err}"
|
261
273
|
out += if inline
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
274
|
+
i == v.length - 1 ? " | " : ", "
|
275
|
+
else
|
276
|
+
"\n"
|
277
|
+
end
|
266
278
|
end
|
267
279
|
end
|
268
280
|
|