site_maps 0.0.1.beta1
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 +7 -0
- data/.github/workflows/main.yml +45 -0
- data/.gitignore +16 -0
- data/.rspec +1 -0
- data/.rubocop.yml +36 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +134 -0
- data/LICENSE.txt +21 -0
- data/README.md +186 -0
- data/Rakefile +4 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exec/site_maps +9 -0
- data/lib/site-maps.rb +3 -0
- data/lib/site_maps/adapters/adapter.rb +80 -0
- data/lib/site_maps/adapters/aws_sdk/config.rb +51 -0
- data/lib/site_maps/adapters/aws_sdk/location.rb +9 -0
- data/lib/site_maps/adapters/aws_sdk/storage.rb +52 -0
- data/lib/site_maps/adapters/aws_sdk.rb +31 -0
- data/lib/site_maps/adapters/file_system/config.rb +5 -0
- data/lib/site_maps/adapters/file_system/location.rb +35 -0
- data/lib/site_maps/adapters/file_system/storage.rb +61 -0
- data/lib/site_maps/adapters/file_system.rb +26 -0
- data/lib/site_maps/adapters/noop.rb +18 -0
- data/lib/site_maps/atomic_repository.rb +24 -0
- data/lib/site_maps/builder/link.rb +27 -0
- data/lib/site_maps/builder/normalizer.rb +48 -0
- data/lib/site_maps/builder/sitemap_index/item.rb +35 -0
- data/lib/site_maps/builder/sitemap_index.rb +40 -0
- data/lib/site_maps/builder/url.rb +152 -0
- data/lib/site_maps/builder/url_set.rb +92 -0
- data/lib/site_maps/cli.rb +68 -0
- data/lib/site_maps/configuration.rb +119 -0
- data/lib/site_maps/incremental_location.rb +62 -0
- data/lib/site_maps/notification/bus.rb +90 -0
- data/lib/site_maps/notification/event.rb +50 -0
- data/lib/site_maps/notification/publisher.rb +78 -0
- data/lib/site_maps/notification.rb +36 -0
- data/lib/site_maps/primitives/array.rb +15 -0
- data/lib/site_maps/primitives/output.rb +66 -0
- data/lib/site_maps/primitives/string.rb +43 -0
- data/lib/site_maps/process.rb +29 -0
- data/lib/site_maps/railtie.rb +18 -0
- data/lib/site_maps/runner/event_listener.rb +78 -0
- data/lib/site_maps/runner.rb +136 -0
- data/lib/site_maps/sitemap_builder.rb +75 -0
- data/lib/site_maps/sitemap_reader.rb +56 -0
- data/lib/site_maps/version.rb +5 -0
- data/lib/site_maps.rb +112 -0
- data/site_maps.gemspec +44 -0
- metadata +172 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SiteMaps
|
4
|
+
module Runner::EventListener
|
5
|
+
extend Primitives::Output
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def [](event_name)
|
10
|
+
method_name = Primitives::String.new(event_name).underscore.to_sym
|
11
|
+
return unless respond_to?(:"on_#{method_name}")
|
12
|
+
|
13
|
+
method(:"on_#{method_name}")
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_sitemaps_runner_enqueue_process(event)
|
17
|
+
process = event[:process]
|
18
|
+
kwargs = event[:kwargs]
|
19
|
+
location = process.location(**kwargs)
|
20
|
+
print_message(
|
21
|
+
"Enqueue process %<name>s#{" at %<location>s" if location}",
|
22
|
+
name: colorize(process.name, :bold),
|
23
|
+
location: colorize(location, :lightgray)
|
24
|
+
)
|
25
|
+
if kwargs.any?
|
26
|
+
print_message("└── Keyword Arguments: {%<kwargs>s}", kwargs: kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", "))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_sitemaps_runner_before_process_execution(event)
|
31
|
+
process = event[:process]
|
32
|
+
kwargs = event[:kwargs]
|
33
|
+
location = process.location(**kwargs)
|
34
|
+
print_message(
|
35
|
+
"Executing process %<name>s#{" at %<location>s" if location}",
|
36
|
+
name: colorize(process.name, :bold),
|
37
|
+
location: colorize(location, :lightgray)
|
38
|
+
)
|
39
|
+
if kwargs.any?
|
40
|
+
print_message("└── Keyword Arguments: {%<kwargs>s}", kwargs: kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", "))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_sitemaps_runner_process_execution(event)
|
45
|
+
process = event[:process]
|
46
|
+
kwargs = event[:kwargs]
|
47
|
+
location = process.location(**kwargs)
|
48
|
+
print_message(
|
49
|
+
"[%<runtime>s] Executed process %<name>s#{" at %<location>s" if location}",
|
50
|
+
name: colorize(process.name, :bold),
|
51
|
+
location: colorize(location, :lightgray),
|
52
|
+
runtime: formatted_runtime(event[:runtime])
|
53
|
+
)
|
54
|
+
if kwargs.any?
|
55
|
+
print_message("└── Keyword Arguments: {%<kwargs>s}", kwargs: kwargs.map { |k, v| "#{k}: #{v.inspect}" }.join(", "))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def on_sitemaps_builder_finalize_urlset(event)
|
60
|
+
links_count = event[:links_count]
|
61
|
+
news_count = event[:news_count]
|
62
|
+
url = event[:url]
|
63
|
+
text = +"[%<runtime>s] Finalize URLSet with "
|
64
|
+
text << "%<links>d links" if links_count > 0
|
65
|
+
text << " and " if links_count > 0 && news_count > 0
|
66
|
+
text << "%<news>d news" if news_count > 0
|
67
|
+
text << " URLs at %<url>s"
|
68
|
+
|
69
|
+
print_message(
|
70
|
+
text,
|
71
|
+
links: links_count,
|
72
|
+
news: news_count,
|
73
|
+
url: colorize(url, :lightgray),
|
74
|
+
runtime: formatted_runtime(event[:runtime])
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SiteMaps
|
4
|
+
class Runner
|
5
|
+
attr_reader :adapter
|
6
|
+
|
7
|
+
def initialize(adapter = SiteMaps.current_adapter, max_threads: 4)
|
8
|
+
@adapter = adapter.tap(&:reset!)
|
9
|
+
@pool = Concurrent::FixedThreadPool.new(max_threads)
|
10
|
+
@execution = Concurrent::Hash.new
|
11
|
+
@failed = Concurrent::AtomicBoolean.new(false)
|
12
|
+
@errors = Concurrent::Array.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def enqueue(process_name = :default, **kwargs)
|
16
|
+
process_name = process_name.to_sym
|
17
|
+
process = @adapter.processes.fetch(process_name) do
|
18
|
+
raise ArgumentError, "Process :#{process_name} not found"
|
19
|
+
end
|
20
|
+
kwargs = process.keyword_arguments(kwargs)
|
21
|
+
SiteMaps::Notification.instrument("sitemaps.runner.enqueue_process") do |payload|
|
22
|
+
payload[:process] = process
|
23
|
+
payload[:kwargs] = kwargs
|
24
|
+
if process.dynamic?
|
25
|
+
@execution[process_name] ||= Concurrent::Array.new
|
26
|
+
if @execution[process_name].any? { |_, k| k == kwargs }
|
27
|
+
raise ArgumentError, "Process :#{process_name} already enqueued with kwargs #{kwargs}"
|
28
|
+
end
|
29
|
+
@execution[process_name] << [process, kwargs]
|
30
|
+
else
|
31
|
+
if @execution.key?(process_name)
|
32
|
+
raise ArgumentError, "Process :#{process_name} already defined"
|
33
|
+
end
|
34
|
+
@execution[process_name] = Concurrent::Array.new([[process, kwargs]])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def enqueue_remaining
|
41
|
+
@adapter.processes.each_key do |process_name|
|
42
|
+
next if @execution.key?(process_name)
|
43
|
+
|
44
|
+
enqueue(process_name)
|
45
|
+
end
|
46
|
+
self
|
47
|
+
end
|
48
|
+
alias_method :enqueue_all, :enqueue_remaining
|
49
|
+
|
50
|
+
def run
|
51
|
+
may_preload_sitemap_index
|
52
|
+
|
53
|
+
futures = []
|
54
|
+
@execution.each do |_process_name, items|
|
55
|
+
items.each do |process, kwargs|
|
56
|
+
SiteMaps::Notification.publish("sitemaps.runner.before_process_execution", process: process, kwargs: kwargs)
|
57
|
+
futures << Concurrent::Future.execute(executor: pool) do
|
58
|
+
wrap_process_execution(process) do
|
59
|
+
SiteMaps::Notification.instrument("sitemaps.runner.process_execution") do |payload|
|
60
|
+
payload[:process] = process
|
61
|
+
payload[:kwargs] = kwargs
|
62
|
+
builder = SiteMaps::SitemapBuilder.new(
|
63
|
+
adapter: adapter,
|
64
|
+
location: process.location(**kwargs)
|
65
|
+
)
|
66
|
+
process.call(builder, **kwargs)
|
67
|
+
builder.finalize!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
futures.each(&:wait)
|
75
|
+
failed.false? ? finalize! : fail_with_errors!
|
76
|
+
ensure
|
77
|
+
pool.shutdown
|
78
|
+
pool.wait_for_termination
|
79
|
+
@execution.clear
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
attr_reader :pool, :failed, :errors
|
85
|
+
|
86
|
+
def finalize!
|
87
|
+
adapter.repo.remaining_index_links.each do |item|
|
88
|
+
adapter.sitemap_index.add(item)
|
89
|
+
end
|
90
|
+
unless adapter.sitemap_index.empty?
|
91
|
+
raw_data = adapter.sitemap_index.to_xml
|
92
|
+
adapter.write(adapter.config.url, raw_data, last_modified: Time.now)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def fail_with_errors!
|
97
|
+
return if errors.empty?
|
98
|
+
|
99
|
+
raise errors.first.last
|
100
|
+
end
|
101
|
+
|
102
|
+
def handle_process_error(process, error)
|
103
|
+
errors << [process, error]
|
104
|
+
end
|
105
|
+
|
106
|
+
def may_preload_sitemap_index
|
107
|
+
return unless preload_sitemap_index_links?
|
108
|
+
|
109
|
+
adapter.fetch_sitemap_index_links.each do |item|
|
110
|
+
adapter.repo.preloaded_index_links.push(item)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def wrap_process_execution(process)
|
115
|
+
return if failed.true?
|
116
|
+
|
117
|
+
yield
|
118
|
+
rescue => e
|
119
|
+
handle_process_error(process, e)
|
120
|
+
failed.make_true
|
121
|
+
end
|
122
|
+
|
123
|
+
def preload_sitemap_index_links?
|
124
|
+
return false if @execution.empty?
|
125
|
+
|
126
|
+
(@adapter.processes.keys - @execution.keys).any? || # There are processes that have not been enqueued
|
127
|
+
@adapter.processes.any? { |_, process| process.dynamic? } # There are dynamic processes
|
128
|
+
end
|
129
|
+
|
130
|
+
# def single_thread?
|
131
|
+
# @pool.max_length == 1 || (
|
132
|
+
# @execution.size == 1 && @execution.first.last.size == 1
|
133
|
+
# )
|
134
|
+
# end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SiteMaps
|
4
|
+
class SitemapBuilder
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize(adapter:, location: nil)
|
8
|
+
@adapter = adapter
|
9
|
+
@url_set = SiteMaps::Builder::URLSet.new
|
10
|
+
@location = location
|
11
|
+
@mutex = Mutex.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(path, params: nil, **options)
|
15
|
+
@mutex.synchronize do
|
16
|
+
link = build_link(path, params)
|
17
|
+
url_set.add(link, **options)
|
18
|
+
rescue SiteMaps::FullSitemapError
|
19
|
+
finalize_and_start_next_urlset!
|
20
|
+
url_set.add(link, **options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_sitemap_index(url, lastmod: Time.now)
|
25
|
+
sitemap_index.add(url, lastmod: lastmod)
|
26
|
+
end
|
27
|
+
|
28
|
+
def finalize!
|
29
|
+
return if url_set.finalized?
|
30
|
+
return if url_set.empty?
|
31
|
+
|
32
|
+
raw_data = url_set.finalize!
|
33
|
+
|
34
|
+
SiteMaps::Notification.instrument("sitemaps.builder.finalize_urlset") do |payload|
|
35
|
+
payload[:links_count] = url_set.links_count
|
36
|
+
payload[:news_count] = url_set.news_count
|
37
|
+
payload[:last_modified] = url_set.last_modified
|
38
|
+
|
39
|
+
if adapter.maybe_inline_urlset? && sitemap_index.empty?
|
40
|
+
payload[:url] = repo.main_url
|
41
|
+
adapter.write(repo.main_url, raw_data, last_modified: url_set.last_modified)
|
42
|
+
else
|
43
|
+
sitemap_url = repo.generate_url(location)
|
44
|
+
payload[:url] = sitemap_url
|
45
|
+
adapter.write(sitemap_url, raw_data, last_modified: url_set.last_modified)
|
46
|
+
add_sitemap_index(sitemap_url, lastmod: url_set.last_modified)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
attr_reader :url_set, :adapter, :location
|
54
|
+
|
55
|
+
def_delegators :adapter, :sitemap_index, :config, :repo
|
56
|
+
|
57
|
+
def finalize_and_start_next_urlset!
|
58
|
+
raw_data = url_set.finalize!
|
59
|
+
SiteMaps::Notification.instrument("sitemaps.builder.finalize_urlset") do |payload|
|
60
|
+
sitemap_url = repo.generate_url(location)
|
61
|
+
payload[:url] = sitemap_url
|
62
|
+
payload[:links_count] = url_set.links_count
|
63
|
+
payload[:news_count] = url_set.news_count
|
64
|
+
payload[:last_modified] = url_set.last_modified
|
65
|
+
adapter.write(sitemap_url, raw_data, last_modified: url_set.last_modified)
|
66
|
+
add_sitemap_index(sitemap_url, lastmod: url_set.last_modified)
|
67
|
+
end
|
68
|
+
@url_set = SiteMaps::Builder::URLSet.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def build_link(path, params)
|
72
|
+
SiteMaps::Builder::Link.new(config.base_uri, path, params)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
|
5
|
+
module SiteMaps
|
6
|
+
class SitemapReader
|
7
|
+
Error = Class.new(SiteMaps::Error)
|
8
|
+
FileNotFound = Class.new(Error)
|
9
|
+
MalformedFile = Class.new(Error)
|
10
|
+
|
11
|
+
def initialize(location)
|
12
|
+
@location = Pathname.new(location)
|
13
|
+
end
|
14
|
+
|
15
|
+
def read
|
16
|
+
if compressed?
|
17
|
+
Zlib::GzipReader.new(read_file).read
|
18
|
+
else
|
19
|
+
read_file.read
|
20
|
+
end
|
21
|
+
rescue Zlib::GzipFile::Error => _e
|
22
|
+
raise MalformedFile.new("The file #{@location} is not a valid Gzip file")
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_doc
|
26
|
+
@doc ||= begin
|
27
|
+
require "nokogiri"
|
28
|
+
Nokogiri::XML(read)
|
29
|
+
end
|
30
|
+
rescue LoadError
|
31
|
+
raise SiteMaps::Error, "Nokogiri is required to parse the XML file"
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def read_file
|
37
|
+
if remote?
|
38
|
+
::URI.parse(@location.to_s).open
|
39
|
+
else
|
40
|
+
::File.open(@location, "r")
|
41
|
+
end
|
42
|
+
rescue Errno::ENOENT
|
43
|
+
raise FileNotFound.new("The file #{@location} does not exist")
|
44
|
+
rescue OpenURI::HTTPError
|
45
|
+
raise FileNotFound.new("The file #{@location} could not be opened")
|
46
|
+
end
|
47
|
+
|
48
|
+
def compressed?
|
49
|
+
@location.extname == ".gz"
|
50
|
+
end
|
51
|
+
|
52
|
+
def remote?
|
53
|
+
%r{^https?://}.match?(@location.to_s)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/site_maps.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "site_maps/version"
|
4
|
+
|
5
|
+
require "builder"
|
6
|
+
require "concurrent-ruby"
|
7
|
+
require "date"
|
8
|
+
require "fileutils"
|
9
|
+
require "forwardable"
|
10
|
+
require "rack/utils"
|
11
|
+
require "stringio"
|
12
|
+
require "time"
|
13
|
+
require "uri"
|
14
|
+
require "zeitwerk"
|
15
|
+
require "zlib"
|
16
|
+
|
17
|
+
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
18
|
+
loader.ignore("#{__dir__}/site-maps.rb")
|
19
|
+
loader.ignore("#{__dir__}/site_maps/tasks.rb")
|
20
|
+
loader.ignore("#{__dir__}/site_maps/cli.rb")
|
21
|
+
loader.inflector.inflect "cli" => "CLI"
|
22
|
+
loader.inflector.inflect "dsl" => "DSL"
|
23
|
+
loader.inflector.inflect "url_set" => "URLSet"
|
24
|
+
loader.inflector.inflect "url" => "URL"
|
25
|
+
loader.inflector.inflect "xml" => "XML"
|
26
|
+
loader.log! if ENV["DEBUG_ZEITWERK"]
|
27
|
+
loader.setup
|
28
|
+
|
29
|
+
module SiteMaps
|
30
|
+
MAX_LENGTH = {
|
31
|
+
links: 50_000,
|
32
|
+
images: 1_000,
|
33
|
+
news: 1_000
|
34
|
+
}
|
35
|
+
MAX_FILESIZE = 50_000_000 # bytes
|
36
|
+
DEFAULT_LOGGER = Logger.new($stdout)
|
37
|
+
|
38
|
+
Error = Class.new(StandardError)
|
39
|
+
AdapterNotFound = Class.new(Error)
|
40
|
+
AdapterNotSetError = Class.new(Error)
|
41
|
+
FileNotFoundError = Class.new(Error)
|
42
|
+
FullSitemapError = Class.new(Error)
|
43
|
+
ConfigurationError = Class.new(Error)
|
44
|
+
|
45
|
+
class << self
|
46
|
+
attr_reader :current_adapter
|
47
|
+
attr_writer :logger
|
48
|
+
|
49
|
+
# @param adapter [Class, String, Symbol] The name of the adapter to use
|
50
|
+
# @param options [Hash] Options to pass to the adapter. Note that these are adapter-specific
|
51
|
+
# @param block [Proc] A block to pass to the adapter
|
52
|
+
# @return [Object] An instance of the adapter
|
53
|
+
def use(adapter, **options, &block)
|
54
|
+
adapter_class = if adapter.is_a?(Class) # && adapter < Adapters::Adapter
|
55
|
+
adapter
|
56
|
+
else
|
57
|
+
const_name = Primitives::String.new(adapter.to_s).classify
|
58
|
+
begin
|
59
|
+
Adapters.const_get(const_name)
|
60
|
+
rescue NameError
|
61
|
+
raise AdapterNotFound, "Adapter #{adapter.inspect} not found"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@current_adapter = adapter_class.new(**options, &block)
|
65
|
+
end
|
66
|
+
|
67
|
+
def config
|
68
|
+
@config ||= Configuration.new
|
69
|
+
yield(@config) if block_given?
|
70
|
+
@config
|
71
|
+
end
|
72
|
+
alias_method :configure, :config
|
73
|
+
|
74
|
+
# Load and prepare a runner with the current adapter
|
75
|
+
# Note that it won't start running until you call `#run` on the runner
|
76
|
+
#
|
77
|
+
# Example:
|
78
|
+
# SiteMaps.generate(config_file: "config/site_maps.rb", max_threads: 10)
|
79
|
+
# .enqueue_all
|
80
|
+
# .run
|
81
|
+
#
|
82
|
+
# You may also enqueue processes manually, specially those that are dynamic
|
83
|
+
#
|
84
|
+
# Example:
|
85
|
+
# SiteMaps.generate(config_file: "config/site_maps.rb", max_threads: 10)
|
86
|
+
# .enqueue(:monthly, year: 2020, month: 1)
|
87
|
+
# .enqueue(:monthly, year: 2020, month: 2)
|
88
|
+
# .enqueue_remaining # Enqueue all other non-enqueued processes
|
89
|
+
# .run
|
90
|
+
#
|
91
|
+
# @param config_file [String] The path to a configuration file
|
92
|
+
# @param options [Hash] Options to pass to the runner
|
93
|
+
# @return [Runner] An instance of the runner
|
94
|
+
def generate(config_file: nil, **options)
|
95
|
+
if config_file
|
96
|
+
@current_adapter = nil
|
97
|
+
load(config_file)
|
98
|
+
end
|
99
|
+
raise AdapterNotSetError, "No adapter set. Use SiteMaps.use to set an adapter" unless current_adapter
|
100
|
+
|
101
|
+
Runner.new(current_adapter, **options)
|
102
|
+
end
|
103
|
+
|
104
|
+
def logger
|
105
|
+
@logger ||= DEFAULT_LOGGER
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if defined?(::Rails)
|
111
|
+
require_relative "site_maps/railtie"
|
112
|
+
end
|
data/site_maps.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/site_maps/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "site_maps"
|
7
|
+
spec.version = SiteMaps::VERSION
|
8
|
+
spec.authors = ["Marcos G. Zimmermann"]
|
9
|
+
spec.email = ["mgzmaster@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = <<~SUMMARY
|
12
|
+
SiteMaps simplifies the generation of sitemaps for ruby or rails applications.
|
13
|
+
SUMMARY
|
14
|
+
spec.description = <<~DESCRIPTION
|
15
|
+
SiteMaps is gem that provides a simple way to generate static sitemaps for your ruby or rails applications.
|
16
|
+
DESCRIPTION
|
17
|
+
|
18
|
+
spec.homepage = "https://github.com/marcosgz/site_maps"
|
19
|
+
spec.license = "MIT"
|
20
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
21
|
+
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes." unless spec.respond_to?(:metadata)
|
23
|
+
|
24
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
25
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/marcosgz/site_maps/issues"
|
26
|
+
spec.metadata["documentation_uri"] = "https://github.com/marcosgz/site_maps"
|
27
|
+
spec.metadata["source_code_uri"] = "https://github.com/marcosgz/site_maps"
|
28
|
+
|
29
|
+
# Specify which files should be added to the gem when it is released.
|
30
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
32
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
|
+
end
|
34
|
+
|
35
|
+
spec.bindir = "exec"
|
36
|
+
spec.executables = spec.files.grep(%r{^exec/}) { |f| File.basename(f) }
|
37
|
+
spec.require_paths = ["lib"]
|
38
|
+
|
39
|
+
spec.add_dependency "rack", ">= 2.0"
|
40
|
+
spec.add_dependency "zeitwerk", ">= 0"
|
41
|
+
spec.add_dependency "builder", "~> 3.0"
|
42
|
+
spec.add_dependency "concurrent-ruby", ">= 1.1"
|
43
|
+
spec.add_dependency "thor", ">= 0.0.0"
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: site_maps
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Marcos G. Zimmermann
|
8
|
+
autorequire:
|
9
|
+
bindir: exec
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: zeitwerk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: builder
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: concurrent-ruby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.1'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: thor
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.0.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.0.0
|
83
|
+
description: 'SiteMaps is gem that provides a simple way to generate static sitemaps
|
84
|
+
for your ruby or rails applications.
|
85
|
+
|
86
|
+
'
|
87
|
+
email:
|
88
|
+
- mgzmaster@gmail.com
|
89
|
+
executables:
|
90
|
+
- site_maps
|
91
|
+
extensions: []
|
92
|
+
extra_rdoc_files: []
|
93
|
+
files:
|
94
|
+
- ".github/workflows/main.yml"
|
95
|
+
- ".gitignore"
|
96
|
+
- ".rspec"
|
97
|
+
- ".rubocop.yml"
|
98
|
+
- ".tool-versions"
|
99
|
+
- CHANGELOG.md
|
100
|
+
- Gemfile
|
101
|
+
- Gemfile.lock
|
102
|
+
- LICENSE.txt
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- bin/console
|
106
|
+
- bin/setup
|
107
|
+
- exec/site_maps
|
108
|
+
- lib/site-maps.rb
|
109
|
+
- lib/site_maps.rb
|
110
|
+
- lib/site_maps/adapters/adapter.rb
|
111
|
+
- lib/site_maps/adapters/aws_sdk.rb
|
112
|
+
- lib/site_maps/adapters/aws_sdk/config.rb
|
113
|
+
- lib/site_maps/adapters/aws_sdk/location.rb
|
114
|
+
- lib/site_maps/adapters/aws_sdk/storage.rb
|
115
|
+
- lib/site_maps/adapters/file_system.rb
|
116
|
+
- lib/site_maps/adapters/file_system/config.rb
|
117
|
+
- lib/site_maps/adapters/file_system/location.rb
|
118
|
+
- lib/site_maps/adapters/file_system/storage.rb
|
119
|
+
- lib/site_maps/adapters/noop.rb
|
120
|
+
- lib/site_maps/atomic_repository.rb
|
121
|
+
- lib/site_maps/builder/link.rb
|
122
|
+
- lib/site_maps/builder/normalizer.rb
|
123
|
+
- lib/site_maps/builder/sitemap_index.rb
|
124
|
+
- lib/site_maps/builder/sitemap_index/item.rb
|
125
|
+
- lib/site_maps/builder/url.rb
|
126
|
+
- lib/site_maps/builder/url_set.rb
|
127
|
+
- lib/site_maps/cli.rb
|
128
|
+
- lib/site_maps/configuration.rb
|
129
|
+
- lib/site_maps/incremental_location.rb
|
130
|
+
- lib/site_maps/notification.rb
|
131
|
+
- lib/site_maps/notification/bus.rb
|
132
|
+
- lib/site_maps/notification/event.rb
|
133
|
+
- lib/site_maps/notification/publisher.rb
|
134
|
+
- lib/site_maps/primitives/array.rb
|
135
|
+
- lib/site_maps/primitives/output.rb
|
136
|
+
- lib/site_maps/primitives/string.rb
|
137
|
+
- lib/site_maps/process.rb
|
138
|
+
- lib/site_maps/railtie.rb
|
139
|
+
- lib/site_maps/runner.rb
|
140
|
+
- lib/site_maps/runner/event_listener.rb
|
141
|
+
- lib/site_maps/sitemap_builder.rb
|
142
|
+
- lib/site_maps/sitemap_reader.rb
|
143
|
+
- lib/site_maps/version.rb
|
144
|
+
- site_maps.gemspec
|
145
|
+
homepage: https://github.com/marcosgz/site_maps
|
146
|
+
licenses:
|
147
|
+
- MIT
|
148
|
+
metadata:
|
149
|
+
homepage_uri: https://github.com/marcosgz/site_maps
|
150
|
+
bug_tracker_uri: https://github.com/marcosgz/site_maps/issues
|
151
|
+
documentation_uri: https://github.com/marcosgz/site_maps
|
152
|
+
source_code_uri: https://github.com/marcosgz/site_maps
|
153
|
+
post_install_message:
|
154
|
+
rdoc_options: []
|
155
|
+
require_paths:
|
156
|
+
- lib
|
157
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 2.7.0
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
requirements: []
|
168
|
+
rubygems_version: 3.5.21
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: SiteMaps simplifies the generation of sitemaps for ruby or rails applications.
|
172
|
+
test_files: []
|