perron 0.9.1 → 0.10.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/README.md +70 -5
- data/app/helpers/perron/erb_helper.rb +9 -0
- data/lib/generators/content/content_generator.rb +2 -0
- data/lib/generators/perron/install_generator.rb +12 -0
- data/lib/generators/perron/templates/initializer.rb.tt +4 -4
- data/lib/perron/configuration.rb +6 -3
- data/lib/perron/site/builder/assets.rb +2 -2
- data/lib/perron/site/builder/page.rb +1 -1
- data/lib/perron/site/builder/public_files.rb +1 -1
- data/lib/perron/site/builder.rb +2 -4
- data/lib/perron/site/data/proxy.rb +35 -5
- data/lib/perron/site/data.rb +22 -14
- data/lib/perron/site/resource/renderer.rb +18 -0
- data/lib/perron/site/resource/slug.rb +5 -1
- data/lib/perron/site/resource.rb +7 -9
- data/lib/perron/site.rb +0 -10
- data/lib/perron/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2aa4c7af63f95aef3bc25c9ef97a4da02d75486ec3ee975f69a980f66cb34557
|
4
|
+
data.tar.gz: f1c62fff6d0ba6c121da85f463dc32fd5656c884d059d0f2955c6a95a4c0bf3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 175ecbdc5dc5468e28e0abe13926b578fb6669d078b594da1dea91ab8cce68c3a7f63f12d3be4f0de757d270c5d3a95ce96db925ea9c3cbe238e1dd72069aaa1
|
7
|
+
data.tar.gz: b65f95000da601c8ea2f6dcea2e1cf9edb907d366ff783b3ba37e4b2c2d0ff0222cf98821f7537690895087c39ad0c902397c6325e309e27019914101072b6df
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -31,7 +31,7 @@ rails generate perron:install
|
|
31
31
|
This creates an initializer:
|
32
32
|
```ruby
|
33
33
|
Perron.configure do |config|
|
34
|
-
config.site_name = "
|
34
|
+
config.site_name = "Helptail"
|
35
35
|
end
|
36
36
|
```
|
37
37
|
|
@@ -131,6 +131,71 @@ end
|
|
131
131
|
```
|
132
132
|
|
133
133
|
|
134
|
+
### Embed Ruby
|
135
|
+
|
136
|
+
Perron provides flexible options for embedding dynamic Ruby code in your content using ERB.
|
137
|
+
|
138
|
+
|
139
|
+
#### 1. File extension
|
140
|
+
|
141
|
+
Any content file with a `.erb` extension (e.g., `about.erb`) will automatically have its content processed as ERB.
|
142
|
+
|
143
|
+
|
144
|
+
#### 2. Frontmatter
|
145
|
+
|
146
|
+
You can enable ERB processing on a per-file basis, even for standard `.md` files, by adding `erb: true` to the file's frontmatter.
|
147
|
+
```markdown
|
148
|
+
---
|
149
|
+
title: Dynamic Page
|
150
|
+
erb: true
|
151
|
+
---
|
152
|
+
|
153
|
+
This entire page will be processed by ERB.
|
154
|
+
The current time is: <%= Time.current.to_fs(:long_ordinal) %>.
|
155
|
+
```
|
156
|
+
|
157
|
+
|
158
|
+
#### 3. `erbify` helper
|
159
|
+
|
160
|
+
For the most granular control, the `erbify` helper allows to process specific sections of a file as ERB.
|
161
|
+
This is ideal for generating dynamic content like lists or tables from your resource's metadata, without needing to enable ERB for the entire file. The `erbify` helper can be used with a string or, more commonly, a block.
|
162
|
+
|
163
|
+
**Example:** Generating a list from frontmatter data in a standard `.md` file.
|
164
|
+
```markdown
|
165
|
+
---
|
166
|
+
title: Features
|
167
|
+
features:
|
168
|
+
- Rails based
|
169
|
+
- SEO friendly
|
170
|
+
- Markdown first
|
171
|
+
- ERB support
|
172
|
+
---
|
173
|
+
|
174
|
+
Check out our amazing features:
|
175
|
+
|
176
|
+
<%= erbify do %>
|
177
|
+
<ul>
|
178
|
+
<% @resource.metadata.features.each do |feature| %>
|
179
|
+
<li>
|
180
|
+
<%= feature %>
|
181
|
+
</li>
|
182
|
+
<% end %>
|
183
|
+
</ul>
|
184
|
+
<% end %>
|
185
|
+
```
|
186
|
+
|
187
|
+
**Result:**
|
188
|
+
```html
|
189
|
+
<p>Check out our amazing features:</p>
|
190
|
+
<ul>
|
191
|
+
<li>Rails based</li>
|
192
|
+
<li>SEO friendly</li>
|
193
|
+
<li>Markdown first</li>
|
194
|
+
<li>ERB support</li>
|
195
|
+
</ul>
|
196
|
+
```
|
197
|
+
|
198
|
+
|
134
199
|
## Data Files
|
135
200
|
|
136
201
|
Perron can consume structured data from YML, JSON, or CSV files, making them available within your templates.
|
@@ -271,8 +336,8 @@ Set site-wide defaults in the initializer:
|
|
271
336
|
class Content::Post < Perron::Resource
|
272
337
|
# …
|
273
338
|
|
274
|
-
config.metadata.description = "
|
275
|
-
config.metadata.author = "
|
339
|
+
config.metadata.description = "Put your routine tasks on autopilot"
|
340
|
+
config.metadata.author = "Helptail team"
|
276
341
|
end
|
277
342
|
```
|
278
343
|
|
@@ -283,8 +348,8 @@ Set site-wide defaults in the initializer:
|
|
283
348
|
Perron.configure do |config|
|
284
349
|
# …
|
285
350
|
|
286
|
-
config.metadata.description = "
|
287
|
-
config.metadata.author = "
|
351
|
+
config.metadata.description = "Put your routine tasks on autopilot"
|
352
|
+
config.metadata.author = "Helptail team"
|
288
353
|
end
|
289
354
|
```
|
290
355
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Perron
|
2
4
|
class InstallGenerator < Rails::Generators::Base
|
3
5
|
source_root File.expand_path("templates", __dir__)
|
@@ -12,5 +14,15 @@ module Perron
|
|
12
14
|
|
13
15
|
template "README.md.tt", File.join(data_directory, "README.md")
|
14
16
|
end
|
17
|
+
|
18
|
+
def add_markdown_gems
|
19
|
+
append_to_file "Gemfile", <<~RUBY
|
20
|
+
|
21
|
+
# Perron can use one of the following gems. Uncomment your preferred choice and run `bundle install`
|
22
|
+
# gem "commonmarker"
|
23
|
+
# gem "kramdown"
|
24
|
+
# gem "redcarpet"
|
25
|
+
RUBY
|
26
|
+
end
|
15
27
|
end
|
16
28
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Perron.configure do |config|
|
2
2
|
# config.output = "output"
|
3
3
|
|
4
|
-
# config.site_name = "
|
4
|
+
# config.site_name = "Helptail"
|
5
5
|
|
6
6
|
# The build mode for Perron. Can be :standalone or :integrated.
|
7
7
|
# config.mode = :standalone
|
@@ -9,12 +9,12 @@ Perron.configure do |config|
|
|
9
9
|
# In `integrated` mode, the root is skipped by default. Set to `true` to enable.
|
10
10
|
# config.include_root = false
|
11
11
|
|
12
|
-
# config.default_url_options = {host: "
|
12
|
+
# config.default_url_options = {host: "helptail.com", protocol: "https", trailing_slash: true}
|
13
13
|
|
14
14
|
# Set default meta values
|
15
15
|
# Examples:
|
16
|
-
# - `config.metadata.description = "
|
17
|
-
# - `config.metadata.author = "
|
16
|
+
# - `config.metadata.description = "Put your routine tasks on autopilot"`
|
17
|
+
# - `config.metadata.author = "Helptail Team"`
|
18
18
|
|
19
19
|
# Set meta title suffix
|
20
20
|
# config.metadata.title_suffix = nil
|
data/lib/perron/configuration.rb
CHANGED
@@ -13,15 +13,18 @@ module Perron
|
|
13
13
|
def initialize
|
14
14
|
@config = ActiveSupport::OrderedOptions.new
|
15
15
|
|
16
|
+
@config.site_name = nil
|
17
|
+
@config.site_description = nil
|
18
|
+
|
19
|
+
@config.site_email = nil
|
20
|
+
|
16
21
|
@config.output = "output"
|
17
22
|
|
18
23
|
@config.mode = :standalone
|
19
24
|
@config.include_root = false
|
20
25
|
|
21
|
-
@config.
|
22
|
-
@config.site_description = nil
|
26
|
+
@config.allowed_extensions = %w[erb md]
|
23
27
|
|
24
|
-
@config.allowed_extensions = [".erb", ".md"]
|
25
28
|
@config.exclude_from_public = %w[assets storage]
|
26
29
|
@config.excluded_assets = %w[action_cable actioncable actiontext activestorage rails-ujs trix turbo]
|
27
30
|
|
@@ -31,7 +31,7 @@ module Perron
|
|
31
31
|
FileUtils.mkdir_p(destination)
|
32
32
|
FileUtils.cp_r(Dir.glob("#{source}/*"), destination)
|
33
33
|
|
34
|
-
puts "
|
34
|
+
puts " Copied assets to `#{destination.relative_path_from(Rails.root)}`"
|
35
35
|
|
36
36
|
prune_excluded_assets from: destination
|
37
37
|
end
|
@@ -41,7 +41,7 @@ module Perron
|
|
41
41
|
def prune_excluded_assets(from:)
|
42
42
|
return if exclusions.empty?
|
43
43
|
|
44
|
-
puts "Pruning excluded assets…"
|
44
|
+
puts " Pruning excluded assets…"
|
45
45
|
|
46
46
|
pattern = /^(#{exclusions.join("|")})(\.esm|\.min)?-[a-f0-9]{8,}/
|
47
47
|
|
data/lib/perron/site/builder.rb
CHANGED
@@ -24,16 +24,14 @@ module Perron
|
|
24
24
|
Perron::Site::Builder::PublicFiles.new.copy
|
25
25
|
end
|
26
26
|
|
27
|
-
puts "
|
28
|
-
puts "-" * 15
|
27
|
+
puts "\n📝 Generating collections…"
|
29
28
|
|
30
29
|
paths.each { render_page(it) }
|
31
30
|
|
32
31
|
Perron::Site::Builder::Sitemap.new(@output_path).generate
|
33
32
|
Perron::Site::Builder::Feeds.new(@output_path).generate
|
34
33
|
|
35
|
-
puts "
|
36
|
-
puts "✅ Build complete"
|
34
|
+
puts "\n✅ Build complete"
|
37
35
|
end
|
38
36
|
|
39
37
|
private
|
@@ -3,14 +3,44 @@
|
|
3
3
|
module Perron
|
4
4
|
class Data
|
5
5
|
class Proxy
|
6
|
-
|
7
|
-
raise ArgumentError, "Data `#{method_name}` does not accept arguments" if arguments.any?
|
6
|
+
include Enumerable
|
8
7
|
|
9
|
-
|
8
|
+
def initialize(parts = [])
|
9
|
+
@parts = parts
|
10
|
+
@data = data_for_proxy
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
13
|
+
def each(&block) = @data.each(&block)
|
14
|
+
|
15
|
+
def inspect = @data.inspect
|
16
|
+
|
17
|
+
def respond_to_missing?(name, include_private = false)
|
18
|
+
identifier = File.join(*@parts, name.to_s)
|
19
|
+
|
20
|
+
Perron::Data.directory?(identifier) || Perron::Data.path_for(identifier) || super
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(name, *arguments, &block)
|
24
|
+
raise ArgumentError, "Data access does not accept arguments" if arguments.any? || block
|
25
|
+
|
26
|
+
new_parts = @parts + [name.to_s]
|
27
|
+
identifier = File.join(*new_parts)
|
28
|
+
|
29
|
+
return Proxy.new(new_parts) if Perron::Data.directory?(identifier)
|
30
|
+
return Perron::Data.new(identifier) if Perron::Data.path_for(identifier)
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def data_for_proxy
|
38
|
+
return [] if @parts.empty?
|
39
|
+
|
40
|
+
identifier = File.join(*@parts)
|
41
|
+
data_path = Perron::Data.path_for(identifier) || Perron::Data.path_for(File.join(identifier, "index"))
|
42
|
+
|
43
|
+
data_path ? Perron::Data.new(data_path) : []
|
14
44
|
end
|
15
45
|
end
|
16
46
|
end
|
data/lib/perron/site/data.rb
CHANGED
@@ -1,19 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "erb"
|
4
|
-
require "singleton"
|
5
|
-
|
6
3
|
require "csv"
|
7
4
|
|
8
5
|
module Perron
|
9
6
|
class Data < SimpleDelegator
|
10
7
|
def initialize(identifier)
|
11
|
-
@file_path = path_for(identifier)
|
8
|
+
@file_path = self.class.path_for!(identifier)
|
12
9
|
@records = records
|
13
10
|
|
14
11
|
super(records)
|
15
12
|
end
|
16
13
|
|
14
|
+
class << self
|
15
|
+
def path_for(identifier)
|
16
|
+
path = Pathname.new(identifier)
|
17
|
+
|
18
|
+
return path.to_s if path.file? && path.absolute?
|
19
|
+
|
20
|
+
base_path = Rails.root.join("app", "content", "data")
|
21
|
+
|
22
|
+
SUPPORTED_EXTENSIONS.lazy.map { base_path.join("#{identifier}#{it}") }.find(&:exist?)&.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def path_for!(identifier)
|
26
|
+
path_for(identifier).tap do |path|
|
27
|
+
raise Errors::FileNotFoundError, "No data file found for `#{identifier}`" unless path
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def directory?(identifier) = Dir.exist?(Rails.root.join("app", "content", "data", identifier))
|
32
|
+
end
|
33
|
+
|
17
34
|
private
|
18
35
|
|
19
36
|
PARSER_METHODS = {
|
@@ -22,21 +39,12 @@ module Perron
|
|
22
39
|
}.freeze
|
23
40
|
SUPPORTED_EXTENSIONS = PARSER_METHODS.keys
|
24
41
|
|
25
|
-
def path_for(identifier)
|
26
|
-
path = Pathname.new(identifier)
|
27
|
-
|
28
|
-
return path.to_s if path.file? && path.absolute?
|
29
|
-
|
30
|
-
path = SUPPORTED_EXTENSIONS.lazy.map { Rails.root.join("app", "content", "data").join("#{identifier}#{it}") }.find(&:exist?)
|
31
|
-
path&.to_s or raise Errors::FileNotFoundError, "No data file found for '#{identifier}'"
|
32
|
-
end
|
33
|
-
|
34
42
|
def records
|
35
43
|
content = rendered_from(@file_path)
|
36
44
|
data = parsed_from(content, @file_path)
|
37
45
|
|
38
46
|
unless data.is_a?(Array)
|
39
|
-
raise Errors::DataParseError, "Data in
|
47
|
+
raise Errors::DataParseError, "Data in `#{@file_path}` must be an array of objects."
|
40
48
|
end
|
41
49
|
|
42
50
|
data.map { Item.new(it) }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perron
|
4
|
+
class Resource
|
5
|
+
module Renderer
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def erb(content, assigns = {})
|
9
|
+
::ApplicationController
|
10
|
+
.renderer
|
11
|
+
.render(
|
12
|
+
inline: content,
|
13
|
+
assigns: assigns
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -13,8 +13,12 @@ module Perron
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def create
|
16
|
-
@metadata.slug.presence || @resource.filename.sub(/^[\d-]+-/, "").delete_suffixes(
|
16
|
+
@metadata.slug.presence || @resource.filename.sub(/^[\d-]+-/, "").delete_suffixes(dot_prepended_allowed_extensions)
|
17
17
|
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def dot_prepended_allowed_extensions = Perron.configuration.allowed_extensions.map { ".#{it}" }
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
data/lib/perron/site/resource.rb
CHANGED
@@ -5,6 +5,7 @@ require "perron/site/resource/core"
|
|
5
5
|
require "perron/site/resource/class_methods"
|
6
6
|
require "perron/site/resource/publishable"
|
7
7
|
require "perron/site/resource/related"
|
8
|
+
require "perron/site/resource/renderer"
|
8
9
|
require "perron/site/resource/slug"
|
9
10
|
require "perron/site/resource/separator"
|
10
11
|
|
@@ -33,14 +34,11 @@ module Perron
|
|
33
34
|
alias_method :to_param, :slug
|
34
35
|
|
35
36
|
def content
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
inline: Perron::Resource::Separator.new(raw_content).content,
|
42
|
-
assigns: {resource: self}
|
43
|
-
)
|
37
|
+
page_content = Perron::Resource::Separator.new(raw_content).content
|
38
|
+
|
39
|
+
return page_content unless erb_processing?
|
40
|
+
|
41
|
+
Perron::Resource::Renderer.erb(page_content, {resource: self})
|
44
42
|
end
|
45
43
|
|
46
44
|
def metadata = Perron::Resource::Separator.new(raw_content).metadata
|
@@ -55,7 +53,7 @@ module Perron
|
|
55
53
|
|
56
54
|
private
|
57
55
|
|
58
|
-
def
|
56
|
+
def erb_processing?
|
59
57
|
@file_path.ends_with?(".erb") || metadata.erb == true
|
60
58
|
end
|
61
59
|
|
data/lib/perron/site.rb
CHANGED
@@ -12,16 +12,6 @@ module Perron
|
|
12
12
|
|
13
13
|
def build = Perron::Site::Builder.new.build
|
14
14
|
|
15
|
-
def name = Perron.configuration.site_name
|
16
|
-
|
17
|
-
def email = Perron.configuration.site_email
|
18
|
-
|
19
|
-
def url
|
20
|
-
options = Perron.configuration.default_url_options
|
21
|
-
|
22
|
-
"#{options[:protocol]}://#{options[:host]}"
|
23
|
-
end
|
24
|
-
|
25
15
|
def collections
|
26
16
|
@collections ||= Dir.children(Perron.configuration.input)
|
27
17
|
.select { File.directory?(File.join(Perron.configuration.input, it)) }
|
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: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rails Designer Developers
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- Rakefile
|
81
81
|
- app/helpers/feeds_helper.rb
|
82
82
|
- app/helpers/meta_tags_helper.rb
|
83
|
+
- app/helpers/perron/erb_helper.rb
|
83
84
|
- app/helpers/perron/markdown_helper.rb
|
84
85
|
- bin/console
|
85
86
|
- bin/rails
|
@@ -127,6 +128,7 @@ files:
|
|
127
128
|
- lib/perron/site/resource/publishable.rb
|
128
129
|
- lib/perron/site/resource/related.rb
|
129
130
|
- lib/perron/site/resource/related/stop_words.rb
|
131
|
+
- lib/perron/site/resource/renderer.rb
|
130
132
|
- lib/perron/site/resource/separator.rb
|
131
133
|
- lib/perron/site/resource/slug.rb
|
132
134
|
- lib/perron/tasks/perron.rake
|