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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +3 -1
  4. data/README.md +108 -46
  5. data/app/helpers/meta_tags_helper.rb +1 -1
  6. data/lib/generators/content/content_generator.rb +25 -0
  7. data/lib/generators/content/templates/root.erb.tt +0 -1
  8. data/lib/generators/perron/install_generator.rb +6 -1
  9. data/lib/generators/perron/templates/README.md.tt +18 -1
  10. data/lib/generators/perron/templates/initializer.rb.tt +5 -2
  11. data/lib/perron/{site/collection.rb → collection.rb} +8 -2
  12. data/lib/perron/configuration.rb +4 -0
  13. data/lib/perron/{site/data.rb → data.rb} +16 -2
  14. data/lib/perron/feeds.rb +1 -0
  15. data/lib/perron/html_processor/syntax_highlight.rb +30 -0
  16. data/lib/perron/html_processor.rb +12 -8
  17. data/lib/perron/markdown.rb +6 -5
  18. data/lib/perron/metatags.rb +33 -59
  19. data/lib/perron/refinements/delete_suffixes.rb +11 -7
  20. data/lib/perron/{site/resource → resource}/class_methods.rb +5 -1
  21. data/lib/perron/resource/metadata.rb +67 -0
  22. data/lib/perron/{site/resource → resource}/publishable.rb +5 -5
  23. data/lib/perron/{site/resource → resource}/related.rb +2 -1
  24. data/lib/perron/{site/resource → resource}/separator.rb +5 -5
  25. data/lib/perron/resource/slug.rb +27 -0
  26. data/lib/perron/{site/resource.rb → resource.rb} +38 -14
  27. data/lib/perron/root.rb +1 -1
  28. data/lib/perron/site/builder/assets.rb +2 -1
  29. data/lib/perron/site/builder/feeds/json.rb +6 -4
  30. data/lib/perron/site/builder/feeds/rss.rb +6 -4
  31. data/lib/perron/site/builder/feeds.rb +2 -0
  32. data/lib/perron/site/builder/page.rb +5 -3
  33. data/lib/perron/site/builder/sitemap.rb +1 -0
  34. data/lib/perron/site/builder.rb +1 -1
  35. data/lib/perron/site.rb +3 -4
  36. data/lib/perron/version.rb +1 -1
  37. data/lib/perron.rb +1 -0
  38. data/perron.gemspec +1 -1
  39. metadata +18 -16
  40. data/lib/perron/site/resource/slug.rb +0 -24
  41. /data/lib/perron/{site/data → data}/proxy.rb +0 -0
  42. /data/lib/perron/{site/resource → resource}/configuration.rb +0 -0
  43. /data/lib/perron/{site/resource → resource}/core.rb +0 -0
  44. /data/lib/perron/{site/resource → resource}/related/stop_words.rb +0 -0
  45. /data/lib/perron/{site/resource → resource}/renderer.rb +0 -0
@@ -18,7 +18,7 @@ module Perron
18
18
  end
19
19
 
20
20
  def markdown_parser
21
- if defined?(::CommonMarker)
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) = CommonMarker.render_html(text, :DEFAULT)
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
- renderer = Redcarpet::Render::HTML.new(filter_html: true)
44
- markdown = Redcarpet::Markdown.new(renderer, autolink: true, tables: true)
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
@@ -4,9 +4,8 @@ module Perron
4
4
  class Metatags
5
5
  include ActionView::Helpers::TagHelper
6
6
 
7
- def initialize(resource)
8
- @resource = resource
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 ||= begin
30
- frontmatter = @resource&.metadata&.stringify_keys || {}
31
- collection_config = @resource&.collection&.configuration&.metadata || {}
32
- site_config = @config.metadata
33
-
34
- title = frontmatter["title"] || collection_config["title"] || site_config["title"] || @config.site_name || Rails.application.name.underscore.camelize
35
- type = frontmatter["type"] || collection_config["type"] || site_config["type"]
36
- description = frontmatter["description"] || collection_config["description"] || site_config["description"]
37
- logo = frontmatter["logo"] || collection_config["logo"] || site_config["logo"]
38
- author = frontmatter["author"] || collection_config["author"] || site_config["author"]
39
- locale = frontmatter["locale"] || collection_config["locale"] || site_config["locale"]
40
-
41
- image = frontmatter["image"] || collection_config["image"] || site_config["image"]
42
- og_image = frontmatter["og:image"] || collection_config["og:image"] || site_config["og:image"] || image
43
- twitter_image = frontmatter["twitter:image"] || collection_config["twitter:image"] || site_config["twitter:image"] || og_image
44
-
45
- {
46
- title: title_tag(title),
47
- description: meta_tag(name: "description", content: description),
48
- article_published: meta_tag(property: "article:published_time", content: @resource&.published_at),
49
-
50
- og_title: meta_tag(property: "og:title", content: frontmatter["og:title"] || title),
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 = Perron.configuration.metadata.title_suffix&.strip
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(Perron.configuration.metadata.title_separator))
52
+ tag.title([resource_title, suffix].compact.join(config.metadata.title_separator))
76
53
  end
