perron 1.1.0 → 1.2.0
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/Gemfile.lock +1 -1
- data/lib/perron/configuration.rb +6 -2
- data/lib/perron/deprecator.rb +1 -1
- data/lib/perron/feeds/split.rb +46 -0
- data/lib/perron/feeds.rb +17 -0
- data/lib/perron/html_processor/absolute_urls.rb +1 -1
- data/lib/perron/install/{deploy.yml → deploy.yml.erb} +4 -5
- data/lib/perron/install.rb +0 -3
- data/lib/perron/relation.rb +4 -2
- data/lib/perron/resource/configuration.rb +13 -3
- data/lib/perron/resource/metadata.rb +2 -1
- data/lib/perron/resource/publishable.rb +9 -1
- data/lib/perron/resource/separator.rb +11 -5
- data/lib/perron/resource/sourceable.rb +3 -1
- data/lib/perron/resource/updatable.rb +46 -0
- data/lib/perron/resource.rb +1 -0
- data/lib/perron/site/builder/feeds/atom.rb +8 -2
- data/lib/perron/site/builder/feeds/json.rb +8 -2
- data/lib/perron/site/builder/feeds/rss.rb +8 -2
- data/lib/perron/site/builder/feeds.rb +32 -10
- data/lib/perron/site/builder/paths.rb +4 -0
- data/lib/perron/site/builder/sitemap.rb +23 -10
- data/lib/perron/tasks/deploy.rake +19 -8
- data/lib/perron/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84ad5823f9409ec7734c3fef06a9d57602e5da59c14e939d2e4acb8f3f2b4e22
|
|
4
|
+
data.tar.gz: 9e8e47f8706704ec8d8d6efb66ccbb6eb87f815570166f0bd188ce0e6f085b9a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 766753cd5c6e74d3353ad603015e316f7158a1a79c28ed8b0fbcbd8d9a7c8c0a1a4cb88e372fbe741548a83e0d0a042da44df8c8545cc6973eb768283177dae8
|
|
7
|
+
data.tar.gz: 605182a711103ad0e0ca07c330290ee2ab1574fcfda9596e042ea7365a4f329485a407692ce4c5e94d5c720e1100bb1c79ef4300ccb04eb4119f989af895e2a5
|
data/Gemfile.lock
CHANGED
data/lib/perron/configuration.rb
CHANGED
|
@@ -15,8 +15,6 @@ module Perron
|
|
|
15
15
|
|
|
16
16
|
@config.output = "output"
|
|
17
17
|
|
|
18
|
-
@config.output_server_strict = true
|
|
19
|
-
|
|
20
18
|
@config.mode = :standalone
|
|
21
19
|
|
|
22
20
|
@config.live_reload = false
|
|
@@ -47,6 +45,8 @@ module Perron
|
|
|
47
45
|
@config.sitemap.enabled = false
|
|
48
46
|
@config.sitemap.priority = 0.5
|
|
49
47
|
@config.sitemap.change_frequency = :monthly
|
|
48
|
+
@config.sitemap.emit_priority = false
|
|
49
|
+
@config.sitemap.emit_changefreq = false
|
|
50
50
|
|
|
51
51
|
@config.site_name = nil
|
|
52
52
|
@config.site_description = nil
|
|
@@ -66,11 +66,15 @@ module Perron
|
|
|
66
66
|
|
|
67
67
|
def mode = @config.mode.to_s.inquiry
|
|
68
68
|
|
|
69
|
+
def output_server_strict = @config.fetch(:output_server_strict) { mode.standalone? }
|
|
70
|
+
|
|
69
71
|
def additional_routes
|
|
70
72
|
@additional_routes || (mode.integrated? ? [] : %w[root_path])
|
|
71
73
|
end
|
|
72
74
|
|
|
73
75
|
def deploy
|
|
76
|
+
Perron.deprecator.deprecation_warning(:deploy, "Perron.configuration.deploy is deprecated and its behavior will change in a future 1.x release (target: 1.3.0).")
|
|
77
|
+
|
|
74
78
|
@deploy ||= ActiveSupport::OrderedOptions.new.tap do |config|
|
|
75
79
|
def config.method_missing(method_name, *args, &block)
|
|
76
80
|
if method_name.to_s.end_with?("=")
|
data/lib/perron/deprecator.rb
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perron
|
|
4
|
+
class Feeds
|
|
5
|
+
module Split
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def grouped_resources(resources, extractor)
|
|
9
|
+
resources
|
|
10
|
+
.flat_map { |resource| extract(resource, extractor).map { [it, resource] } }
|
|
11
|
+
.group_by(&:first)
|
|
12
|
+
.transform_values { it.map(&:last) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def split_values(resources, extractor)
|
|
16
|
+
resources
|
|
17
|
+
.flat_map { extract(it, extractor) }
|
|
18
|
+
.uniq
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def extract(resource, extractor)
|
|
22
|
+
value = case extractor
|
|
23
|
+
when Symbol then resource.public_send(extractor)
|
|
24
|
+
when Proc then extractor.call(resource)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Array(value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def split_path_for(type_config, value)
|
|
31
|
+
split_by = type_config[:split_by]
|
|
32
|
+
|
|
33
|
+
if split_by[:path]
|
|
34
|
+
split_by[:path].gsub(":value", value.to_s.parameterize)
|
|
35
|
+
else
|
|
36
|
+
extension = File.extname(type_config.path)
|
|
37
|
+
base_path = type_config.path.delete_suffix(extension)
|
|
38
|
+
field = split_by[:extractor]
|
|
39
|
+
field_name = field.is_a?(Symbol) ? field.to_s : "custom"
|
|
40
|
+
|
|
41
|
+
"#{base_path}/#{field_name}/#{value.to_s.parameterize}#{extension}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/perron/feeds.rb
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "perron/feeds/split"
|
|
4
|
+
|
|
3
5
|
module Perron
|
|
4
6
|
class Feeds
|
|
5
7
|
include ActionView::Helpers::TagHelper
|
|
8
|
+
include Perron::Feeds::Split
|
|
6
9
|
|
|
7
10
|
def render(options = {})
|
|
8
11
|
html_tags = []
|
|
@@ -22,6 +25,20 @@ module Perron
|
|
|
22
25
|
title = "#{collection.name.humanize} #{type.to_s.humanize} Feed"
|
|
23
26
|
|
|
24
27
|
html_tags << tag(:link, rel: "alternate", type: MIME_TYPES[type], title: title, href: absolute_url)
|
|
28
|
+
|
|
29
|
+
next unless feed[:split_by]
|
|
30
|
+
|
|
31
|
+
split_values(collection.resources, feed[:split_by][:extractor]).each do |value|
|
|
32
|
+
split_path = split_path_for(feed, value)
|
|
33
|
+
split_url = URI.join(url.root_url, split_path).to_s
|
|
34
|
+
split_title = if (title_template = feed[:split_by][:title])
|
|
35
|
+
title_template.gsub(":value", value.to_s.humanize)
|
|
36
|
+
else
|
|
37
|
+
"#{collection.name.humanize}: #{value.to_s.humanize} #{type.to_s.humanize} Feed"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
html_tags << tag(:link, rel: "alternate", type: MIME_TYPES[type], title: split_title, href: split_url)
|
|
41
|
+
end
|
|
25
42
|
end
|
|
26
43
|
end
|
|
27
44
|
end
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
# Deploy configuration for Perron
|
|
2
2
|
# Requires Beam Up (`bundle add beam_up`)
|
|
3
|
-
# See also: https://perron.railsdesigner.com/docs/deploy
|
|
3
|
+
# See also: https://perron.railsdesigner.com/docs/deploy/#deploy-task
|
|
4
4
|
|
|
5
5
|
# Uncomment and configure your provider:
|
|
6
|
-
# provider:
|
|
6
|
+
# provider: seal_static
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# site_id: your_site_id
|
|
8
|
+
# seal_static:
|
|
9
|
+
# api_key: your_key_here
|
|
11
10
|
|
|
12
11
|
before_actions:
|
|
13
12
|
- RAILS_ENV=production bundle exec rails perron:build
|
data/lib/perron/install.rb
CHANGED
|
@@ -6,9 +6,6 @@ copy_file "#{__dir__}/install/initializer.rb", "config/initializers/perron.rb"
|
|
|
6
6
|
say "Create content data directory"
|
|
7
7
|
copy_file "#{__dir__}/install/README.md", "app/content/data/README.md"
|
|
8
8
|
|
|
9
|
-
say "Create deploy configuration"
|
|
10
|
-
copy_file "#{__dir__}/install/deploy.yml", "config/deploy.yml"
|
|
11
|
-
|
|
12
9
|
say "Add Markdown gem options to Gemfile"
|
|
13
10
|
append_to_file "Gemfile", <<~RUBY
|
|
14
11
|
|
data/lib/perron/relation.rb
CHANGED
|
@@ -34,9 +34,11 @@ module Perron
|
|
|
34
34
|
attribute, direction = attribute.first
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
present, missing = partition { !it.public_send(attribute).nil? }
|
|
38
|
+
present = present.sort_by { it.public_send(attribute) }
|
|
39
|
+
present = present.reverse if direction == :desc
|
|
38
40
|
|
|
39
|
-
Relation.new(
|
|
41
|
+
Relation.new(present + missing, @model_class)
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
def pluck(*attributes)
|
|
@@ -12,17 +12,17 @@ module Perron
|
|
|
12
12
|
|
|
13
13
|
config.feeds = Options.new
|
|
14
14
|
|
|
15
|
-
config.feeds.atom =
|
|
15
|
+
config.feeds.atom = FeedTypeConfig.new
|
|
16
16
|
config.feeds.atom.enabled = false
|
|
17
17
|
config.feeds.atom.path = "feeds/#{collection.name.demodulize.parameterize}.atom"
|
|
18
18
|
config.feeds.atom.max_items = 20
|
|
19
19
|
|
|
20
|
-
config.feeds.json =
|
|
20
|
+
config.feeds.json = FeedTypeConfig.new
|
|
21
21
|
config.feeds.json.enabled = false
|
|
22
22
|
config.feeds.json.path = "feeds/#{collection.name.demodulize.parameterize}.json"
|
|
23
23
|
config.feeds.json.max_items = 20
|
|
24
24
|
|
|
25
|
-
config.feeds.rss =
|
|
25
|
+
config.feeds.rss = FeedTypeConfig.new
|
|
26
26
|
config.feeds.rss.enabled = false
|
|
27
27
|
config.feeds.rss.path = "feeds/#{collection.name.demodulize.parameterize}.xml"
|
|
28
28
|
config.feeds.rss.max_items = 20
|
|
@@ -58,6 +58,16 @@ module Perron
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
private_constant :Options
|
|
61
|
+
|
|
62
|
+
class FeedTypeConfig < ActiveSupport::OrderedOptions
|
|
63
|
+
def split_by(method_or_lambda = nil, path: nil, title: nil, &block)
|
|
64
|
+
extractor = method_or_lambda || block
|
|
65
|
+
|
|
66
|
+
self[:split_by] = {extractor: extractor}
|
|
67
|
+
self[:split_by][:path] = path if path
|
|
68
|
+
self[:split_by][:title] = title if title
|
|
69
|
+
end
|
|
70
|
+
end
|
|
61
71
|
end
|
|
62
72
|
end
|
|
63
73
|
end
|
|
@@ -30,6 +30,7 @@ module Perron
|
|
|
30
30
|
to[:title] ||= @config.site_name || Rails.application.name.underscore.camelize
|
|
31
31
|
|
|
32
32
|
to[:canonical_url] ||= canonical_url
|
|
33
|
+
to[:explicit_canonical_url] = @frontmatter[:canonical_url]
|
|
33
34
|
|
|
34
35
|
to[:image] = absolute_url(to[:image]) if to[:image]
|
|
35
36
|
|
|
@@ -71,7 +72,7 @@ module Perron
|
|
|
71
72
|
return path if path.blank?
|
|
72
73
|
return path if path.start_with?("http://", "https://", "//")
|
|
73
74
|
|
|
74
|
-
Perron.configuration.url.delete_suffix("/")
|
|
75
|
+
"#{Perron.configuration.url.delete_suffix("/")}/#{path.delete_prefix("/")}"
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def site_data
|
|
@@ -54,7 +54,15 @@ module Perron
|
|
|
54
54
|
return @date_from_filename if defined?(@date_from_filename)
|
|
55
55
|
|
|
56
56
|
match = File.basename(file_path).match(DATE_REGEX)
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
@date_from_filename =
|
|
59
|
+
if match
|
|
60
|
+
begin
|
|
61
|
+
Date.new(match[:year].to_i, match[:month].to_i, match[:day].to_i).in_time_zone
|
|
62
|
+
rescue Date::Error
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
58
66
|
end
|
|
59
67
|
end
|
|
60
68
|
end
|
|
@@ -19,12 +19,18 @@ module Perron
|
|
|
19
19
|
|
|
20
20
|
def parsed(content)
|
|
21
21
|
if content =~ /\A---\s*(.*?)\s*---\s*(.*)/m
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
parsed_yaml = YAML.safe_load($1, permitted_classes: [Date, Time])
|
|
23
|
+
|
|
24
|
+
if parsed_yaml.nil? || parsed_yaml.is_a?(Hash)
|
|
25
|
+
@frontmatter = parsed_yaml || {}
|
|
26
|
+
@content = $2.strip
|
|
27
|
+
|
|
28
|
+
return
|
|
29
|
+
end
|
|
27
30
|
end
|
|
31
|
+
|
|
32
|
+
@frontmatter = {}
|
|
33
|
+
@content = content
|
|
28
34
|
end
|
|
29
35
|
end
|
|
30
36
|
end
|
|
@@ -37,12 +37,14 @@ module Perron
|
|
|
37
37
|
def generate_from_sources!
|
|
38
38
|
return unless source_backed?
|
|
39
39
|
|
|
40
|
+
extension = source_definitions.values.first&.dig(:extension) || "erb"
|
|
41
|
+
|
|
40
42
|
derive.each do |combo|
|
|
41
43
|
content = content_with combo
|
|
42
44
|
filename = filename_with combo
|
|
43
45
|
|
|
44
46
|
FileUtils.mkdir_p(output_dir)
|
|
45
|
-
File.write(output_dir.join("#{filename}
|
|
47
|
+
File.write(output_dir.join("#{filename}.#{extension}"), content)
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perron
|
|
4
|
+
class Resource
|
|
5
|
+
module Updatable
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
def metadata
|
|
10
|
+
@metadata ||= Proxy.new(super, self)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Proxy
|
|
15
|
+
def initialize(metadata, resource)
|
|
16
|
+
@metadata = metadata
|
|
17
|
+
@resource = resource
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update(attributes)
|
|
21
|
+
attributes = attributes.deep_symbolize_keys
|
|
22
|
+
|
|
23
|
+
separator = Perron::Resource::Separator.new(@resource.raw_content)
|
|
24
|
+
frontmatter = separator.frontmatter.to_h.merge(attributes)
|
|
25
|
+
yaml = frontmatter.transform_keys(&:to_s).to_yaml.sub(/\A---\n/, "")
|
|
26
|
+
body = separator.content
|
|
27
|
+
|
|
28
|
+
File.write(@resource.file_path, "---\n#{yaml}---\n\n#{body}\n")
|
|
29
|
+
|
|
30
|
+
@resource.instance_variable_set(:@frontmatter, nil)
|
|
31
|
+
attributes.each { |key, value| @metadata[key] = value }
|
|
32
|
+
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def respond_to_missing?(name, include_private = false)
|
|
37
|
+
@metadata.respond_to?(name, include_private) || super
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def method_missing(name, *arguments, &block)
|
|
41
|
+
@metadata.public_send(name, *arguments, &block)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/perron/resource.rb
CHANGED
|
@@ -11,8 +11,10 @@ module Perron
|
|
|
11
11
|
include Feeds::Author
|
|
12
12
|
include Feeds::Template
|
|
13
13
|
|
|
14
|
-
def initialize(collection:)
|
|
14
|
+
def initialize(collection:, resources: nil, feed_config: nil)
|
|
15
15
|
@collection = collection
|
|
16
|
+
@resources = resources
|
|
17
|
+
@feed_config = feed_config
|
|
16
18
|
@configuration = Perron.configuration
|
|
17
19
|
end
|
|
18
20
|
|
|
@@ -28,12 +30,16 @@ module Perron
|
|
|
28
30
|
private
|
|
29
31
|
|
|
30
32
|
def resources
|
|
31
|
-
@
|
|
33
|
+
(@resources || @collection.resources)
|
|
32
34
|
.reject { it.metadata.feed == false }
|
|
33
35
|
.sort_by { it.metadata.published_at || it.metadata.updated_at || Time.current }
|
|
34
36
|
.reverse
|
|
35
37
|
.take(feed_configuration.max_items)
|
|
36
38
|
end
|
|
39
|
+
|
|
40
|
+
def feed_configuration
|
|
41
|
+
@feed_config || super
|
|
42
|
+
end
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
@@ -11,8 +11,10 @@ module Perron
|
|
|
11
11
|
include Feeds::Author
|
|
12
12
|
include Feeds::Template
|
|
13
13
|
|
|
14
|
-
def initialize(collection:)
|
|
14
|
+
def initialize(collection:, resources: nil, feed_config: nil)
|
|
15
15
|
@collection = collection
|
|
16
|
+
@resources = resources
|
|
17
|
+
@feed_config = feed_config
|
|
16
18
|
@configuration = Perron.configuration
|
|
17
19
|
end
|
|
18
20
|
|
|
@@ -28,12 +30,16 @@ module Perron
|
|
|
28
30
|
private
|
|
29
31
|
|
|
30
32
|
def resources
|
|
31
|
-
@
|
|
33
|
+
(@resources || @collection.resources)
|
|
32
34
|
.reject { it.metadata.feed == false }
|
|
33
35
|
.sort_by { it.metadata.published_at || it.metadata.updated_at || Time.current }
|
|
34
36
|
.reverse
|
|
35
37
|
.take(feed_configuration.max_items)
|
|
36
38
|
end
|
|
39
|
+
|
|
40
|
+
def feed_configuration
|
|
41
|
+
@feed_config || super
|
|
42
|
+
end
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
@@ -11,8 +11,10 @@ module Perron
|
|
|
11
11
|
include Feeds::Author
|
|
12
12
|
include Feeds::Template
|
|
13
13
|
|
|
14
|
-
def initialize(collection:)
|
|
14
|
+
def initialize(collection:, resources: nil, feed_config: nil)
|
|
15
15
|
@collection = collection
|
|
16
|
+
@resources = resources
|
|
17
|
+
@feed_config = feed_config
|
|
16
18
|
@configuration = Perron.configuration
|
|
17
19
|
end
|
|
18
20
|
|
|
@@ -28,12 +30,16 @@ module Perron
|
|
|
28
30
|
private
|
|
29
31
|
|
|
30
32
|
def resources
|
|
31
|
-
@
|
|
33
|
+
(@resources || @collection.resources)
|
|
32
34
|
.reject { it.metadata.feed == false }
|
|
33
35
|
.sort_by { it.metadata.published_at || it.metadata.updated_at || Time.current }
|
|
34
36
|
.reverse
|
|
35
37
|
.take(feed_configuration.max_items)
|
|
36
38
|
end
|
|
39
|
+
|
|
40
|
+
def feed_configuration
|
|
41
|
+
@feed_config || super
|
|
42
|
+
end
|
|
37
43
|
end
|
|
38
44
|
end
|
|
39
45
|
end
|
|
@@ -4,10 +4,14 @@ require "perron/site/builder/feeds/atom"
|
|
|
4
4
|
require "perron/site/builder/feeds/json"
|
|
5
5
|
require "perron/site/builder/feeds/rss"
|
|
6
6
|
|
|
7
|
+
require "perron/feeds/split"
|
|
8
|
+
|
|
7
9
|
module Perron
|
|
8
10
|
module Site
|
|
9
11
|
class Builder
|
|
10
12
|
class Feeds
|
|
13
|
+
include Perron::Feeds::Split
|
|
14
|
+
|
|
11
15
|
def initialize(output_path)
|
|
12
16
|
@output_path = output_path
|
|
13
17
|
end
|
|
@@ -18,21 +22,39 @@ module Perron
|
|
|
18
22
|
|
|
19
23
|
config = collection.configuration.feeds
|
|
20
24
|
|
|
21
|
-
if config.atom.enabled
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
generate_feed(collection: collection, type_config: config.atom, generator_class: Atom) if config.atom.enabled
|
|
26
|
+
generate_feed(collection: collection, type_config: config.json, generator_class: Json) if config.json.enabled
|
|
27
|
+
generate_feed(collection: collection, type_config: config.rss, generator_class: Rss) if config.rss.enabled
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def generate_feed(collection:, type_config:, generator_class:)
|
|
34
|
+
generator = generator_class.new(collection: collection)
|
|
35
|
+
content = generator.generate
|
|
24
36
|
|
|
25
|
-
|
|
26
|
-
create_file at: config.json.path, with: Json.new(collection: collection).generate
|
|
27
|
-
end
|
|
37
|
+
create_file(at: type_config.path, with: content) if content.present?
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
return unless type_config[:split_by]
|
|
40
|
+
|
|
41
|
+
grouped_resources(collection.resources, type_config[:split_by][:extractor]).each do |value, group|
|
|
42
|
+
path = split_path_for(type_config, value)
|
|
43
|
+
config = split_config(type_config, value, path)
|
|
44
|
+
content = generator_class.new(collection: collection, resources: group, feed_config: config).generate
|
|
45
|
+
|
|
46
|
+
create_file(at: path, with: content) if content.present?
|
|
32
47
|
end
|
|
33
48
|
end
|
|
34
49
|
|
|
35
|
-
|
|
50
|
+
def split_config(type_config, value, split_path)
|
|
51
|
+
ActiveSupport::OrderedOptions.new.tap do |config|
|
|
52
|
+
type_config.each { |key, value| config[key] = value unless key == :split_by }
|
|
53
|
+
|
|
54
|
+
config.path = split_path
|
|
55
|
+
config.title = "#{type_config.title.presence || Perron.configuration.site_name}: #{value.to_s.humanize}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
36
58
|
|
|
37
59
|
def create_file(at:, with:)
|
|
38
60
|
return if with.blank?
|
|
@@ -52,9 +52,8 @@ module Perron
|
|
|
52
52
|
routes.with_options(Perron.configuration.default_url_options) do |url|
|
|
53
53
|
with.url do
|
|
54
54
|
with.loc url.public_send(route_name.to_s.gsub("_path", "_url"))
|
|
55
|
-
with.priority Perron.configuration.sitemap.priority
|
|
56
|
-
with.changefreq Perron.configuration.sitemap.change_frequency
|
|
57
|
-
with.lastmod Time.current.iso8601
|
|
55
|
+
with.priority Perron.configuration.sitemap.priority if Perron.configuration.sitemap.emit_priority
|
|
56
|
+
with.changefreq Perron.configuration.sitemap.change_frequency if Perron.configuration.sitemap.emit_changefreq
|
|
58
57
|
end
|
|
59
58
|
end
|
|
60
59
|
end
|
|
@@ -76,8 +75,8 @@ module Perron
|
|
|
76
75
|
|
|
77
76
|
with.url do
|
|
78
77
|
with.loc loc
|
|
79
|
-
with.priority Perron.configuration.sitemap.priority
|
|
80
|
-
with.changefreq Perron.configuration.sitemap.change_frequency
|
|
78
|
+
with.priority Perron.configuration.sitemap.priority if Perron.configuration.sitemap.emit_priority
|
|
79
|
+
with.changefreq Perron.configuration.sitemap.change_frequency if Perron.configuration.sitemap.emit_changefreq
|
|
81
80
|
with.lastmod lastmod if lastmod
|
|
82
81
|
end
|
|
83
82
|
end
|
|
@@ -95,14 +94,15 @@ module Perron
|
|
|
95
94
|
|
|
96
95
|
loc = resource.root? ? routes.root_url(url_options) : routes.public_send("#{route.name}_url", resource, **url_options)
|
|
97
96
|
|
|
97
|
+
return if canonical_mismatch?(resource.metadata.explicit_canonical_url, loc)
|
|
98
98
|
return if added_urls.include?(loc)
|
|
99
99
|
added_urls << loc
|
|
100
100
|
|
|
101
101
|
routes.with_options(Perron.configuration.default_url_options) do |url|
|
|
102
102
|
with.url do
|
|
103
103
|
with.loc loc
|
|
104
|
-
with.priority priority
|
|
105
|
-
with.changefreq change_frequency
|
|
104
|
+
with.priority priority if Perron.configuration.sitemap.emit_priority
|
|
105
|
+
with.changefreq change_frequency if Perron.configuration.sitemap.emit_changefreq
|
|
106
106
|
with.lastmod resource.metadata.updated_at&.iso8601 if resource.metadata.updated_at.present?
|
|
107
107
|
end
|
|
108
108
|
end
|
|
@@ -111,10 +111,23 @@ module Perron
|
|
|
111
111
|
def last_modified_for(collection)
|
|
112
112
|
return unless collection
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
dates = resources.filter_map { it.metadata.updated_at || it.metadata.publication_date }
|
|
114
|
+
modification_dates = collection.send(:load_resources).select(&:buildable?).filter_map { it.metadata.updated_at }
|
|
116
115
|
|
|
117
|
-
|
|
116
|
+
modification_dates.max&.iso8601
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def canonical_mismatch?(canonical, location)
|
|
120
|
+
return false unless canonical.is_a?(String) && canonical.present?
|
|
121
|
+
|
|
122
|
+
canonical_uri = URI.parse(canonical)
|
|
123
|
+
canonical_uri = URI.join(location, canonical) unless canonical_uri.host
|
|
124
|
+
page_uri = URI.parse(location)
|
|
125
|
+
|
|
126
|
+
normalize = ->(uri) { [uri.host, uri.path].map(&:to_s).map(&:downcase).join("|") }
|
|
127
|
+
|
|
128
|
+
normalize.call(canonical_uri) != normalize.call(page_uri)
|
|
129
|
+
rescue URI::InvalidURIError
|
|
130
|
+
false
|
|
118
131
|
end
|
|
119
132
|
|
|
120
133
|
def routes = Rails.application.routes.url_helpers
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
namespace :perron do
|
|
2
2
|
desc "Deploy static site using Beam Up"
|
|
3
3
|
task deploy: :environment do
|
|
4
|
+
Perron.deprecator.deprecation_warning(:deploy, "The `perron:deploy` task is deprecated and its behavior will change in a future 1.x release (target: 1.3.0). See https://perron.railsdesigner.com/docs/deploy/ for updates.")
|
|
5
|
+
|
|
4
6
|
begin
|
|
5
7
|
require "beam_up"
|
|
6
8
|
rescue LoadError
|
|
@@ -14,19 +16,19 @@ namespace :perron do
|
|
|
14
16
|
MSG
|
|
15
17
|
end
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
unless config.exist?
|
|
20
|
-
template = File.expand_path("../install/deploy.yml", __dir__)
|
|
21
|
-
FileUtils.cp(template, config)
|
|
19
|
+
config_file = "config/deploy.yml" if Rails.root.join("config/deploy.yml").exist?
|
|
20
|
+
config_file = "config/deploy.yml.erb" if Rails.root.join("config/deploy.yml.erb").exist?
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
if config_file.nil?
|
|
23
|
+
FileUtils.cp(File.expand_path("../install/deploy.yml.erb", __dir__), Rails.root.join("config/deploy.yml.erb"))
|
|
24
|
+
config_file = "config/deploy.yml.erb"
|
|
25
|
+
puts "Created config/deploy.yml.erb"
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
beamed = BeamUp.with_progress do
|
|
27
29
|
BeamUp.deploy!(
|
|
28
30
|
Perron.configuration.output,
|
|
29
|
-
config_file:
|
|
31
|
+
config_file: config_file
|
|
30
32
|
)
|
|
31
33
|
end
|
|
32
34
|
|
|
@@ -37,6 +39,8 @@ namespace :perron do
|
|
|
37
39
|
namespace :deploy do
|
|
38
40
|
desc "Initialize deploy configuration with Beam Up"
|
|
39
41
|
task :init, [:provider] do |task, arguments|
|
|
42
|
+
Perron.deprecator.deprecation_warning(:deploy, "The `perron:deploy:init` task is deprecated and its behavior will change in a future 1.x release (target: 1.3.0). See https://perron.railsdesigner.com/docs/deploy/ for updates.")
|
|
43
|
+
|
|
40
44
|
begin
|
|
41
45
|
require "beam_up"
|
|
42
46
|
rescue LoadError
|
|
@@ -50,7 +54,14 @@ namespace :perron do
|
|
|
50
54
|
MSG
|
|
51
55
|
end
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
config_file = "config/deploy.yml" if Rails.root.join("config/deploy.yml").exist?
|
|
58
|
+
config_file = "config/deploy.yml.erb" if Rails.root.join("config/deploy.yml.erb").exist?
|
|
59
|
+
|
|
60
|
+
if config_file.nil?
|
|
61
|
+
config_file = "config/deploy.yml.erb"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
path = BeamUp.init!(arguments[:provider], config_file: config_file)
|
|
54
65
|
|
|
55
66
|
puts "Configured Beam Up in #{path}"
|
|
56
67
|
end
|
data/lib/perron/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: perron
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Designer Developers
|
|
@@ -127,6 +127,7 @@ files:
|
|
|
127
127
|
- lib/perron/engine.rb
|
|
128
128
|
- lib/perron/errors.rb
|
|
129
129
|
- lib/perron/feeds.rb
|
|
130
|
+
- lib/perron/feeds/split.rb
|
|
130
131
|
- lib/perron/html_processor.rb
|
|
131
132
|
- lib/perron/html_processor/absolute_urls.rb
|
|
132
133
|
- lib/perron/html_processor/base.rb
|
|
@@ -134,7 +135,7 @@ files:
|
|
|
134
135
|
- lib/perron/html_processor/target_blank.rb
|
|
135
136
|
- lib/perron/install.rb
|
|
136
137
|
- lib/perron/install/README.md.tt
|
|
137
|
-
- lib/perron/install/deploy.yml
|
|
138
|
+
- lib/perron/install/deploy.yml.erb
|
|
138
139
|
- lib/perron/install/initializer.rb.tt
|
|
139
140
|
- lib/perron/markdown.rb
|
|
140
141
|
- lib/perron/metatags.rb
|
|
@@ -162,6 +163,7 @@ files:
|
|
|
162
163
|
- lib/perron/resource/sourceable.rb
|
|
163
164
|
- lib/perron/resource/sweeper.rb
|
|
164
165
|
- lib/perron/resource/table_of_content.rb
|
|
166
|
+
- lib/perron/resource/updatable.rb
|
|
165
167
|
- lib/perron/site.rb
|
|
166
168
|
- lib/perron/site/builder.rb
|
|
167
169
|
- lib/perron/site/builder/additional_routes.rb
|
|
@@ -209,7 +211,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
209
211
|
- !ruby/object:Gem::Version
|
|
210
212
|
version: '0'
|
|
211
213
|
requirements: []
|
|
212
|
-
rubygems_version: 4.0.
|
|
214
|
+
rubygems_version: 4.0.22
|
|
213
215
|
specification_version: 4
|
|
214
216
|
summary: Rails-based static site generator
|
|
215
217
|
test_files: []
|