lslinks 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bcaf27dbf9771119d244c77f11a2c8c635c21579390cf8871b2131eb4b4e514d
4
+ data.tar.gz: 2c5e76d18208a9a582077d83662c34110d002533849ea23e2edf7e967854ff74
5
+ SHA512:
6
+ metadata.gz: 91de13c8881a9daf128e1e1bc4e16232453501c90791337bbad074c1041f58ea444be450f2fc068690b5cb8f8b97a3e4cf7d28b3e850bee04a0da5fd43d06c2a
7
+ data.tar.gz: 44910da85da36eb115f348830976aef77c6c29cf97c04899a3894ec26ba1d1fdcd033c1b67b0dda2929c932a252aacb07bc8124f944a31da2591f5460207e809
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2023 Yuya.Nishida.
2
+
3
+ X11 License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # lslinks
2
+
3
+ A command line tool to list links.
4
+
5
+ ## Installation
6
+
7
+ ```console
8
+ $ gem install lslinks
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### list links
14
+
15
+ ```console
16
+ $ lslinks https://www.ruby-lang.org/
17
+ /en/
18
+ ```
19
+
20
+ ### list links with text
21
+
22
+ ```console
23
+ $ lslinks -l https://www.ruby-lang.org/
24
+ /en/ Click here
25
+ ```
26
+
27
+ ### list links as Full URL
28
+
29
+ ```console
30
+ $ lslinks -k https://www.ruby-lang.org/
31
+ https://www.ruby-lang.org/en/
32
+ ```
33
+
34
+ ## Development
35
+
36
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
+
38
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
+
40
+ ## Contributing
41
+
42
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nishidayuya/lslinks .
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/exe/lslinks ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "lslinks"
4
+
5
+ Lslinks::Cli.run(ARGV)
@@ -0,0 +1,18 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Cli
4
+ class << self
5
+ def run(argv)
6
+ options, resource_name = *Lslinks::OptionParser.(argv)
7
+ Lslinks::Reader.open(resource_name, **options) do |resource_stream|
8
+ Lslinks::Parser.each_link(resource_stream, **options) do |link|
9
+ Lslinks::Formatter.output(resource_name, link, **options)
10
+ end
11
+ end
12
+ rescue => e
13
+ raise if Lslinks.debug?
14
+
15
+ $stderr.puts(e.message)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,4 @@
1
+ require "lslinks"
2
+
3
+ class Lslinks::Error::UnsupportedResource < Lslinks::Error
4
+ end
@@ -0,0 +1,4 @@
1
+ require "lslinks"
2
+
3
+ class Lslinks::Error < StandardError
4
+ end
@@ -0,0 +1,22 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Formatter
4
+ class << self
5
+ def output(resource_name, link, stdout: $stdout, **options)
6
+ link_uri = if options[:convert_links]
7
+ URI(resource_name) + link.url
8
+ else
9
+ link.uri
10
+ end
11
+
12
+ output_record = [link_uri]
13
+ output_record << squeeze_text(link.text) if options[:list_mode]
14
+
15
+ stdout.puts(output_record.join("\t"))
16
+ end
17
+
18
+ private
19
+
20
+ def squeeze_text(text) = text.gsub(/\s+/, " ").strip
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ require "lslinks"
2
+
3
+ class Lslinks::Link < Data.define(:url, :text)
4
+ class << self
5
+ def from_nokogiri_element(element)
6
+ return new(url: element.attr("href"), text: element.text)
7
+ end
8
+ end
9
+
10
+ def uri = URI(url)
11
+ end
@@ -0,0 +1,50 @@
1
+ require "lslinks"
2
+
3
+ class Lslinks::OptionParser < OptionParser
4
+ class << self
5
+ def call(argv)
6
+ parser = new
7
+ parser.banner = "Usage: #{File.basename(Process.argv0)} [OPTIONS] URI_or_path"
8
+ parser.version = Lslinks::VERSION
9
+ parser.separator("")
10
+ parser.separator("Basic options:")
11
+ parser.on("-l", "list links with text")
12
+ parser.on("-k", "--convert-links", "convert links to full URL")
13
+ parser.separator("")
14
+ parser.separator("HTTP input options:")
15
+ parser.on("--user-agent=USER_AGENT") # from curl wget
16
+ parser.on("--referer=REFERER") # from curl wget
17
+ parser.on("--header=HEADER") # from curl wget
18
+ options = {
19
+ http_headers: {},
20
+ }
21
+ rest_args = parser.order(argv, into: options)
22
+ resource_name = rest_args.shift
23
+ if !resource_name
24
+ $stderr.puts(parser.help)
25
+ exit(1)
26
+ end
27
+ return options, resource_name
28
+ end
29
+ end
30
+
31
+ def order!(argv, into:, &nonopt)
32
+ setter = ->(name, val) do
33
+ symbolized_name = name.gsub("-", "_").to_sym
34
+ case symbolized_name
35
+ when :l
36
+ into[:list_mode] = true
37
+ when :user_agent
38
+ into[:http_headers]["User-Agent"] = val
39
+ when :referer
40
+ into[:http_headers]["Referer"] = val
41
+ when :header
42
+ key, value = *val.split(/:\s*/, 2)
43
+ into[:http_headers][key] = value
44
+ else
45
+ into[symbolized_name] = val
46
+ end
47
+ end
48
+ parse_in_order(argv, setter, &nonopt)
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Parser
4
+ class << self
5
+ def each_link(resource_stream, **)
6
+ document = Nokogiri::HTML(resource_stream.read) # TODO: to stream reading
7
+ document.css("a[href]").each do |element|
8
+ link = Lslinks::Link.from_nokogiri_element(element)
9
+ yield(link)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Reader::File
4
+ class << self
5
+ def open(resource_name, **, &block)
6
+ return File.open(resource_name, &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Reader::Http
4
+ class << self
5
+ DEFAULT_HTTP_HEADERS = {
6
+ "User-Agent" => "Ruby/#{RUBY_VERSION} lslinks/#{Lslinks::VERSION}",
7
+ }
8
+
9
+ def open(resource_name, **options, &block)
10
+ begin
11
+ uri = URI(resource_name)
12
+ rescue URI::InvalidURIError
13
+ raise Lslinks::Error::UnsupportedResource
14
+ end
15
+ raise Lslinks::Error::UnsupportedResource if !uri.is_a?(URI::HTTP)
16
+
17
+ http_headers = DEFAULT_HTTP_HEADERS.merge(options[:http_headers])
18
+ return uri.open(http_headers, &block)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Reader::Stdin
4
+ class << self
5
+ def open(resource_name, stdin: $stdin, **, &block)
6
+ raise Lslinks::Error::UnsupportedResource if "-" != resource_name
7
+
8
+ return block.(stdin)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ require "lslinks"
2
+
3
+ module Lslinks::Reader
4
+ class << self
5
+ def open(resource_name, **options, &block)
6
+ READER_CLASSES.each do |reader_class|
7
+ return reader_class.open(resource_name, **options, &block)
8
+ rescue Lslinks::Error::UnsupportedResource
9
+ # nop
10
+ end
11
+ end
12
+ end
13
+
14
+ require "lslinks/reader/file"
15
+ require "lslinks/reader/http"
16
+ require "lslinks/reader/stdin"
17
+ READER_CLASSES = [
18
+ Lslinks::Reader::Http,
19
+ Lslinks::Reader::Stdin,
20
+ Lslinks::Reader::File,
21
+ ]
22
+ end
data/lib/lslinks.rb ADDED
@@ -0,0 +1,22 @@
1
+ require "open-uri"
2
+ require "optparse"
3
+ require "pathname"
4
+ require "uri"
5
+
6
+ require "nokogiri"
7
+
8
+ module Lslinks
9
+ VERSION = "0.1.0"
10
+
11
+ class << self
12
+ def debug?
13
+ return "1" == ENV["LSLINKS_DEBUG"]
14
+ end
15
+ end
16
+ end
17
+
18
+ Pathname(__dir__).glob("**/*.rb").map { |path|
19
+ path.sub_ext("")
20
+ }.sort.each do |path|
21
+ require(path.relative_path_from(__dir__))
22
+ end
data/sig/lslinks.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Lslinks
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lslinks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yuya.Nishida.
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-11-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description:
28
+ email:
29
+ executables:
30
+ - lslinks
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE.txt
35
+ - README.md
36
+ - Rakefile
37
+ - exe/lslinks
38
+ - lib/lslinks.rb
39
+ - lib/lslinks/cli.rb
40
+ - lib/lslinks/error.rb
41
+ - lib/lslinks/error/unsupported_resource.rb
42
+ - lib/lslinks/formatter.rb
43
+ - lib/lslinks/link.rb
44
+ - lib/lslinks/option_parser.rb
45
+ - lib/lslinks/parser.rb
46
+ - lib/lslinks/reader.rb
47
+ - lib/lslinks/reader/file.rb
48
+ - lib/lslinks/reader/http.rb
49
+ - lib/lslinks/reader/stdin.rb
50
+ - sig/lslinks.rbs
51
+ homepage: https://github.com/nishidayuya/lslinks
52
+ licenses: []
53
+ metadata:
54
+ homepage_uri: https://github.com/nishidayuya/lslinks
55
+ source_code_uri: https://github.com/nishidayuya/lslinks
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 2.6.0
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.4.10
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: A command line tool to list links.
75
+ test_files: []