77
54
 
78
- def meta_tag(attributes)
79
- return if attributes[:content].blank?
55
+ def link_tag(attributes)
56
+ return if attributes[:href].blank?
80
57
 
81
- tag.meta(**attributes)
58
+ tag.link(**attributes)
82
59
  end
83
60
 
84
- def canonical_url
85
- url_options = @config.default_url_options
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
- url.then { (url_options[:trailing_slash] && !it.end_with?("/") && !has_extension) ? "#{it}/" : it }
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 SuffixStripping
3
- refine String do
4
- def delete_suffixes(suffixes)
5
- suffixes
6
- .sort_by(&:length)
7
- .reverse_each
8
- .reduce(self, :delete_suffix)
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 Rails.env.development?
10
+ return true if Perron.configuration.view_unpublished
11
11
 
12
- return false if metadata.draft == true
13
- return false if metadata.published == false
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 = metadata.published_at.present? ? begin
24
- Time.zone.parse(metadata.published_at.to_s)
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/site/resource/related/stop_words"
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 metadata
13
- @metadata_with_dot_access ||= ActiveSupport::OrderedOptions.new.tap do |options|
14
- @metadata.each { |key, value| options[key] = value }
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
- @metadata = YAML.safe_load($1, permitted_classes: [Date, Time]) || {}
22
+ @frontmatter = YAML.safe_load($1, permitted_classes: [Date, Time]) || {}
23
23
  @content = $2.strip
24
24
  else
25
- @metadata = {}
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/site/resource/configuration"
4
- require "perron/site/resource/core"
5
- require "perron/site/resource/class_methods"
6
- require "perron/site/resource/publishable"
7
- require "perron/site/resource/related"
8
- require "perron/site/resource/renderer"
9
- require "perron/site/resource/slug"
10
- require "perron/site/resource/separator"
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 metadata = Perron::Resource::Separator.new(raw_content).metadata
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
- def raw_content = File.read(@file_path)
47
- alias_method :raw, :raw_content
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 erb_processing?
57
- @file_path.ends_with?(".erb") || metadata.erb == true
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
@@ -5,7 +5,7 @@ module Perron
5
5
  include ActiveSupport::Concern
6
6
 
7
7
  def root
8
- @resource = Content::Page.find("/")
8
+ @resource = Content::Page.root
9
9
 
10
10
  render :show
11
11
  end
@@ -29,7 +29,8 @@ module Perron
29
29
  end
30
30
 
31
31
  FileUtils.mkdir_p(destination)
32
- FileUtils.cp_r(Dir.glob("#{source}/*"), destination)
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
- description: @configuration.site_description,
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: (resource.metadata.published_at || resource.metadata.updated_at)&.iso8601,
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(@collection.configuration.feeds.json.max_items)
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((resource.metadata.published_at || resource.metadata.updated_at)&.rfc822)
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(@collection.configuration.feeds.rss.max_items)
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
@@ -13,6 +13,8 @@ module Perron
13
13
 
14
14
  def generate
15
15
  Perron::Site.collections.each do |collection|
16
+ next if collection.configuration.blank?
17
+
16
18
  config = collection.configuration.feeds
17
19
 
18
20
  if config.rss.enabled
@@ -29,10 +29,12 @@ module Perron
29
29
  private
30
30
 
31
31
  def save_html(html)
32
- directory_path = @output_path.join(@path.delete_prefix("/"))
33
- file_path = directory_path.join("index.html")
32
+ prefixless_path = @path.delete_prefix("/")
34
33
 
35
- FileUtils.mkdir_p(directory_path)
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"
@@ -25,6 +25,7 @@ module Perron
25
25
  private
26
26
 
27
27
  def add_urls_for(collection, with:)
28
+ return if collection.configuration.blank?
28
29
  return if collection.configuration.sitemap.exclude == true
29
30
 
30
31
  collection.resources.each do |resource|
@@ -39,7 +39,7 @@ module Perron
39
39
  def paths
40
40
  Set.new.tap do |paths|
41
41
  Perron::Site.collections.each { Perron::Site::Builder::Paths.new(it, paths).get }
42
- end.to_a
42
+ end
43
43
  end
44
44
 
45
45
  def render_page(path) = Perron::Site::Builder::Page.new(path).render
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/site/collection"
5
- require "perron/site/resource"
6
- require "perron/site/data"
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
@@ -1,3 +1,3 @@
1
1
  module Perron
2
- VERSION = "0.10.0"
2
+ VERSION = "0.12.0"
3
3
  end
data/lib/perron.rb CHANGED
@@ -5,6 +5,7 @@ require "perron/configuration"
5
5
  require "perron/errors"
6
6
  require "perron/root"
7
7
  require "perron/site"
8
+ require "perron/resource"
8
9
  require "perron/markdown"
9
10
  require "perron/feeds"
10
11
  require "perron/metatags"
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/perron/"
11
+ spec.homepage = "https://perron.railsdesigner.com/"
12
12
  spec.license = "MIT"
13
13
 
14
14
  spec.metadata["homepage_uri"] = spec.homepage