perron 0.10.0 → 0.12.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 +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +108 -46
- data/app/helpers/meta_tags_helper.rb +1 -1
- data/lib/generators/content/content_generator.rb +25 -0
- data/lib/generators/content/templates/root.erb.tt +0 -1
- data/lib/generators/perron/install_generator.rb +6 -1
- data/lib/generators/perron/templates/README.md.tt +18 -1
- data/lib/generators/perron/templates/initializer.rb.tt +5 -2
- data/lib/perron/{site/collection.rb → collection.rb} +8 -2
- data/lib/perron/configuration.rb +4 -0
- data/lib/perron/{site/data.rb → data.rb} +16 -2
- data/lib/perron/feeds.rb +1 -0
- data/lib/perron/html_processor/syntax_highlight.rb +30 -0
- data/lib/perron/html_processor.rb +12 -8
- data/lib/perron/markdown.rb +6 -5
- data/lib/perron/metatags.rb +33 -59
- data/lib/perron/refinements/delete_suffixes.rb +11 -7
- data/lib/perron/{site/resource → resource}/class_methods.rb +5 -1
- data/lib/perron/resource/metadata.rb +67 -0
- data/lib/perron/{site/resource → resource}/publishable.rb +5 -5
- data/lib/perron/{site/resource → resource}/related.rb +2 -1
- data/lib/perron/{site/resource → resource}/separator.rb +5 -5
- data/lib/perron/resource/slug.rb +27 -0
- data/lib/perron/{site/resource.rb → resource.rb} +38 -14
- data/lib/perron/root.rb +1 -1
- data/lib/perron/site/builder/assets.rb +2 -1
- data/lib/perron/site/builder/feeds/json.rb +6 -4
- data/lib/perron/site/builder/feeds/rss.rb +6 -4
- data/lib/perron/site/builder/feeds.rb +2 -0
- data/lib/perron/site/builder/page.rb +5 -3
- data/lib/perron/site/builder/sitemap.rb +1 -0
- data/lib/perron/site/builder.rb +1 -1
- data/lib/perron/site.rb +3 -4
- data/lib/perron/version.rb +1 -1
- data/lib/perron.rb +1 -0
- data/perron.gemspec +1 -1
- metadata +18 -16
- data/lib/perron/site/resource/slug.rb +0 -24
- /data/lib/perron/{site/data → data}/proxy.rb +0 -0
- /data/lib/perron/{site/resource → resource}/configuration.rb +0 -0
- /data/lib/perron/{site/resource → resource}/core.rb +0 -0
- /data/lib/perron/{site/resource → resource}/related/stop_words.rb +0 -0
- /data/lib/perron/{site/resource → resource}/renderer.rb +0 -0
data/lib/perron/markdown.rb
CHANGED
@@ -18,7 +18,7 @@ module Perron
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def markdown_parser
|
21
|
-
if defined?(::
|
21
|
+
if defined?(::Commonmarker)
|
22
22
|
CommonMarkerParser.new
|
23
23
|
elsif defined?(::Kramdown)
|
24
24
|
KramdownParser.new
|
@@ -31,17 +31,18 @@ module Perron
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class CommonMarkerParser
|
34
|
-
def parse(text) =
|
34
|
+
def parse(text) = Commonmarker.to_html(text, **Perron.configuration.markdown_options)
|
35
35
|
end
|
36
36
|
|
37
37
|
class KramdownParser
|
38
|
-
def parse(text) = Kramdown::Document.new(text).to_html
|
38
|
+
def parse(text) = Kramdown::Document.new(text, Perron.configuration.markdown_options).to_html
|
39
39
|
end
|
40
40
|
|
41
41
|
class RedcarpetParser
|
42
42
|
def parse(text)
|
43
|
-
|
44
|
-
|
43
|
+
options = Perron.configuration.markdown_options
|
44
|
+
renderer = Redcarpet::Render::HTML.new(options.fetch(:renderer_options, {}))
|
45
|
+
markdown = Redcarpet::Markdown.new(renderer, options.fetch(:markdown_options, {}))
|
45
46
|
|
46
47
|
markdown.render(text)
|
47
48
|
end
|
data/lib/perron/metatags.rb
CHANGED
@@ -4,9 +4,8 @@ module Perron
|
|
4
4
|
class Metatags
|
5
5
|
include ActionView::Helpers::TagHelper
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
9
|
-
@config = Perron.configuration
|
7
|
+
def initialize(data)
|
8
|
+
@data = data
|
10
9
|
end
|
11
10
|
|
12
11
|
def render(options = {})
|
@@ -19,75 +18,50 @@ module Perron
|
|
19
18
|
|
20
19
|
private
|
21
20
|
|
22
|
-
FRONTMATTER_KEY_MAP = {
|
23
|
-
"locale" => %w[og:locale],
|
24
|
-
"image" => %w[og:image twitter:image],
|
25
|
-
"author" => %w[og:author]
|
26
|
-
}.freeze
|
27
|
-
|
28
21
|
def tags
|
29
|
-
@tags ||=
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
og_type: meta_tag(property: "og:type", content: frontmatter["og:type"] || type),
|
52
|
-
og_url: meta_tag(property: "og:url", content: canonical_url),
|
53
|
-
og_image: meta_tag(property: "og:image", content: og_image),
|
54
|
-
|
55
|
-
og_description: meta_tag(property: "og:description", content: frontmatter["og:description"] || description),
|
56
|
-
og_site_name: meta_tag(property: "og:site_name", content: @config.site_name),
|
57
|
-
og_logo: meta_tag(property: "og:logo", content: frontmatter["og:logo"] || logo),
|
58
|
-
og_author: meta_tag(property: "og:author", content: frontmatter["og:author"] || author),
|
59
|
-
og_locale: meta_tag(property: "og:locale", content: frontmatter["og:locale"] || locale),
|
60
|
-
|
61
|
-
twitter_card: meta_tag(name: "twitter:card", content: frontmatter["twitter:card"] || "summary_large_image"),
|
62
|
-
twitter_title: meta_tag(name: "twitter:title", content: frontmatter["twitter:title"] || title),
|
63
|
-
twitter_description: meta_tag(name: "twitter:description", content: frontmatter["twitter:description"] || description),
|
64
|
-
twitter_image: meta_tag(name: "twitter:image", content: twitter_image)
|
65
|
-
}
|
66
|
-
end
|
22
|
+
@tags ||= {
|
23
|
+
title: title_tag(@data[:title]),
|
24
|
+
canonical: link_tag(rel: "canonical", href: @data[:canonical_url]),
|
25
|
+
|
26
|
+
description: meta_tag(name: "description", content: @data[:description]),
|
27
|
+
article_published: meta_tag(property: "article:published_time", content: @data[:article_published_time]),
|
28
|
+
|
29
|
+
og_title: meta_tag(property: "og:title", content: @data[:og_title]),
|
30
|
+
og_type: meta_tag(property: "og:type", content: @data[:og_type]),
|
31
|
+
og_url: meta_tag(property: "og:url", content: @data[:og_url]),
|
32
|
+
og_image: meta_tag(property: "og:image", content: @data[:og_image]),
|
33
|
+
og_description: meta_tag(property: "og:description", content: @data[:og_description]),
|
34
|
+
og_site_name: meta_tag(property: "og:site_name", content: @data[:og_site_name]),
|
35
|
+
og_logo: meta_tag(property: "og:logo", content: @data[:og_logo]),
|
36
|
+
og_author: meta_tag(property: "og:author", content: @data[:og_author]),
|
37
|
+
og_locale: meta_tag(property: "og:locale", content: @data[:og_locale]),
|
38
|
+
|
39
|
+
twitter_card: meta_tag(name: "twitter:card", content: @data[:twitter_card]),
|
40
|
+
twitter_title: meta_tag(name: "twitter:title", content: @data[:twitter_title]),
|
41
|
+
twitter_description: meta_tag(name: "twitter:description", content: @data[:twitter_description]),
|
42
|
+
twitter_image: meta_tag(name: "twitter:image", content: @data[:twitter_image])
|
43
|
+
}
|
67
44
|
end
|
68
45
|
|
69
46
|
def title_tag(content)
|
47
|
+
config = Perron.configuration
|
70
48
|
resource_title = content.to_s.strip
|
71
|
-
title_suffix =
|
72
|
-
|
49
|
+
title_suffix = config.metadata.title_suffix&.strip
|
73
50
|
suffix = (title_suffix if title_suffix.present? && resource_title != title_suffix)
|
74
51
|
|
75
|
-
tag.title([resource_title, suffix].compact.join(
|
52
|
+
tag.title([resource_title, suffix].compact.join(config.metadata.title_separator))
|
76
53
|
end
|
77
54
|
|
78
|
-
def
|
79
|
-
return if attributes[:
|
55
|
+
def link_tag(attributes)
|
56
|
+
return if attributes[:href].blank?
|
80
57
|
|
81
|
-
tag.
|
58
|
+
tag.link(**attributes)
|
82
59
|
end
|
83
60
|
|
84
|
-
def
|
85
|
-
|
86
|
-
base_url = "#{url_options[:protocol]}://#{url_options[:host]}"
|
87
|
-
url = URI.join(base_url, @resource&.path).to_s
|
88
|
-
has_extension = URI(url).path.split("/").last&.include?(".")
|
61
|
+
def meta_tag(attributes)
|
62
|
+
return if attributes[:content].blank?
|
89
63
|
|
90
|
-
|
64
|
+
tag.meta(**attributes)
|
91
65
|
end
|
92
66
|
end
|
93
67
|
end
|
@@ -1,11 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Perron
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
suffixes
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module Refinements
|
5
|
+
module DeleteSuffixes
|
6
|
+
refine String do
|
7
|
+
def delete_suffixes(suffixes)
|
8
|
+
suffixes
|
9
|
+
.sort_by(&:length)
|
10
|
+
.reverse_each
|
11
|
+
.reduce(self, :delete_suffix)
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -30,13 +30,17 @@ module Perron
|
|
30
30
|
|
31
31
|
def collection = Collection.new(collection_name)
|
32
32
|
|
33
|
+
def root
|
34
|
+
collection_name.pages? && collection.find_by_file_name("root", name.constantize)
|
35
|
+
end
|
36
|
+
|
33
37
|
def model_name
|
34
38
|
@model_name ||= ActiveModel::Name.new(self, nil, name.demodulize.to_s)
|
35
39
|
end
|
36
40
|
|
37
41
|
private
|
38
42
|
|
39
|
-
def collection_name = name.demodulize.underscore.pluralize
|
43
|
+
def collection_name = name.demodulize.underscore.pluralize.inquiry
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perron
|
4
|
+
class Resource
|
5
|
+
class Metadata
|
6
|
+
def initialize(resource:, frontmatter:, collection:)
|
7
|
+
@resource = resource
|
8
|
+
@frontmatter = frontmatter&.deep_symbolize_keys || {}
|
9
|
+
@collection = collection
|
10
|
+
@config = Perron.configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def data
|
14
|
+
@data ||= ActiveSupport::OrderedOptions
|
15
|
+
.new
|
16
|
+
.merge(apply_fallbacks_and_defaults(to: merged_site_collection_resource_frontmatter))
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def merged_site_collection_resource_frontmatter = site_data.merge(collection_data).merge(@frontmatter)
|
22
|
+
|
23
|
+
def apply_fallbacks_and_defaults(to:)
|
24
|
+
to[:title] ||= @config.site_name || Rails.application.name.underscore.camelize
|
25
|
+
|
26
|
+
to[:canonical_url] ||= canonical_url
|
27
|
+
|
28
|
+
to[:og_image] ||= to[:image]
|
29
|
+
to[:twitter_image] ||= to[:og_image]
|
30
|
+
|
31
|
+
to[:og_title] ||= to[:title]
|
32
|
+
to[:twitter_title] ||= to[:title]
|
33
|
+
to[:og_description] ||= to[:description]
|
34
|
+
to[:twitter_description] ||= to[:description]
|
35
|
+
to[:og_type] ||= to[:type]
|
36
|
+
to[:og_logo] ||= to[:logo]
|
37
|
+
to[:og_author] ||= to[:author]
|
38
|
+
to[:og_locale] ||= to[:locale]
|
39
|
+
|
40
|
+
to[:og_site_name] = @config.site_name
|
41
|
+
to[:twitter_card] ||= "summary_large_image"
|
42
|
+
to[:og_url] = canonical_url
|
43
|
+
to[:article_published_time] = @resource.published_at
|
44
|
+
|
45
|
+
to.compact
|
46
|
+
end
|
47
|
+
|
48
|
+
def canonical_url
|
49
|
+
return @frontmatter[:canonical_url] if @frontmatter[:canonical_url]
|
50
|
+
return Rails.application.routes.url_helpers.root_url(**Perron.configuration.default_url_options) if @resource.slug == "/"
|
51
|
+
|
52
|
+
Rails.application.routes.url_helpers.polymorphic_url(
|
53
|
+
@resource,
|
54
|
+
**Perron.configuration.default_url_options
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
def site_data
|
59
|
+
@config.metadata.except(:title_separator, :title_suffix).deep_symbolize_keys || {}
|
60
|
+
end
|
61
|
+
|
62
|
+
def collection_data
|
63
|
+
@collection&.configuration&.metadata&.deep_symbolize_keys || {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -7,10 +7,10 @@ module Perron
|
|
7
7
|
|
8
8
|
included do
|
9
9
|
def published?
|
10
|
-
return true if
|
10
|
+
return true if Perron.configuration.view_unpublished
|
11
11
|
|
12
|
-
return false if
|
13
|
-
return false if
|
12
|
+
return false if frontmatter.draft == true
|
13
|
+
return false if frontmatter.published == false
|
14
14
|
return false if publication_date&.after?(Time.current)
|
15
15
|
|
16
16
|
true
|
@@ -20,8 +20,8 @@ module Perron
|
|
20
20
|
|
21
21
|
def publication_date
|
22
22
|
@publication_date ||= begin
|
23
|
-
from_meta =
|
24
|
-
Time.zone.parse(
|
23
|
+
from_meta = frontmatter.published_at.present? ? begin
|
24
|
+
Time.zone.parse(frontmatter.published_at.to_s)
|
25
25
|
rescue
|
26
26
|
nil
|
27
27
|
end : nil
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "perron/
|
3
|
+
require "perron/resource/related/stop_words"
|
4
4
|
|
5
5
|
module Perron
|
6
6
|
module Site
|
@@ -70,6 +70,7 @@ module Perron
|
|
70
70
|
@tokenized_content ||= {}
|
71
71
|
|
72
72
|
return @tokenized_content[target_resource] if @tokenized_content.key?(target_resource)
|
73
|
+
return [] if target_resource.content.blank?
|
73
74
|
|
74
75
|
content = target_resource.content.gsub(/<[^>]*>/, " ")
|
75
76
|
tokens = content.downcase.scan(/\w+/).reject { StopWords.all.include?(it) || it.length < 3 }
|
@@ -9,9 +9,9 @@ module Perron
|
|
9
9
|
parsed(content)
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
@
|
14
|
-
@
|
12
|
+
def frontmatter
|
13
|
+
@frontmatter_with_dot_access ||= ActiveSupport::OrderedOptions.new.tap do |options|
|
14
|
+
@frontmatter.each { |key, value| options[key] = value }
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -19,10 +19,10 @@ module Perron
|
|
19
19
|
|
20
20
|
def parsed(content)
|
21
21
|
if content =~ /\A---\s*(.*?)\s*---\s*(.*)/m
|
22
|
-
@
|
22
|
+
@frontmatter = YAML.safe_load($1, permitted_classes: [Date, Time]) || {}
|
23
23
|
@content = $2.strip
|
24
24
|
else
|
25
|
-
@
|
25
|
+
@frontmatter = {}
|
26
26
|
@content = content
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "perron/refinements/delete_suffixes"
|
4
|
+
|
5
|
+
module Perron
|
6
|
+
class Resource
|
7
|
+
class Slug
|
8
|
+
using Perron::Refinements::DeleteSuffixes
|
9
|
+
|
10
|
+
def initialize(resource, frontmatter)
|
11
|
+
@resource = resource
|
12
|
+
@frontmatter = frontmatter
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
return "/" if Perron.configuration.allowed_extensions.any? { @resource.filename == "root.#{it}" }
|
17
|
+
|
18
|
+
@frontmatter.slug.presence ||
|
19
|
+
@resource.filename.sub(/^[\d-]+-/, "").delete_suffixes(dot_prepended_allowed_extensions)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def dot_prepended_allowed_extensions = Perron.configuration.allowed_extensions.map { ".#{it}" }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "perron/
|
4
|
-
require "perron/
|
5
|
-
require "perron/
|
6
|
-
require "perron/
|
7
|
-
require "perron/
|
8
|
-
require "perron/
|
9
|
-
require "perron/
|
10
|
-
require "perron/
|
3
|
+
require "perron/resource/configuration"
|
4
|
+
require "perron/resource/core"
|
5
|
+
require "perron/resource/class_methods"
|
6
|
+
require "perron/resource/metadata"
|
7
|
+
require "perron/resource/publishable"
|
8
|
+
require "perron/resource/related"
|
9
|
+
require "perron/resource/renderer"
|
10
|
+
require "perron/resource/slug"
|
11
|
+
require "perron/resource/separator"
|
11
12
|
|
12
13
|
module Perron
|
13
14
|
class Resource
|
@@ -29,10 +30,21 @@ module Perron
|
|
29
30
|
|
30
31
|
def filename = File.basename(@file_path)
|
31
32
|
|
32
|
-
def slug = Perron::Resource::Slug.new(self).create
|
33
|
+
def slug = Perron::Resource::Slug.new(self, frontmatter).create
|
33
34
|
alias_method :path, :slug
|
34
35
|
alias_method :to_param, :slug
|
35
36
|
|
37
|
+
def metadata
|
38
|
+
Perron::Resource::Metadata.new(
|
39
|
+
resource: self,
|
40
|
+
frontmatter: frontmatter,
|
41
|
+
collection: collection
|
42
|
+
).data
|
43
|
+
end
|
44
|
+
|
45
|
+
def raw_content = File.read(@file_path)
|
46
|
+
alias_method :raw, :raw_content
|
47
|
+
|
36
48
|
def content
|
37
49
|
page_content = Perron::Resource::Separator.new(raw_content).content
|
38
50
|
|
@@ -41,10 +53,14 @@ module Perron
|
|
41
53
|
Perron::Resource::Renderer.erb(page_content, {resource: self})
|
42
54
|
end
|
43
55
|
|
44
|
-
def
|
56
|
+
def to_partial_path
|
57
|
+
@to_partial_path ||= begin
|
58
|
+
element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self.class.model_name))
|
59
|
+
collection = ActiveSupport::Inflector.tableize(self.class.model_name)
|
45
60
|
|
46
|
-
|
47
|
-
|
61
|
+
File.join("content", collection, element)
|
62
|
+
end
|
63
|
+
end
|
48
64
|
|
49
65
|
def collection = Collection.new(self.class.model_name.collection)
|
50
66
|
|
@@ -53,8 +69,8 @@ module Perron
|
|
53
69
|
|
54
70
|
private
|
55
71
|
|
56
|
-
def
|
57
|
-
@
|
72
|
+
def frontmatter
|
73
|
+
@frontmatter ||= Perron::Resource::Separator.new(raw_content).frontmatter
|
58
74
|
end
|
59
75
|
|
60
76
|
def generate_id
|
@@ -62,5 +78,13 @@ module Perron
|
|
62
78
|
@file_path.delete_prefix(Perron.configuration.input.to_s).parameterize
|
63
79
|
).first(ID_LENGTH)
|
64
80
|
end
|
81
|
+
|
82
|
+
def erb_processing?
|
83
|
+
@file_path.ends_with?(".erb") || metadata.erb == true
|
84
|
+
end
|
85
|
+
|
86
|
+
def root?
|
87
|
+
collection.name.inquiry.pages? && File.basename(filename) == "root"
|
88
|
+
end
|
65
89
|
end
|
66
90
|
end
|
data/lib/perron/root.rb
CHANGED
@@ -29,7 +29,8 @@ module Perron
|
|
29
29
|
end
|
30
30
|
|
31
31
|
FileUtils.mkdir_p(destination)
|
32
|
-
FileUtils.
|
32
|
+
FileUtils.move(Dir.glob("#{source}/*"), destination, force: true)
|
33
|
+
FileUtils.remove_dir(source)
|
33
34
|
|
34
35
|
puts " Copied assets to `#{destination.relative_path_from(Rails.root)}`"
|
35
36
|
|
@@ -18,14 +18,14 @@ module Perron
|
|
18
18
|
hash = Rails.application.routes.url_helpers.with_options(@configuration.default_url_options) do |url|
|
19
19
|
{
|
20
20
|
version: "https://jsonfeed.org/version/1.1",
|
21
|
-
title: @configuration.site_name,
|
22
21
|
home_page_url: @configuration.url,
|
23
|
-
|
22
|
+
title: feed_configuration.title.presence || @configuration.site_name,
|
23
|
+
description: feed_configuration.description.presence || @configuration.site_description,
|
24
24
|
items: resources.map do |resource|
|
25
25
|
{
|
26
26
|
id: resource.id,
|
27
27
|
url: url.polymorphic_url(resource),
|
28
|
-
date_published:
|
28
|
+
date_published: resource.published_at&.iso8601,
|
29
29
|
title: resource.metadata.title,
|
30
30
|
content_html: Perron::Markdown.render(resource.content)
|
31
31
|
}
|
@@ -43,8 +43,10 @@ module Perron
|
|
43
43
|
.reject { it.metadata.feed == false }
|
44
44
|
.sort_by { it.metadata.published_at || it.metadata.updated_at || Time.current }
|
45
45
|
.reverse
|
46
|
-
.take(
|
46
|
+
.take(feed_configuration.max_items)
|
47
47
|
end
|
48
|
+
|
49
|
+
def feed_configuration = @collection.configuration.feeds.json
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -18,8 +18,8 @@ module Perron
|
|
18
18
|
Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
19
19
|
xml.rss(:version => "2.0", "xmlns:atom" => "http://www.w3.org/2005/Atom") do
|
20
20
|
xml.channel do
|
21
|
-
xml.title @configuration.site_name
|
22
|
-
xml.description @configuration.site_description
|
21
|
+
xml.title feed_configuration.title.presence || @configuration.site_name
|
22
|
+
xml.description feed_configuration.description.presence || @configuration.site_description
|
23
23
|
xml.link @configuration.url
|
24
24
|
xml.generator "Perron (#{Perron::VERSION})"
|
25
25
|
|
@@ -28,7 +28,7 @@ module Perron
|
|
28
28
|
xml.item do
|
29
29
|
xml.guid resource.id
|
30
30
|
xml.link url.polymorphic_url(resource), isPermaLink: true
|
31
|
-
xml.pubDate(
|
31
|
+
xml.pubDate(resource.published_at&.rfc822)
|
32
32
|
xml.title resource.metadata.title
|
33
33
|
xml.description { xml.cdata(Perron::Markdown.render(resource.content)) }
|
34
34
|
end
|
@@ -46,8 +46,10 @@ module Perron
|
|
46
46
|
.reject { it.metadata.feed == false }
|
47
47
|
.sort_by { it.metadata.published_at || it.metadata.updated_at || Time.current }
|
48
48
|
.reverse
|
49
|
-
.take(
|
49
|
+
.take(feed_configuration.max_items)
|
50
50
|
end
|
51
|
+
|
52
|
+
def feed_configuration = @collection.configuration.feeds.rss
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -29,10 +29,12 @@ module Perron
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def save_html(html)
|
32
|
-
|
33
|
-
file_path = directory_path.join("index.html")
|
32
|
+
prefixless_path = @path.delete_prefix("/")
|
34
33
|
|
35
|
-
|
34
|
+
file_path = @output_path.join(prefixless_path)
|
35
|
+
file_path = file_path.join("index.html") if File.extname(prefixless_path).empty?
|
36
|
+
|
37
|
+
FileUtils.mkdir_p(file_path.dirname)
|
36
38
|
File.write(file_path, html)
|
37
39
|
|
38
40
|
print "\e[32m.\e[0m"
|
data/lib/perron/site/builder.rb
CHANGED
data/lib/perron/site.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "perron/site/builder"
|
4
|
-
require "perron/
|
5
|
-
require "perron/
|
6
|
-
require "perron/
|
7
|
-
require "perron/site/data/proxy"
|
4
|
+
require "perron/collection"
|
5
|
+
require "perron/data"
|
6
|
+
require "perron/data/proxy"
|
8
7
|
|
9
8
|
module Perron
|
10
9
|
module Site
|
data/lib/perron/version.rb
CHANGED
data/lib/perron.rb
CHANGED
data/perron.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
|
9
9
|
spec.summary = "Rails-based static site generator"
|
10
10
|
spec.description = "Perron is a Rails-based static site generator that follows Rails conventions. It allows you to create content collections with markdown or ERB, configure SEO metadata, and build production-ready static sites while leveraging your existing Rails knowledge with familiar patterns and minimal configuration."
|
11
|
-
spec.homepage = "https://railsdesigner.com/
|
11
|
+
spec.homepage = "https://perron.railsdesigner.com/"
|
12
12
|
spec.license = "MIT"
|
13
13
|
|
14
14
|
spec.metadata["homepage_uri"] = spec.homepage
|