perron 0.15.0 → 0.16.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 +7 -3
- data/lib/perron/configuration.rb +0 -2
- data/lib/perron/content/data.rb +13 -0
- data/lib/perron/data.rb +13 -0
- data/lib/perron/deprecator.rb +7 -0
- data/lib/perron/engine.rb +8 -1
- data/lib/perron/output_server.rb +49 -0
- data/lib/perron/resource/associations.rb +23 -9
- data/lib/perron/resource/previewable.rb +1 -0
- data/lib/perron/resource/sourceable.rb +3 -2
- data/lib/perron/resource.rb +2 -0
- data/lib/perron/site/builder/feeds/author.rb +41 -0
- data/lib/perron/site/builder/feeds/json.rb +12 -0
- data/lib/perron/site/builder/feeds/rss.rb +6 -0
- data/lib/perron/site.rb +2 -0
- data/lib/perron/tasks/clobber.rake +12 -0
- data/lib/perron/version.rb +1 -1
- data/lib/perron.rb +2 -0
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 709c1a304332c522dd7e425824f2718b1a84994db9695b842cddab07fa2a6c2d
|
|
4
|
+
data.tar.gz: cd636faddbff65dd1cc27652fb9141a936ce7df7e5f4fca1e156fd7b1ff27522
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 40df8027fb5974b0670a80b4c61e918da1f3dd7cec833e5fab48cdb606ddb9d9e56480cb69ad3c3033c2fdf1deb09e0c105cb15730cb92581e1d57c3db57ce3f
|
|
7
|
+
data.tar.gz: af0d331538e600ad27d23f9377d6cdabcc1f3142ad7d07de517b002334c0414896edb45d6d0d5d6ab50a6af81be12f4b2bf667c15e8bc50e211a824b6701d1b2
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
perron (0.
|
|
4
|
+
perron (0.16.0)
|
|
5
5
|
csv
|
|
6
6
|
json
|
|
7
7
|
psych
|
|
@@ -120,7 +120,8 @@ GEM
|
|
|
120
120
|
net-smtp
|
|
121
121
|
marcel (1.0.4)
|
|
122
122
|
mini_mime (1.1.5)
|
|
123
|
-
|
|
123
|
+
mini_portile2 (2.8.9)
|
|
124
|
+
minitest (5.27.0)
|
|
124
125
|
net-imap (0.5.9)
|
|
125
126
|
date
|
|
126
127
|
net-protocol
|
|
@@ -131,6 +132,9 @@ GEM
|
|
|
131
132
|
net-smtp (0.5.1)
|
|
132
133
|
net-protocol
|
|
133
134
|
nio4r (2.7.4)
|
|
135
|
+
nokogiri (1.18.8)
|
|
136
|
+
mini_portile2 (~> 2.8.2)
|
|
137
|
+
racc (~> 1.4)
|
|
134
138
|
nokogiri (1.18.8-aarch64-linux-gnu)
|
|
135
139
|
racc (~> 1.4)
|
|
136
140
|
nokogiri (1.18.8-aarch64-linux-musl)
|
|
@@ -244,7 +248,7 @@ GEM
|
|
|
244
248
|
concurrent-ruby (~> 1.0)
|
|
245
249
|
unicode-display_width (3.1.4)
|
|
246
250
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
247
|
-
unicode-emoji (4.0
|
|
251
|
+
unicode-emoji (4.2.0)
|
|
248
252
|
useragent (0.16.11)
|
|
249
253
|
websocket-driver (0.8.0)
|
|
250
254
|
base64
|
data/lib/perron/configuration.rb
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Content
|
|
4
|
+
module Data
|
|
5
|
+
def self.const_missing(name)
|
|
6
|
+
klass = Class.new(Perron::Data) do
|
|
7
|
+
def self.const_missing(nested_name) = const_set(nested_name, Class.new(Perron::Data))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
const_set(name, klass)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/perron/data.rb
CHANGED
|
@@ -13,6 +13,17 @@ module Perron
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
class << self
|
|
16
|
+
def all
|
|
17
|
+
parts = name.to_s.split("::").drop(2)
|
|
18
|
+
identifier = parts.empty? ? name.demodulize.underscore : parts.map(&:underscore).join("/")
|
|
19
|
+
|
|
20
|
+
new(identifier)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def find(id)
|
|
24
|
+
all.find { it[:id] == id || it["id"] == id }
|
|
25
|
+
end
|
|
26
|
+
|
|
16
27
|
def path_for(identifier)
|
|
17
28
|
path = Pathname.new(identifier)
|
|
18
29
|
|
|
@@ -107,6 +118,8 @@ module Perron
|
|
|
107
118
|
|
|
108
119
|
def [](key) = @attributes[key.to_sym]
|
|
109
120
|
|
|
121
|
+
def association_value(key) = self[key]
|
|
122
|
+
|
|
110
123
|
def to_partial_path
|
|
111
124
|
@to_partial_path ||= begin
|
|
112
125
|
identifier = @identifier.to_s
|
data/lib/perron/engine.rb
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "perron/output_server"
|
|
4
|
+
|
|
3
5
|
module Perron
|
|
4
6
|
class Engine < Rails::Engine
|
|
5
7
|
initializer "perron.default_url_options" do |app|
|
|
6
8
|
app.config.action_controller.default_url_options = Perron.configuration.default_url_options
|
|
7
9
|
end
|
|
8
10
|
|
|
11
|
+
initializer "perron.output_server" do |app|
|
|
12
|
+
app.middleware.use Perron::OutputServer
|
|
13
|
+
end
|
|
14
|
+
|
|
9
15
|
rake_tasks do
|
|
10
16
|
load File.expand_path("../tasks/build.rake", __FILE__)
|
|
11
|
-
load File.expand_path("../tasks/
|
|
17
|
+
load File.expand_path("../tasks/clobber.rake", __FILE__)
|
|
12
18
|
load File.expand_path("../tasks/sync_sources.rake", __FILE__)
|
|
19
|
+
load File.expand_path("../tasks/validate.rake", __FILE__)
|
|
13
20
|
end
|
|
14
21
|
end
|
|
15
22
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perron
|
|
4
|
+
class OutputServer
|
|
5
|
+
def initialize(app)
|
|
6
|
+
@app = app
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def call(environment)
|
|
10
|
+
return @app.call(environment) if disabled?
|
|
11
|
+
|
|
12
|
+
static_file(environment).then do |file|
|
|
13
|
+
file ? serve(file) : @app.call(environment)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def disabled? = !enabled?
|
|
20
|
+
|
|
21
|
+
def static_file(environment)
|
|
22
|
+
request_path = Rack::Request.new(environment).path_info
|
|
23
|
+
file_path = File.join(output_path, request_path, "index.html")
|
|
24
|
+
|
|
25
|
+
File.file?(file_path) ? file_path : nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def serve(file_path)
|
|
29
|
+
content = File.read(file_path)
|
|
30
|
+
|
|
31
|
+
[
|
|
32
|
+
200,
|
|
33
|
+
|
|
34
|
+
{
|
|
35
|
+
"Content-Type" => "text/html; charset=utf-8",
|
|
36
|
+
"Content-Length" => content.bytesize.to_s
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
[content]
|
|
40
|
+
]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def enabled? = Dir.exist?(output_path)
|
|
44
|
+
|
|
45
|
+
def output_path
|
|
46
|
+
@output_path ||= Rails.root.join(Perron.configuration.output)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -22,11 +22,11 @@ module Perron
|
|
|
22
22
|
define_method(association_name) do
|
|
23
23
|
cache_has_many_association(association_name) do
|
|
24
24
|
associated_class = association_class_for(association_name, singularize: true, **options)
|
|
25
|
-
|
|
26
|
-
primary_key_method = options.fetch(:primary_key, :slug)
|
|
27
|
-
lookup_value = public_send(primary_key_method)
|
|
25
|
+
ids_key = "#{association_name}_ids"
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
metadata[ids_key] ?
|
|
28
|
+
records_for_ids(associated_class, metadata[ids_key]) :
|
|
29
|
+
records_for_foreign_key(associated_class, association_name, **options)
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
end
|
|
@@ -41,6 +41,10 @@ module Perron
|
|
|
41
41
|
@belongs_to_cache[name] = yield
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
+
def foreign_key_for(base_name, **options)
|
|
45
|
+
(options[:foreign_key] || "#{base_name}_id").to_s
|
|
46
|
+
end
|
|
47
|
+
|
|
44
48
|
def cache_has_many_association(name)
|
|
45
49
|
@has_many_cache ||= {}
|
|
46
50
|
return @has_many_cache[name] if @has_many_cache.key?(name)
|
|
@@ -49,18 +53,28 @@ module Perron
|
|
|
49
53
|
end
|
|
50
54
|
|
|
51
55
|
def association_class_for(association_name, singularize: false, **options)
|
|
52
|
-
|
|
56
|
+
if options[:class_name]
|
|
57
|
+
options[:class_name].to_s.constantize
|
|
58
|
+
else
|
|
53
59
|
name = association_name.to_s
|
|
54
60
|
name = name.singularize if singularize
|
|
55
61
|
|
|
56
|
-
"Content::#{name.classify}"
|
|
62
|
+
"Content::#{name.classify}".constantize
|
|
57
63
|
end
|
|
64
|
+
end
|
|
58
65
|
|
|
59
|
-
|
|
66
|
+
def records_for_ids(associated_class, ids)
|
|
67
|
+
ids = Array(ids)
|
|
68
|
+
|
|
69
|
+
associated_class.all.select { ids.include?(it[:id]) || ids.include?(it["id"]) }
|
|
60
70
|
end
|
|
61
71
|
|
|
62
|
-
def
|
|
63
|
-
|
|
72
|
+
def records_for_foreign_key(associated_class, association_name, **options)
|
|
73
|
+
foreign_key = foreign_key_for(inverse_association_name, **options)
|
|
74
|
+
primary_key_method = options.fetch(:primary_key, :slug)
|
|
75
|
+
lookup_value = public_send(primary_key_method)
|
|
76
|
+
|
|
77
|
+
associated_class.all.select { it.association_value(foreign_key) == lookup_value }
|
|
64
78
|
end
|
|
65
79
|
|
|
66
80
|
def inverse_association_name = self.class.name.demodulize.underscore
|
|
@@ -40,7 +40,7 @@ module Perron
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def combinations
|
|
43
|
-
datasets = source_names.map { Perron::
|
|
43
|
+
datasets = source_names.map { Perron::Data.new(it.to_s) }
|
|
44
44
|
|
|
45
45
|
datasets.first.product(*datasets[1..])
|
|
46
46
|
end
|
|
@@ -71,7 +71,8 @@ module Perron
|
|
|
71
71
|
primary_key = options[:primary_key]
|
|
72
72
|
singular_name = name.to_s.singularize
|
|
73
73
|
identifier = frontmatter["#{singular_name}_#{primary_key}"]
|
|
74
|
-
|
|
74
|
+
|
|
75
|
+
hash[name] = Perron::Data.new(name.to_s).find { it.public_send(primary_key).to_s == identifier.to_s }
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
Source.new(data)
|
data/lib/perron/resource.rb
CHANGED
|
@@ -66,6 +66,8 @@ module Perron
|
|
|
66
66
|
render_inline_erb using: page_content
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
def association_value(key) = metadata[key]
|
|
70
|
+
|
|
69
71
|
def to_partial_path
|
|
70
72
|
@to_partial_path ||= begin
|
|
71
73
|
element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(self.class.model_name))
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perron
|
|
4
|
+
module Site
|
|
5
|
+
class Builder
|
|
6
|
+
class Feeds
|
|
7
|
+
module Author
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def author(resource)
|
|
11
|
+
author = resource.author || feed_configuration.author
|
|
12
|
+
|
|
13
|
+
Author.new(author) if author
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class Author
|
|
17
|
+
def initialize(author)
|
|
18
|
+
@author = author
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def name
|
|
22
|
+
@author.respond_to?(:metadata) ? @author.metadata.name : @author[:name]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def email
|
|
26
|
+
@author.respond_to?(:metadata) ? @author.metadata.email : @author[:email]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def url
|
|
30
|
+
@author.respond_to?(:metadata) ? @author.metadata.url : @author[:url]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def avatar
|
|
34
|
+
@author.respond_to?(:metadata) ? @author.metadata.avatar : @author[:avatar]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "json"
|
|
4
|
+
require "perron/site/builder/feeds/author"
|
|
4
5
|
|
|
5
6
|
module Perron
|
|
6
7
|
module Site
|
|
7
8
|
class Builder
|
|
8
9
|
class Feeds
|
|
9
10
|
class Json
|
|
11
|
+
include Feeds::Author
|
|
12
|
+
|
|
10
13
|
def initialize(collection:)
|
|
11
14
|
@collection = collection
|
|
12
15
|
@configuration = Perron.configuration
|
|
@@ -27,6 +30,7 @@ module Perron
|
|
|
27
30
|
id: resource.id,
|
|
28
31
|
url: url.polymorphic_url(resource, ref: feed_configuration.ref).delete_suffix("?ref="),
|
|
29
32
|
date_published: resource.published_at&.iso8601,
|
|
33
|
+
authors: authors(resource),
|
|
30
34
|
title: resource.metadata.title,
|
|
31
35
|
content_html: Perron::Markdown.render(resource.content)
|
|
32
36
|
}
|
|
@@ -48,6 +52,14 @@ module Perron
|
|
|
48
52
|
end
|
|
49
53
|
|
|
50
54
|
def feed_configuration = @collection.configuration.feeds.json
|
|
55
|
+
|
|
56
|
+
def authors(resource)
|
|
57
|
+
author = author(resource)
|
|
58
|
+
|
|
59
|
+
return nil unless author&.name
|
|
60
|
+
|
|
61
|
+
[{name: author.name, email: author.email, url: author.url, avatar: author.avatar}.compact].presence
|
|
62
|
+
end
|
|
51
63
|
end
|
|
52
64
|
end
|
|
53
65
|
end
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "nokogiri"
|
|
4
|
+
require "perron/site/builder/feeds/author"
|
|
4
5
|
|
|
5
6
|
module Perron
|
|
6
7
|
module Site
|
|
7
8
|
class Builder
|
|
8
9
|
class Feeds
|
|
9
10
|
class Rss
|
|
11
|
+
include Feeds::Author
|
|
12
|
+
|
|
10
13
|
def initialize(collection:)
|
|
11
14
|
@collection = collection
|
|
12
15
|
@configuration = Perron.configuration
|
|
@@ -29,6 +32,9 @@ module Perron
|
|
|
29
32
|
xml.guid resource.id
|
|
30
33
|
xml.link url.polymorphic_url(resource, ref: feed_configuration.ref).delete_suffix("?ref="), isPermaLink: true
|
|
31
34
|
xml.pubDate(resource.published_at&.rfc822)
|
|
35
|
+
if (author = author(resource)) && author.email
|
|
36
|
+
xml.author author.name ? "#{author.email} (#{author.name})" : author.email
|
|
37
|
+
end
|
|
32
38
|
xml.title resource.metadata.title
|
|
33
39
|
xml.description { xml.cdata(Perron::Markdown.render(resource.content)) }
|
|
34
40
|
end
|
data/lib/perron/site.rb
CHANGED
|
@@ -24,6 +24,8 @@ module Perron
|
|
|
24
24
|
def collection(name) = Collection.new(name)
|
|
25
25
|
|
|
26
26
|
def data(name = nil)
|
|
27
|
+
Perron.deprecator.deprecation_warning(:data, "Use Content::Data::ClassName instead, e.g. `Content::Data::Users.all`")
|
|
28
|
+
|
|
27
29
|
(name && Perron::Data.new(name)) || Perron::Data::Proxy.new
|
|
28
30
|
end
|
|
29
31
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
namespace :perron do
|
|
2
|
+
desc "Remove compiled static output"
|
|
3
|
+
task clobber: :environment do
|
|
4
|
+
output_path = Rails.root.join(Perron.configuration.output)
|
|
5
|
+
|
|
6
|
+
if Dir.exist?(output_path)
|
|
7
|
+
FileUtils.rm_rf(output_path)
|
|
8
|
+
|
|
9
|
+
puts "Removed #{output_path}"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/perron/version.rb
CHANGED
data/lib/perron.rb
CHANGED
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "perron/version"
|
|
4
4
|
require "perron/configuration"
|
|
5
|
+
require "perron/deprecator"
|
|
5
6
|
require "perron/errors"
|
|
6
7
|
require "perron/root"
|
|
7
8
|
require "perron/site"
|
|
9
|
+
require "perron/content/data"
|
|
8
10
|
require "perron/resource"
|
|
9
11
|
require "perron/markdown"
|
|
10
12
|
require "perron/feeds"
|
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: 0.
|
|
4
|
+
version: 0.16.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Designer Developers
|
|
@@ -99,8 +99,10 @@ files:
|
|
|
99
99
|
- lib/perron.rb
|
|
100
100
|
- lib/perron/collection.rb
|
|
101
101
|
- lib/perron/configuration.rb
|
|
102
|
+
- lib/perron/content/data.rb
|
|
102
103
|
- lib/perron/data.rb
|
|
103
104
|
- lib/perron/data/proxy.rb
|
|
105
|
+
- lib/perron/deprecator.rb
|
|
104
106
|
- lib/perron/engine.rb
|
|
105
107
|
- lib/perron/errors.rb
|
|
106
108
|
- lib/perron/feeds.rb
|
|
@@ -111,6 +113,7 @@ files:
|
|
|
111
113
|
- lib/perron/html_processor/target_blank.rb
|
|
112
114
|
- lib/perron/markdown.rb
|
|
113
115
|
- lib/perron/metatags.rb
|
|
116
|
+
- lib/perron/output_server.rb
|
|
114
117
|
- lib/perron/refinements/delete_suffixes.rb
|
|
115
118
|
- lib/perron/resource.rb
|
|
116
119
|
- lib/perron/resource/associations.rb
|
|
@@ -133,6 +136,7 @@ files:
|
|
|
133
136
|
- lib/perron/site/builder.rb
|
|
134
137
|
- lib/perron/site/builder/assets.rb
|
|
135
138
|
- lib/perron/site/builder/feeds.rb
|
|
139
|
+
- lib/perron/site/builder/feeds/author.rb
|
|
136
140
|
- lib/perron/site/builder/feeds/json.rb
|
|
137
141
|
- lib/perron/site/builder/feeds/rss.rb
|
|
138
142
|
- lib/perron/site/builder/page.rb
|
|
@@ -141,6 +145,7 @@ files:
|
|
|
141
145
|
- lib/perron/site/builder/sitemap.rb
|
|
142
146
|
- lib/perron/site/validate.rb
|
|
143
147
|
- lib/perron/tasks/build.rake
|
|
148
|
+
- lib/perron/tasks/clobber.rake
|
|
144
149
|
- lib/perron/tasks/sync_sources.rake
|
|
145
150
|
- lib/perron/tasks/validate.rake
|
|
146
151
|
- lib/perron/version.rb
|
|
@@ -165,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
165
170
|
- !ruby/object:Gem::Version
|
|
166
171
|
version: '0'
|
|
167
172
|
requirements: []
|
|
168
|
-
rubygems_version: 4.0.
|
|
173
|
+
rubygems_version: 4.0.3
|
|
169
174
|
specification_version: 4
|
|
170
175
|
summary: Rails-based static site generator
|
|
171
176
|
test_files: []
|