perron 0.5.0 → 0.6.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 +5 -1
- data/README.md +40 -1
- data/lib/generators/perron/install_generator.rb +7 -0
- data/lib/generators/perron/templates/README.md.tt +30 -0
- data/lib/perron/errors.rb +4 -0
- data/lib/perron/site/builder/public_files.rb +1 -1
- data/lib/perron/site/data.rb +144 -0
- data/lib/perron/site/resource.rb +8 -8
- data/lib/perron/site.rb +1 -0
- data/lib/perron/version.rb +1 -1
- data/perron.gemspec +4 -0
- metadata +45 -2
- data/lib/perron/site/resource/context.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f91a86bc7ff57f28eb58ef9aac6b1d3e94c008a3570df359aca5f5e6b416c7e7
|
4
|
+
data.tar.gz: 53cd0a23ce3fbcd1fe90aa07a26577f34e66be5a8fd018c596498e34c67c5718
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd5f18ac803ece9604f9187047c637e4be0f1ad31fb77bce0d73f97dc633ba60644a4d2638deadc2d2d05e6f5152e8050ecc4823caa1dd2c64d0da487618ee85
|
7
|
+
data.tar.gz: e99ffd6732c726f78f4a5e3f2ce07c571019b43d8028539ea1a5d6ad0d75f52f74d254808e3585f0d0e546b2d453e880f2291b2e088dc8e6fe8e63b496f5990d
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
perron (0.
|
4
|
+
perron (0.6.0)
|
5
|
+
csv
|
6
|
+
json
|
7
|
+
psych
|
5
8
|
rails (>= 7.2.0)
|
6
9
|
|
7
10
|
GEM
|
@@ -86,6 +89,7 @@ GEM
|
|
86
89
|
concurrent-ruby (1.3.5)
|
87
90
|
connection_pool (2.5.3)
|
88
91
|
crass (1.0.6)
|
92
|
+
csv (3.3.5)
|
89
93
|
date (3.4.1)
|
90
94
|
debug (1.11.0)
|
91
95
|
irb (~> 1.10)
|
data/README.md
CHANGED
@@ -89,6 +89,35 @@ bundle add {commonmarker,kramdown,redcarpet}
|
|
89
89
|
```
|
90
90
|
|
91
91
|
|
92
|
+
## Data Files
|
93
|
+
|
94
|
+
Perron can consume structured data from YML, JSON, or CSV files, making them available within your templates.
|
95
|
+
This is useful for populating features, team members, or any other repeated data structure.
|
96
|
+
|
97
|
+
### Usage
|
98
|
+
|
99
|
+
To use a data file, instantiate `Perron::Data` with the basename of the file and iterate over the result.
|
100
|
+
```erb
|
101
|
+
<% Perron::Data.new("features").each do |feature| %>
|
102
|
+
<h4><%= feature.name %></h4>
|
103
|
+
<p><%= feature.description %></p>
|
104
|
+
<% end %>
|
105
|
+
```
|
106
|
+
|
107
|
+
### File Location and Formats
|
108
|
+
|
109
|
+
By default, Perron looks up `app/content/data/` for files with a `.yml`, `.json`, or `.csv` extension.
|
110
|
+
For a `new("features")` call, it would find `features.yml`, `features.json`, or `features.csv`. You can also provide a full, absolute path to any data file.
|
111
|
+
|
112
|
+
### Accessing Data
|
113
|
+
|
114
|
+
The wrapper object provides flexible, read-only access to each record's attributes. Both dot notation and hash-like key access are supported.
|
115
|
+
```ruby
|
116
|
+
feature.name
|
117
|
+
feature[:name]
|
118
|
+
```
|
119
|
+
|
120
|
+
|
92
121
|
## Metatags
|
93
122
|
|
94
123
|
The `meta_tags` helper automatically generates SEO and social sharing meta tags for your pages.
|
@@ -115,7 +144,7 @@ Or exclude certain tags:
|
|
115
144
|
<%= meta_tags except: %w[twitter_card twitter_image] %>
|
116
145
|
```
|
117
146
|
|
118
|
-
###
|
147
|
+
### Priority
|
119
148
|
|
120
149
|
Values are determined with the following precedence, from highest to lowest:
|
121
150
|
|
@@ -172,6 +201,16 @@ RAILS_ENV=production rails perron:build
|
|
172
201
|
This will create your static site in the configured output directory (`output` by default).
|
173
202
|
|
174
203
|
|
204
|
+
## Sites using Perron
|
205
|
+
|
206
|
+
Sites that use Perron.
|
207
|
+
|
208
|
+
### Standalone (as a SSG)
|
209
|
+
- [AppRefresher](https://apprefresher.com)
|
210
|
+
|
211
|
+
### Integrated (part of a Rails app)
|
212
|
+
- [Rails Designers (private community for Rails UI engineers](https://railsdesigners.com)
|
213
|
+
|
175
214
|
## Contributing
|
176
215
|
|
177
216
|
This project uses [Standard](https://github.com/testdouble/standard) for formatting Ruby code. Please run `be standardrb` before submitting pull requests. Run tests with `rails test`.
|
@@ -5,5 +5,12 @@ module Perron
|
|
5
5
|
def copy_initializer
|
6
6
|
template "initializer.rb.tt", "config/initializers/perron.rb"
|
7
7
|
end
|
8
|
+
|
9
|
+
def create_data_directory
|
10
|
+
data_directory = Rails.root.join("app", "views", "content", "data")
|
11
|
+
empty_directory data_directory
|
12
|
+
|
13
|
+
template "README.md.tt", File.join(data_directory, "README.md")
|
14
|
+
end
|
8
15
|
end
|
9
16
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Data
|
2
|
+
|
3
|
+
Perron can consume structured data from YML, JSON, or CSV files, making them available within your templates.
|
4
|
+
This is useful for populating features, team members, or any other repeated data structure.
|
5
|
+
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
To use a data file, instantiate `Perron::Data` with the basename of the file and iterate over the result.
|
10
|
+
```erb
|
11
|
+
<% Perron::Data.new("features").each do |feature| %>
|
12
|
+
<h4><%= feature.name %></h4>
|
13
|
+
|
14
|
+
<p><%= feature.description %></p>
|
15
|
+
<% end %>
|
16
|
+
```
|
17
|
+
|
18
|
+
## File Location and Formats
|
19
|
+
|
20
|
+
By default, Perron looks up `app/content/data/` for files with a `.yml`, `.json`, or `.csv` extension.
|
21
|
+
For a `new("features")` call, it would find `features.yml`, `features.json`, or `features.csv`. You can also provide a full, absolute path to any data file.
|
22
|
+
|
23
|
+
|
24
|
+
## Accessing Data
|
25
|
+
|
26
|
+
The wrapper object provides flexible, read-only access to each record's attributes. Both dot notation and hash-like key access are supported.
|
27
|
+
```ruby
|
28
|
+
feature.name
|
29
|
+
feature[:name]
|
30
|
+
```
|
data/lib/perron/errors.rb
CHANGED
@@ -30,7 +30,7 @@ module Perron
|
|
30
30
|
private
|
31
31
|
|
32
32
|
def paths
|
33
|
-
@paths ||= Dir.glob(
|
33
|
+
@paths ||= Dir.glob(File.join(@public_dir, "*")).reject do |path|
|
34
34
|
Set.new(Perron.configuration.exclude_from_public + %w[. ..]).include?(File.basename(path))
|
35
35
|
end
|
36
36
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "csv"
|
4
|
+
|
5
|
+
module Perron
|
6
|
+
class Data < SimpleDelegator
|
7
|
+
def initialize(identifier)
|
8
|
+
@file_path = path_for(identifier)
|
9
|
+
@records = records
|
10
|
+
|
11
|
+
super(records)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
PARSER_METHODS = {
|
17
|
+
".yml" => :parse_yaml, ".yaml" => :parse_yaml,
|
18
|
+
".json" => :parse_json, ".csv" => :parse_csv
|
19
|
+
}.freeze
|
20
|
+
SUPPORTED_EXTENSIONS = PARSER_METHODS.keys
|
21
|
+
|
22
|
+
def path_for(identifier)
|
23
|
+
path = Pathname.new(identifier)
|
24
|
+
|
25
|
+
return path.to_s if path.file? && path.absolute?
|
26
|
+
|
27
|
+
path = SUPPORTED_EXTENSIONS.lazy.map { Rails.root.join("app", "content", "data").join("#{identifier}#{it}") }.find(&:exist?)
|
28
|
+
path&.to_s or raise Errors::FileNotFoundError, "No data file found for '#{identifier}'"
|
29
|
+
end
|
30
|
+
|
31
|
+
def records
|
32
|
+
content = File.read(@file_path)
|
33
|
+
extension = File.extname(@file_path)
|
34
|
+
parser = PARSER_METHODS.fetch(extension) do
|
35
|
+
raise Errors::UnsupportedDataFormatError, "Unsupported data format: #{extension}"
|
36
|
+
end
|
37
|
+
|
38
|
+
data = send(parser, content)
|
39
|
+
|
40
|
+
unless data.is_a?(Array)
|
41
|
+
raise Errors::DataParseError, "Data in '#{@file_path}' must be an array of objects."
|
42
|
+
end
|
43
|
+
|
44
|
+
data.map { Item.new(it) }
|
45
|
+
rescue Psych::SyntaxError, JSON::ParserError, CSV::MalformedCSVError => error
|
46
|
+
raise Errors::DataParseError, "Failed to parse '#{@file_path}': #{error.message}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_yaml(content)
|
50
|
+
YAML.safe_load(content, permitted_classes: [Symbol], aliases: true)
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse_json(content)
|
54
|
+
JSON.parse(content, symbolize_names: true)
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_csv(content)
|
58
|
+
CSV.new(content, headers: true, header_converters: :symbol).to_a.map(&:to_h)
|
59
|
+
end
|
60
|
+
|
61
|
+
class Item
|
62
|
+
def initialize(attributes)
|
63
|
+
@attributes = attributes.transform_keys(&:to_sym)
|
64
|
+
end
|
65
|
+
|
66
|
+
def [](key) = @attributes[key.to_sym]
|
67
|
+
|
68
|
+
def method_missing(method_name, *arguments, &block)
|
69
|
+
return super if !@attributes.key?(method_name) || arguments.any? || block
|
70
|
+
|
71
|
+
@attributes[method_name]
|
72
|
+
end
|
73
|
+
|
74
|
+
def respond_to_missing?(method_name, include_private = false)
|
75
|
+
@attributes.key?(method_name) || super
|
76
|
+
end
|
77
|
+
end
|
78
|
+
private_constant :Item
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# require "csv"
|
83
|
+
|
84
|
+
# module Perron
|
85
|
+
# class Data
|
86
|
+
# include Enumerable
|
87
|
+
|
88
|
+
# def initialize(resource)
|
89
|
+
# @file_path = path_for(resource)
|
90
|
+
# @data = data
|
91
|
+
# end
|
92
|
+
|
93
|
+
# def each(&block)
|
94
|
+
# @data.each(&block)
|
95
|
+
# end
|
96
|
+
|
97
|
+
# private
|
98
|
+
|
99
|
+
# PARSER_METHODS = {
|
100
|
+
# ".csv" => :parse_csv,
|
101
|
+
# ".json" => :parse_json,
|
102
|
+
# ".yaml" => :parse_yaml,
|
103
|
+
# ".yml" => :parse_yaml
|
104
|
+
# }.freeze
|
105
|
+
# SUPPORTED_EXTENSIONS = PARSER_METHODS.keys.freeze
|
106
|
+
|
107
|
+
# def path_for(identifier)
|
108
|
+
# path = Pathname.new(identifier)
|
109
|
+
|
110
|
+
# return path.to_s if path.file? && path.absolute?
|
111
|
+
|
112
|
+
# found_path = SUPPORTED_EXTENSIONS.lazy.map do |extension|
|
113
|
+
# Rails.root.join("app", "content", "data").join("#{identifier}#{extension}")
|
114
|
+
# end.find(&:exist?)
|
115
|
+
|
116
|
+
# found_path&.to_s or raise Errors::FileNotFoundError, "No data file found for '#{identifier}'"
|
117
|
+
# end
|
118
|
+
|
119
|
+
# def data
|
120
|
+
# content = File.read(@file_path)
|
121
|
+
# extension = File.extname(@file_path)
|
122
|
+
# parser = PARSER_METHODS.fetch(extension) do
|
123
|
+
# raise Errors::UnsupportedDataFormatError, "Unsupported data format: #{extension}"
|
124
|
+
# end
|
125
|
+
|
126
|
+
# raw_data = send(parser, content)
|
127
|
+
|
128
|
+
# unless raw_data.is_a?(Array)
|
129
|
+
# raise Errors::DataParseError, "Data in '#{@file_path}' must be an array of objects."
|
130
|
+
# end
|
131
|
+
|
132
|
+
# struct = Struct.new(*raw_data.first.keys, keyword_init: true)
|
133
|
+
# raw_data.map { struct.new(**it) }
|
134
|
+
# rescue Psych::SyntaxError, JSON::ParserError, CSV::MalformedCSVError => error
|
135
|
+
# raise Errors::DataParseError, "Failed to parse '#{@file_path}': #{error.message}"
|
136
|
+
# end
|
137
|
+
|
138
|
+
# def parse_yaml(content) = YAML.safe_load(content, permitted_classes: [Symbol], aliases: true)
|
139
|
+
|
140
|
+
# def parse_json(content) = JSON.parse(content, symbolize_names: true)
|
141
|
+
|
142
|
+
# def parse_csv(content) = CSV.new(content, headers: true, header_converters: :symbol).to_a.map(&:to_h)
|
143
|
+
# end
|
144
|
+
# end
|
data/lib/perron/site/resource.rb
CHANGED
@@ -4,7 +4,6 @@ require "perron/site/resource/core"
|
|
4
4
|
require "perron/site/resource/class_methods"
|
5
5
|
require "perron/site/resource/publishable"
|
6
6
|
require "perron/site/resource/slug"
|
7
|
-
require "perron/site/resource/context"
|
8
7
|
require "perron/site/resource/separator"
|
9
8
|
|
10
9
|
module Perron
|
@@ -31,11 +30,14 @@ module Perron
|
|
31
30
|
alias_method :to_param, :slug
|
32
31
|
|
33
32
|
def content
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
return Perron::Resource::Separator.new(raw_content).content unless processable?
|
34
|
+
|
35
|
+
::ApplicationController
|
36
|
+
.renderer
|
37
|
+
.render(
|
38
|
+
inline: Perron::Resource::Separator.new(raw_content).content,
|
39
|
+
assigns: {resource: self}
|
40
|
+
)
|
39
41
|
end
|
40
42
|
|
41
43
|
def metadata = Perron::Resource::Separator.new(raw_content).metadata
|
@@ -56,7 +58,5 @@ module Perron
|
|
56
58
|
@file_path.delete_prefix(Perron.configuration.input).parameterize
|
57
59
|
).first(ID_LENGTH)
|
58
60
|
end
|
59
|
-
|
60
|
-
def context = Perron::Resource::Context.new(self)
|
61
61
|
end
|
62
62
|
end
|
data/lib/perron/site.rb
CHANGED
data/lib/perron/version.rb
CHANGED
data/perron.gemspec
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.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rails Designer Developers
|
@@ -23,6 +23,48 @@ dependencies:
|
|
23
23
|
- - ">="
|
24
24
|
- !ruby/object:Gem::Version
|
25
25
|
version: 7.2.0
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: csv
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: json
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: psych
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
26
68
|
description: Perron is a Rails-based static site generator that follows Rails conventions.
|
27
69
|
It allows you to create content collections with markdown or ERB, configure SEO
|
28
70
|
metadata, and build production-ready static sites while leveraging your existing
|
@@ -49,6 +91,7 @@ files:
|
|
49
91
|
- lib/generators/content/templates/root.erb.tt
|
50
92
|
- lib/generators/content/templates/show.html.erb.tt
|
51
93
|
- lib/generators/perron/install_generator.rb
|
94
|
+
- lib/generators/perron/templates/README.md.tt
|
52
95
|
- lib/generators/perron/templates/initializer.rb.tt
|
53
96
|
- lib/perron.rb
|
54
97
|
- lib/perron/configuration.rb
|
@@ -67,9 +110,9 @@ files:
|
|
67
110
|
- lib/perron/site/builder/paths.rb
|
68
111
|
- lib/perron/site/builder/public_files.rb
|
69
112
|
- lib/perron/site/collection.rb
|
113
|
+
- lib/perron/site/data.rb
|
70
114
|
- lib/perron/site/resource.rb
|
71
115
|
- lib/perron/site/resource/class_methods.rb
|
72
|
-
- lib/perron/site/resource/context.rb
|
73
116
|
- lib/perron/site/resource/core.rb
|
74
117
|
- lib/perron/site/resource/publishable.rb
|
75
118
|
- lib/perron/site/resource/separator.rb
|