nbf_tools 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 023b1e16f83687108652237e0e32b8a7e1ad942c4d0fbedf06f9a3845353d809
4
+ data.tar.gz: 9c35361b95ea7e3e6857cac1fdd6288abb3579e4e1bb98f1f8eff84447735228
5
+ SHA512:
6
+ metadata.gz: 0f8bbe44b621662f646b2ec9befb410ec0b4e9f3e2826295688929ba80734ab11ec965c9566752ffdee4e75bd67472c7e7276d72c6a842f53eba19f8885e9eb3
7
+ data.tar.gz: ed8924a1e235f9ea288bf31b2f5def66637f4f603b1533e9f89dd31946bec52a649ce3efd34f25bd10e975a0cf9e1e0292a8f3038e83eb9e006b3b5f25204491
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
3
+ ruby_version: 2.6
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2022-12-17
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in nbf_tools.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "minitest", "~> 5.0"
11
+
12
+ gem "standard", "~> 1.3"
data/Gemfile.lock ADDED
@@ -0,0 +1,69 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nbf_tools (0.1.1)
5
+ nokogiri (~> 1.15)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.4.2)
11
+ base64 (0.1.1)
12
+ json (2.6.3)
13
+ language_server-protocol (3.17.0.3)
14
+ lint_roller (1.1.0)
15
+ minitest (5.20.0)
16
+ nokogiri (1.15.4-x86_64-darwin)
17
+ racc (~> 1.4)
18
+ parallel (1.23.0)
19
+ parser (3.2.2.3)
20
+ ast (~> 2.4.1)
21
+ racc
22
+ racc (1.7.1)
23
+ rainbow (3.1.1)
24
+ rake (13.0.6)
25
+ regexp_parser (2.8.1)
26
+ rexml (3.2.6)
27
+ rubocop (1.56.2)
28
+ base64 (~> 0.1.1)
29
+ json (~> 2.3)
30
+ language_server-protocol (>= 3.17.0)
31
+ parallel (~> 1.10)
32
+ parser (>= 3.2.2.3)
33
+ rainbow (>= 2.2.2, < 4.0)
34
+ regexp_parser (>= 1.8, < 3.0)
35
+ rexml (>= 3.2.5, < 4.0)
36
+ rubocop-ast (>= 1.28.1, < 2.0)
37
+ ruby-progressbar (~> 1.7)
38
+ unicode-display_width (>= 2.4.0, < 3.0)
39
+ rubocop-ast (1.29.0)
40
+ parser (>= 3.2.1.0)
41
+ rubocop-performance (1.19.0)
42
+ rubocop (>= 1.7.0, < 2.0)
43
+ rubocop-ast (>= 0.4.0)
44
+ ruby-progressbar (1.13.0)
45
+ standard (1.31.1)
46
+ language_server-protocol (~> 3.17.0.2)
47
+ lint_roller (~> 1.0)
48
+ rubocop (~> 1.56.2)
49
+ standard-custom (~> 1.0.0)
50
+ standard-performance (~> 1.2)
51
+ standard-custom (1.0.2)
52
+ lint_roller (~> 1.0)
53
+ rubocop (~> 1.50)
54
+ standard-performance (1.2.0)
55
+ lint_roller (~> 1.1)
56
+ rubocop-performance (~> 1.19.0)
57
+ unicode-display_width (2.4.2)
58
+
59
+ PLATFORMS
60
+ x86_64-darwin-21
61
+
62
+ DEPENDENCIES
63
+ minitest (~> 5.0)
64
+ nbf_tools!
65
+ rake (~> 13.0)
66
+ standard (~> 1.3)
67
+
68
+ BUNDLED WITH
69
+ 2.3.10
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # NbfTools
2
+
3
+ NETSCAPE Bookmark file tools.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add nbf_tools
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install nbf_tools
14
+
15
+ ## Usage
16
+
17
+ Parse NETSCAPE Bookmark file.
18
+
19
+ ```ruby
20
+ NbfTools.parse bookmark_file_path
21
+ ```
22
+
23
+ Merge and parse NETSCAPE Bookmark files.
24
+
25
+ ```ruby
26
+ NbfTools.parse_files_in_one bookmark_file_path1, bookmark_file_path2
27
+ ```
28
+
29
+ Export merge NETSCAPE Bookmark files to one html string.
30
+
31
+ ```ruby
32
+ NbfTools.parse_files_in_one_html bookmark_file_path1, bookmark_file_path2
33
+ ```
34
+
35
+
36
+ ## Development
37
+
38
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
39
+
40
+ 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).
41
+
42
+ ## Contributing
43
+
44
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Sapeu/nbf_tools.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/test_*.rb"]
10
+ end
11
+
12
+ require "standard/rake"
13
+
14
+ task default: %i[test standard]
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NbfTools
4
+ class Configuration
5
+ # personal toolbar folder text, default: ''
6
+ attr_accessor :personal_toolbar_folder_text
7
+ # link type text, default: 'link'
8
+ attr_accessor :link_type_text
9
+ # folder type text, default: 'folder'
10
+ attr_accessor :folder_type_text
11
+ end
12
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NbfTools
4
+ class HTML
5
+ CONTENT_FORMAT = "<!DOCTYPE NETSCAPE-Bookmark-file-1>\n<!-- This is an automatically generated file.\n It will be read and overwritten.\n DO NOT EDIT! -->\n<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">\n<TITLE>Bookmarks</TITLE>\n<H1>Bookmarks</H1>\n<DL><p>\n%{content}\n</DL><p>"
6
+ LINK_FORMAT = "%{indent}<DT><A %{attributes}>%{text}</A>"
7
+ FOLDER_FORMAT = "%{indent}<DT><H3 %{attributes}>%{text}</H3>\n%{indent}<DL><p>\n%{items}\n%{indent}</DL><p>"
8
+
9
+ def initialize(data)
10
+ @data = data
11
+ end
12
+
13
+ def to_s
14
+ sprintf(CONTENT_FORMAT, content: data_html)
15
+ end
16
+
17
+ def generate_attributes(element, *except_keys)
18
+ element.except(*except_keys).transform_keys(&:upcase).map { |k, v| "#{k}=\"#{v}\"" }.join(" ")
19
+ end
20
+
21
+ def data_html(data = @data)
22
+ return if data.nil?
23
+ data.map do |e|
24
+ case e["type"]
25
+ when NbfTools.config.link_type_text
26
+ link_html(e)
27
+ when NbfTools.config.folder_type_text
28
+ folder_html(e)
29
+ end
30
+ end.join("\n")
31
+ end
32
+
33
+ def link_html(item)
34
+ indent = "\t" * (item["path"].count("/") + 1)
35
+ attributes = generate_attributes(item, "path", "text", "type")
36
+ text = item["text"]
37
+ sprintf(LINK_FORMAT, indent: indent, attributes: attributes, text: text)
38
+ end
39
+
40
+ def folder_html(folder)
41
+ indent = "\t" * folder["path"].count("/")
42
+ attributes = generate_attributes(folder, "path", "text", "type", "items")
43
+ text = folder["text"]
44
+ items = data_html(folder["items"])
45
+ sprintf(FOLDER_FORMAT, indent: indent, attributes: attributes, text: text, items: items)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NbfTools
4
+ class Merge
5
+ def initialize(data)
6
+ @data = data
7
+ @link_map = {}
8
+ @folder_map = {}
9
+ end
10
+
11
+ def to_a
12
+ @data.each do |file_data|
13
+ flat_folder_and_link_map(file_data, @link_map, @folder_map)
14
+ end
15
+
16
+ @link_map.values.each do |e|
17
+ folder = @folder_map[e["path"]]
18
+ next if folder.nil?
19
+ folder["items"] ||= []
20
+ folder["items"] << e
21
+ @folder_map[e["path"]] = folder
22
+ end
23
+
24
+ @folder_map.values.each do |e|
25
+ parent_path = e["path"].split("/")[0..-2].join("/")
26
+ folder = @folder_map[parent_path]
27
+ next if folder.nil?
28
+ folder["items"] ||= []
29
+ folder["items"] << e
30
+ @folder_map[parent_path] = folder
31
+ end
32
+ @folder_map.values.select { |e| e["path"].count("/") < 2 } + @link_map.values.select { |e| e["path"] == "/" }
33
+ end
34
+
35
+ def flat_folder_and_link_map(data, link_map, folder_map)
36
+ data.map do |e|
37
+ case e["type"]
38
+ when NbfTools.config.link_type_text
39
+ choose_latest_element(link_map, "href", e)
40
+ when NbfTools.config.folder_type_text
41
+ choose_latest_element(folder_map, "path", e)
42
+ flat_folder_and_link_map(e["items"], link_map, folder_map)
43
+ end
44
+ end
45
+ end
46
+
47
+ def choose_latest_element(data_map, key, new_element)
48
+ if data_map.key?(new_element[key])
49
+ old_e = data_map[new_element[key]]
50
+ if [new_element["add_date"].to_i, new_element["last_modified"].to_i].max > [old_e["add_date"].to_i, old_e["last_modified"].to_i].max
51
+ data_map[new_element[key]] = new_element.except("items")
52
+ end
53
+ else
54
+ data_map[new_element[key]] = new_element.except("items")
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "nokogiri"
4
+ module NbfTools
5
+ class Parse
6
+ def initialize file
7
+ @document = Nokogiri::HTML(File.open(file))
8
+ end
9
+
10
+ def parse
11
+ parse_node_children(@document.xpath("/html/body/dl").first, Pathname.new("/"))
12
+ end
13
+
14
+ def parse_node_children(node, path)
15
+ node.children.each_with_object([]) do |c, items|
16
+ case c.node_name
17
+ when "dt"
18
+ items.push(*parse_node_children(c, path))
19
+ when "a"
20
+ bookmark = c.to_h.merge("text" => c.text, "type" => NbfTools.config.link_type_text, "path" => path.to_s)
21
+ items.push bookmark
22
+ when "h3"
23
+ folder_name = c.text
24
+ folder_name = NbfTools.config.personal_toolbar_folder_text if c["personal_toolbar_folder"] == "true"
25
+ folder = c.to_h.merge("text" => folder_name, "type" => NbfTools.config.folder_type_text, "path" => (path + folder_name).to_s, "items" => [])
26
+ items.push folder
27
+ when "dl"
28
+ folder = items.select { |e| e["type"] == "folder" }.last
29
+ folder.nil? ? items.push(*parse_node_children(c), path) : folder["items"] = parse_node_children(c, path + folder["text"])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NbfTools
4
+ VERSION = "0.1.1"
5
+ end
data/lib/nbf_tools.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "nbf_tools/configuration"
4
+ require_relative "nbf_tools/html"
5
+ require_relative "nbf_tools/merge"
6
+ require_relative "nbf_tools/parse"
7
+ require_relative "nbf_tools/version"
8
+
9
+ module NbfTools
10
+ class Error < StandardError; end
11
+ # Your code goes here...
12
+
13
+ class << self
14
+ def config
15
+ return @config if defined?(@config)
16
+
17
+ @config = Configuration.new
18
+ @config.personal_toolbar_folder_text = "personal toolbar"
19
+ @config.link_type_text = "link"
20
+ @config.folder_type_text = "folder"
21
+
22
+ @config
23
+ end
24
+
25
+ def configure(&block)
26
+ config.instance_exec(&block)
27
+ end
28
+
29
+ def parse(file)
30
+ Parse.new(file).parse
31
+ end
32
+
33
+ def parse_files_in_one(*files)
34
+ data = files.map { |file| parse(file) }
35
+ return data[0] if files.size < 2
36
+ Merge.new(data).to_a
37
+ end
38
+
39
+ def parse_files_in_one_html(*files)
40
+ return File.read(files[0]) if files.size < 2
41
+ data = parse_files_in_one(*files)
42
+ HTML.new(data).to_s
43
+ end
44
+ end
45
+ end
data/nbf_tools.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/nbf_tools/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "nbf_tools"
7
+ spec.version = NbfTools::VERSION
8
+ spec.authors = ["Sapeu"]
9
+ spec.email = ["sapeu.lee@foxmail.com"]
10
+
11
+ spec.summary = "NETSCAPE Bookmark file tools."
12
+ spec.description = "NETSCAPE Bookmark file tools."
13
+ spec.homepage = "https://github.com/sapeu/nbf_tools"
14
+ spec.required_ruby_version = ">= 2.7.0"
15
+
16
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/sapeu/nbf_tools"
20
+ spec.metadata["changelog_uri"] = "https://github.com/sapeu/nbf_tools/blob/main/CHANGELOG.md"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
27
+ end
28
+ end
29
+ spec.bindir = "exe"
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ["lib"]
32
+
33
+ # Uncomment to register a new dependency of your gem
34
+ spec.add_dependency "nokogiri", "~> 1.15"
35
+ spec.add_development_dependency "standard", "~> 1.31"
36
+
37
+ # For more information and examples about making a new gem, check out our
38
+ # guide at: https://bundler.io/guides/creating_gem.html
39
+ end
data/sig/nbf_tools.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module NbfTools
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nbf_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Sapeu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-10-06 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: '1.15'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: standard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.31'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.31'
41
+ description: NETSCAPE Bookmark file tools.
42
+ email:
43
+ - sapeu.lee@foxmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".standard.yml"
49
+ - CHANGELOG.md
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - README.md
53
+ - Rakefile
54
+ - lib/nbf_tools.rb
55
+ - lib/nbf_tools/configuration.rb
56
+ - lib/nbf_tools/html.rb
57
+ - lib/nbf_tools/merge.rb
58
+ - lib/nbf_tools/parse.rb
59
+ - lib/nbf_tools/version.rb
60
+ - nbf_tools.gemspec
61
+ - sig/nbf_tools.rbs
62
+ homepage: https://github.com/sapeu/nbf_tools
63
+ licenses: []
64
+ metadata:
65
+ homepage_uri: https://github.com/sapeu/nbf_tools
66
+ source_code_uri: https://github.com/sapeu/nbf_tools
67
+ changelog_uri: https://github.com/sapeu/nbf_tools/blob/main/CHANGELOG.md
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.7.0
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.4.10
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: NETSCAPE Bookmark file tools.
87
+ test_files: []