perron 0.7.0 → 0.9.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 +166 -7
- data/app/helpers/feeds_helper.rb +5 -0
- data/app/helpers/meta_tags_helper.rb +4 -6
- data/app/helpers/perron/markdown_helper.rb +5 -1
- data/lib/generators/perron/install_generator.rb +1 -1
- data/lib/generators/perron/templates/README.md.tt +16 -6
- data/lib/perron/configuration.rb +14 -5
- data/lib/perron/errors.rb +4 -0
- data/lib/perron/feeds.rb +38 -0
- data/lib/perron/html_processor/base.rb +15 -0
- data/lib/perron/html_processor/lazy_load_images.rb +13 -0
- data/lib/perron/html_processor/target_blank.rb +4 -8
- data/lib/perron/html_processor.rb +30 -8
- data/lib/perron/markdown.rb +2 -2
- data/lib/perron/metatags.rb +21 -13
- data/lib/perron/site/builder/feeds/json.rb +52 -0
- data/lib/perron/site/builder/feeds/rss.rb +55 -0
- data/lib/perron/site/builder/feeds.rb +41 -0
- data/lib/perron/site/builder/sitemap.rb +54 -0
- data/lib/perron/site/builder.rb +6 -0
- data/lib/perron/site/collection.rb +6 -1
- data/lib/perron/site/data/proxy.rb +17 -0
- data/lib/perron/site/data.rb +39 -73
- data/lib/perron/site/resource/configuration.rb +58 -0
- data/lib/perron/site/resource/related/stop_words.rb +34 -0
- data/lib/perron/site/resource/related.rb +99 -0
- data/lib/perron/site/resource.rb +7 -1
- data/lib/perron/site.rb +4 -2
- data/lib/perron/version.rb +1 -1
- data/lib/perron.rb +1 -0
- data/perron.gemspec +1 -1
- metadata +16 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f225e6b75be66a9fd394e0c87b3c63c878042664e3acfeaa7ff68cc449af1b1
|
4
|
+
data.tar.gz: a963c546505ffa227310b7e0d8cba7a40446d0a70b86b8491f7baa761bf6e0cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f9926aba1d4c88204131fc61564173334a059bcc832c7457f0c31a276b1e05d1466c196afc8a25f54091402436618bee7ae97c6397fdb0660a1da50dbb80231
|
7
|
+
data.tar.gz: 54f74446e210fb7ac299b0dc5496bcce18676128fdf9af994403513f8f4ddff37aee8933e58cc5d4e3cbf7316667b0b19860863ddaec6da78ca79c9ac81d3fd6
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -17,11 +17,17 @@ A Rails-based static site generator.
|
|
17
17
|
|
18
18
|
### Installation
|
19
19
|
|
20
|
-
Start by
|
20
|
+
Start by adding Perron:
|
21
|
+
```bash
|
22
|
+
bundle add perron
|
23
|
+
```
|
24
|
+
|
25
|
+
Then generate the initializer:
|
21
26
|
```bash
|
22
27
|
rails generate perron:install
|
23
28
|
```
|
24
29
|
|
30
|
+
|
25
31
|
This creates an initializer:
|
26
32
|
```ruby
|
27
33
|
Perron.configure do |config|
|
@@ -85,6 +91,46 @@ bundle add {commonmarker,kramdown,redcarpet}
|
|
85
91
|
```
|
86
92
|
|
87
93
|
|
94
|
+
## HTML Transformations
|
95
|
+
|
96
|
+
Perron can post-process the HTML generated from your Markdown content.
|
97
|
+
|
98
|
+
|
99
|
+
### Usage
|
100
|
+
|
101
|
+
Apply transformations by passing an array of processor names or classes to the `markdownify` helper via the `process` option.
|
102
|
+
```erb
|
103
|
+
<%= markdownify @resource.content, process: %w[target_blank lazy_load_images] %>
|
104
|
+
```
|
105
|
+
|
106
|
+
|
107
|
+
### Available Processors
|
108
|
+
|
109
|
+
The following processors are built-in and can be activated by passing their string name:
|
110
|
+
|
111
|
+
- `target_blank`: Adds `target="_blank"` to all external links;
|
112
|
+
- `lazy_load_images`: Adds `loading="lazy"` to all `<img>` tags.
|
113
|
+
|
114
|
+
|
115
|
+
### Creating Your Own
|
116
|
+
|
117
|
+
You can create your own processor by defining a class that inherits from `Perron::HtmlProcessor::Base` and implements a `process` method.
|
118
|
+
Then, pass the class constant directly in the `process` array.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
# app/processors/add_nofollow_processor.rb
|
122
|
+
class AddNofollowProcessor < Perron::HtmlProcessor::Base
|
123
|
+
def process
|
124
|
+
@html.css("a[target=_blank]").each { it["rel"] = "nofollow" }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
```erb
|
130
|
+
<%= markdownify @resource.content, process: ["target_blank", AddNofollowProcessor] %>
|
131
|
+
```
|
132
|
+
|
133
|
+
|
88
134
|
## Data Files
|
89
135
|
|
90
136
|
Perron can consume structured data from YML, JSON, or CSV files, making them available within your templates.
|
@@ -92,9 +138,9 @@ This is useful for populating features, team members, or any other repeated data
|
|
92
138
|
|
93
139
|
### Usage
|
94
140
|
|
95
|
-
To use a data file, instantiate `Perron::
|
141
|
+
To use a data file, instantiate `Perron::Site.data` with the basename of the file and iterate over the result.
|
96
142
|
```erb
|
97
|
-
<% Perron::
|
143
|
+
<% Perron::Site.data.features.each do |feature| %>
|
98
144
|
<h4><%= feature.name %></h4>
|
99
145
|
<p><%= feature.description %></p>
|
100
146
|
<% end %>
|
@@ -103,7 +149,7 @@ To use a data file, instantiate `Perron::Data` with the basename of the file and
|
|
103
149
|
### File Location and Formats
|
104
150
|
|
105
151
|
By default, Perron looks up `app/content/data/` for files with a `.yml`, `.json`, or `.csv` extension.
|
106
|
-
For a `
|
152
|
+
For a `features` call, it would find `features.yml`, `features.json`, or `features.csv`. You can also provide a path to any data file, via `Perron::Data.new("path/to/data.json")`.
|
107
153
|
|
108
154
|
### Accessing Data
|
109
155
|
|
@@ -114,11 +160,55 @@ feature[:name]
|
|
114
160
|
```
|
115
161
|
|
116
162
|
|
163
|
+
## Feeds
|
164
|
+
|
165
|
+
The `feeds` helper automatically generates HTML `<link>` tags for your site's RSS and JSON feeds.
|
166
|
+
|
167
|
+
|
168
|
+
### Usage
|
169
|
+
|
170
|
+
In your layout (e.g., `app/views/layouts/application.html.erb`), add the helper to the `<head>` section:
|
171
|
+
```erb
|
172
|
+
<head>
|
173
|
+
…
|
174
|
+
<%= feeds %>
|
175
|
+
…
|
176
|
+
</head>
|
177
|
+
```
|
178
|
+
|
179
|
+
To render feeds for specific collections, such as `posts`:
|
180
|
+
```erb
|
181
|
+
<%= feeds only: %w[posts] %>
|
182
|
+
```
|
183
|
+
|
184
|
+
Similarly, you can exclude collections:
|
185
|
+
```erb
|
186
|
+
<%= feeds except: %w[pages] %>
|
187
|
+
```
|
188
|
+
|
189
|
+
|
190
|
+
### Configuration
|
191
|
+
|
192
|
+
Feeds are configured within the `Resource` class corresponding to a collection:
|
193
|
+
```ruby
|
194
|
+
# app/models/content/post.rb
|
195
|
+
class Content::Post < Perron::Resource
|
196
|
+
configure do |config|
|
197
|
+
config.feeds.rss.enabled = true
|
198
|
+
# config.feeds.rss.path = "path-to-feed.xml"
|
199
|
+
# config.feeds.rss.max_items = 25
|
200
|
+
config.feeds.json.enabled = true
|
201
|
+
# config.feeds.json.max_items = 15
|
202
|
+
# config.feeds.json.path = "path-to-feed.json"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
```
|
206
|
+
|
207
|
+
|
117
208
|
## Metatags
|
118
209
|
|
119
210
|
The `meta_tags` helper automatically generates SEO and social sharing meta tags for your pages.
|
120
211
|
|
121
|
-
|
122
212
|
### Usage
|
123
213
|
|
124
214
|
In your layout (e.g., `app/views/layouts/application.html.erb`), add the helper to the `<head>` section:
|
@@ -174,7 +264,19 @@ author: Kendall
|
|
174
264
|
Your content here…
|
175
265
|
```
|
176
266
|
|
177
|
-
#### 3.
|
267
|
+
#### 3. Collection configuration
|
268
|
+
|
269
|
+
Set site-wide defaults in the initializer:
|
270
|
+
```ruby
|
271
|
+
class Content::Post < Perron::Resource
|
272
|
+
# …
|
273
|
+
|
274
|
+
config.metadata.description = "AI-powered tool to keep your knowledge base articles images/screenshots and content up-to-date"
|
275
|
+
config.metadata.author = "Rails Designer"
|
276
|
+
end
|
277
|
+
```
|
278
|
+
|
279
|
+
#### 4. Default Values
|
178
280
|
|
179
281
|
Set site-wide defaults in the initializer:
|
180
282
|
```ruby
|
@@ -187,6 +289,61 @@ end
|
|
187
289
|
```
|
188
290
|
|
189
291
|
|
292
|
+
## Related Resources
|
293
|
+
|
294
|
+
The `related_resources` method allows to find and display a list of similar resources
|
295
|
+
from the same collection. Similarity is calculated using the **TF-IDF** algorithm on the content of each resource.
|
296
|
+
|
297
|
+
|
298
|
+
### Basic Usage
|
299
|
+
|
300
|
+
To get a list of the 5 most similar resources, call the method on any resource instance.
|
301
|
+
```ruby
|
302
|
+
# app/views/content/posts/show.html.erb
|
303
|
+
@resource.related_resources
|
304
|
+
|
305
|
+
# Just the 3 most similar resources
|
306
|
+
@resource.related_resources(limit: 3)
|
307
|
+
```
|
308
|
+
|
309
|
+
|
310
|
+
## XML Sitemap
|
311
|
+
|
312
|
+
A sitemap is an XML file that lists all the pages of a website to help search engines discover and index content more efficiently, typically containing URLs, last modification dates, change frequency, and priority values.
|
313
|
+
|
314
|
+
Enable it with the following line in the Perron configuration:
|
315
|
+
```ruby
|
316
|
+
Perron.configure do |config|
|
317
|
+
# …
|
318
|
+
config.sitemap.enabled = true
|
319
|
+
# config.sitemap.priority = 0.8
|
320
|
+
# config.sitemap.change_frequency = :monthly
|
321
|
+
# …
|
322
|
+
end
|
323
|
+
```
|
324
|
+
|
325
|
+
Values can be overridden per collection…
|
326
|
+
```ruby
|
327
|
+
# app/models/content/post.rb
|
328
|
+
class Content::Post < Perron::Resource
|
329
|
+
configure do |config|
|
330
|
+
config.sitemap.enabled = false
|
331
|
+
config.sitemap.priority = 0.5
|
332
|
+
config.sitemap.change_frequency = :weekly
|
333
|
+
end
|
334
|
+
end
|
335
|
+
```
|
336
|
+
|
337
|
+
…or on a resource basis:
|
338
|
+
```ruby
|
339
|
+
# app/content/posts/my-first-post.md
|
340
|
+
---
|
341
|
+
sitemap_priority: 0.25
|
342
|
+
sitemap_change_frequency: :daily
|
343
|
+
---
|
344
|
+
```
|
345
|
+
|
346
|
+
|
190
347
|
## Building Your Static Site
|
191
348
|
|
192
349
|
When in `standalone` mode and you're ready to generate your static site, run:
|
@@ -203,9 +360,11 @@ Sites that use Perron.
|
|
203
360
|
|
204
361
|
### Standalone (as a SSG)
|
205
362
|
- [AppRefresher](https://apprefresher.com)
|
363
|
+
- [Helptail](https://helptail.com)
|
206
364
|
|
207
365
|
### Integrated (part of a Rails app)
|
208
|
-
- [Rails Designers (private community for Rails UI engineers](https://railsdesigners.com)
|
366
|
+
- [Rails Designers (private community for Rails UI engineers)](https://railsdesigners.com)
|
367
|
+
|
209
368
|
|
210
369
|
## Contributing
|
211
370
|
|
@@ -1,17 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module MetaTagsHelper
|
4
|
-
def meta_tags(options = {})
|
5
|
-
Perron::Metatags.new(source).render(options)
|
6
|
-
end
|
4
|
+
def meta_tags(options = {}) = Perron::Metatags.new(resource).render(options)
|
7
5
|
|
8
6
|
private
|
9
7
|
|
10
|
-
|
8
|
+
Resource = Data.define(:path, :metadata, :published_at)
|
11
9
|
|
12
|
-
def
|
10
|
+
def resource
|
13
11
|
return Source.new(request.path, @metadata, nil) if @metadata.present?
|
14
12
|
|
15
|
-
@resource ||
|
13
|
+
@resource || Resource.new(request.path, {}, nil)
|
16
14
|
end
|
17
15
|
end
|
@@ -4,6 +4,10 @@ require "perron/markdown"
|
|
4
4
|
|
5
5
|
module Perron
|
6
6
|
module MarkdownHelper
|
7
|
-
def markdownify(content = nil,
|
7
|
+
def markdownify(content = nil, options = {}, &block)
|
8
|
+
processors = options.fetch(:process, [])
|
9
|
+
|
10
|
+
Perron::Markdown.render(content || capture(&block).strip_heredoc, processors: processors)
|
11
|
+
end
|
8
12
|
end
|
9
13
|
end
|
@@ -7,7 +7,7 @@ module Perron
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def create_data_directory
|
10
|
-
data_directory = Rails.root.join("app", "
|
10
|
+
data_directory = Rails.root.join("app", "content", "data")
|
11
11
|
empty_directory data_directory
|
12
12
|
|
13
13
|
template "README.md.tt", File.join(data_directory, "README.md")
|
@@ -6,19 +6,29 @@ This is useful for populating features, team members, or any other repeated data
|
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
|
-
To use a data file,
|
9
|
+
To use a data file, you can access it through the `Perron::Site.data` object followed by the basename of the file:
|
10
10
|
```erb
|
11
|
-
|
12
|
-
<h4
|
11
|
+
<%% Perron::Site.data.features.each do |feature| %>
|
12
|
+
<h4><%%= feature.name %></h4>
|
13
13
|
|
14
|
-
<p
|
15
|
-
|
14
|
+
<p><%%= feature.description %></p>
|
15
|
+
<%% end %>
|
16
16
|
```
|
17
17
|
|
18
|
+
This is a convenient shorthand for `Perron::Data.new("features")`, which can also be used directly:
|
19
|
+
```ruby
|
20
|
+
<%% Perron::Data.new("features").each do |feature| %>
|
21
|
+
<h4><%%= feature.name %></h4>
|
22
|
+
|
23
|
+
<p><%%= feature.description %></p>
|
24
|
+
<%% end %>
|
25
|
+
```
|
26
|
+
|
27
|
+
|
18
28
|
## File Location and Formats
|
19
29
|
|
20
30
|
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.
|
31
|
+
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, like `Perron::Data.new("path-to-some-data-file")`.
|
22
32
|
|
23
33
|
|
24
34
|
## Accessing Data
|
data/lib/perron/configuration.rb
CHANGED
@@ -9,10 +9,6 @@ module Perron
|
|
9
9
|
yield(configuration)
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.reset_configuration!
|
13
|
-
@configuration = Configuration.new
|
14
|
-
end
|
15
|
-
|
16
12
|
class Configuration
|
17
13
|
def initialize
|
18
14
|
@config = ActiveSupport::OrderedOptions.new
|
@@ -23,6 +19,7 @@ module Perron
|
|
23
19
|
@config.include_root = false
|
24
20
|
|
25
21
|
@config.site_name = nil
|
22
|
+
@config.site_description = nil
|
26
23
|
|
27
24
|
@config.allowed_extensions = [".erb", ".md"]
|
28
25
|
@config.exclude_from_public = %w[assets storage]
|
@@ -34,11 +31,16 @@ module Perron
|
|
34
31
|
trailing_slash: ENV.fetch("PERRON_TRAILING_SLASH", "true") == "true"
|
35
32
|
}
|
36
33
|
|
34
|
+
@config.sitemap = ActiveSupport::OrderedOptions.new
|
35
|
+
@config.sitemap.enabled = false
|
36
|
+
@config.sitemap.priority = 0.5
|
37
|
+
@config.sitemap.change_frequency = :monthly
|
38
|
+
|
37
39
|
@config.metadata = ActiveSupport::OrderedOptions.new
|
38
40
|
@config.metadata.title_separator = " — "
|
39
41
|
end
|
40
42
|
|
41
|
-
def input = "app
|
43
|
+
def input = Rails.root.join("app", "content")
|
42
44
|
|
43
45
|
def output
|
44
46
|
mode.integrated? ? "public" : @config.output
|
@@ -48,6 +50,13 @@ module Perron
|
|
48
50
|
|
49
51
|
def exclude_root? = !@config.include_root
|
50
52
|
|
53
|
+
def url
|
54
|
+
options = Perron.configuration.default_url_options
|
55
|
+
path = options[:trailing_slash] ? "/" : ""
|
56
|
+
|
57
|
+
URI.join("#{options[:protocol]}://#{options[:host]}", path).to_s
|
58
|
+
end
|
59
|
+
|
51
60
|
def method_missing(method_name, ...)
|
52
61
|
if @config.respond_to?(method_name)
|
53
62
|
@config.send(method_name, ...)
|
data/lib/perron/errors.rb
CHANGED
data/lib/perron/feeds.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Perron
|
4
|
+
class Feeds
|
5
|
+
include ActionView::Helpers::TagHelper
|
6
|
+
|
7
|
+
def render(options = {})
|
8
|
+
html_tags = []
|
9
|
+
|
10
|
+
Rails.application.routes.url_helpers.with_options(Perron.configuration.default_url_options) do |url|
|
11
|
+
Perron::Site.collections.each do |collection|
|
12
|
+
collection_name = collection.name.to_s
|
13
|
+
|
14
|
+
next if options[:only]&.map(&:to_s)&.exclude?(collection_name)
|
15
|
+
next if options[:except]&.map(&:to_s)&.include?(collection_name)
|
16
|
+
|
17
|
+
collection.configuration.feeds.each do |type, feed|
|
18
|
+
next unless feed.enabled && feed.path && MIME_TYPES.key?(type)
|
19
|
+
|
20
|
+
absolute_url = URI.join(url.root_url, feed.path).to_s
|
21
|
+
title = "#{collection.name.humanize} #{type.to_s.upcase} Feed"
|
22
|
+
|
23
|
+
html_tags << tag(:link, rel: "alternate", type: MIME_TYPES[type], title: title, href: absolute_url)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
safe_join(html_tags, "\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
MIME_TYPES = {
|
34
|
+
rss: "application/rss+xml",
|
35
|
+
json: "application/json"
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
@@ -1,21 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "perron/html_processor/base"
|
4
|
+
|
3
5
|
module Perron
|
4
6
|
class HtmlProcessor
|
5
|
-
class TargetBlank
|
6
|
-
def initialize(html)
|
7
|
-
@html = html
|
8
|
-
end
|
9
|
-
|
7
|
+
class TargetBlank < HtmlProcessor::Base
|
10
8
|
def process
|
11
9
|
@html.css("a").each do |link|
|
12
10
|
href = link["href"]
|
13
11
|
|
14
|
-
next
|
15
|
-
next if href.start_with?("/", "#", "mailto:")
|
12
|
+
next if href.blank? || href.start_with?("/", "#", "mailto:")
|
16
13
|
|
17
14
|
link["target"] = "_blank"
|
18
|
-
link["rel"] = "noopener"
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
@@ -1,28 +1,50 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "perron/html_processor/target_blank"
|
4
|
+
require "perron/html_processor/lazy_load_images"
|
4
5
|
|
5
6
|
module Perron
|
6
7
|
class HtmlProcessor
|
7
|
-
def initialize(html)
|
8
|
+
def initialize(html, processors: [])
|
8
9
|
@html = html
|
10
|
+
@processors = processors.map { find_by(it) }
|
9
11
|
end
|
10
12
|
|
11
13
|
def process
|
12
14
|
document = Nokogiri::HTML::DocumentFragment.parse(@html)
|
13
15
|
|
14
|
-
|
15
|
-
processor.new(document).process
|
16
|
-
end
|
16
|
+
@processors.each { it.new(document).process }
|
17
17
|
|
18
18
|
document.to_html
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
Perron::HtmlProcessor::
|
26
|
-
|
23
|
+
BUILT_IN = {
|
24
|
+
"target_blank" => Perron::HtmlProcessor::TargetBlank,
|
25
|
+
"lazy_load_images" => Perron::HtmlProcessor::LazyLoadImages
|
26
|
+
}
|
27
|
+
|
28
|
+
def find_by(identifier)
|
29
|
+
case identifier
|
30
|
+
when String, Symbol
|
31
|
+
key = identifier.to_s
|
32
|
+
|
33
|
+
BUILT_IN[key] || find_class_by(key)
|
34
|
+
when Class
|
35
|
+
identifier
|
36
|
+
else
|
37
|
+
raise Perron::Errors::InvalidProcessorError, "Processor must be a String, Symbol, or Class, but got #{identifier.class.name}."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_class_by(name)
|
42
|
+
processor = name.camelize.safe_constantize
|
43
|
+
|
44
|
+
return processor if processor
|
45
|
+
|
46
|
+
raise Perron::Errors::ProcessorNotFoundError,
|
47
|
+
"Could not find processor `#{name}`. It is not a Perron-included processor and the constant `#{name.camelize}` could not be found."
|
48
|
+
end
|
27
49
|
end
|
28
50
|
end
|
data/lib/perron/markdown.rb
CHANGED
@@ -5,9 +5,9 @@ require "perron/html_processor"
|
|
5
5
|
module Perron
|
6
6
|
class Markdown
|
7
7
|
class << self
|
8
|
-
def render(text)
|
8
|
+
def render(text, processors: [])
|
9
9
|
parser.parse(text)
|
10
|
-
.then { Perron::HtmlProcessor.new(it).process }
|
10
|
+
.then { Perron::HtmlProcessor.new(it, processors: processors).process }
|
11
11
|
.html_safe
|
12
12
|
end
|
13
13
|
|
data/lib/perron/metatags.rb
CHANGED
@@ -20,6 +20,7 @@ module Perron
|
|
20
20
|
private
|
21
21
|
|
22
22
|
FRONTMATTER_KEY_MAP = {
|
23
|
+
"locale" => %w[og:locale],
|
23
24
|
"image" => %w[og:image twitter:image],
|
24
25
|
"author" => %w[og:author]
|
25
26
|
}.freeze
|
@@ -27,33 +28,40 @@ module Perron
|
|
27
28
|
def tags
|
28
29
|
@tags ||= begin
|
29
30
|
frontmatter = @resource&.metadata&.stringify_keys || {}
|
30
|
-
|
31
|
+
collection_config = @resource.collection.configuration.metadata
|
32
|
+
site_config = @config.metadata
|
31
33
|
|
32
|
-
title = frontmatter["title"] ||
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
38
44
|
|
39
45
|
{
|
40
46
|
title: title_tag(title),
|
41
47
|
description: meta_tag(name: "description", content: description),
|
48
|
+
article_published: meta_tag(property: "article:published_time", content: @resource&.published_at),
|
42
49
|
|
43
|
-
og_type: meta_tag(property: "og:type", content: frontmatter["og:type"] || "article"),
|
44
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
|
+
|
45
55
|
og_description: meta_tag(property: "og:description", content: frontmatter["og:description"] || description),
|
46
56
|
og_site_name: meta_tag(property: "og:site_name", content: @config.site_name),
|
47
|
-
|
57
|
+
og_logo: meta_tag(property: "og:logo", content: frontmatter["og:logo"] || logo),
|
48
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),
|
49
60
|
|
50
61
|
twitter_card: meta_tag(name: "twitter:card", content: frontmatter["twitter:card"] || "summary_large_image"),
|
51
62
|
twitter_title: meta_tag(name: "twitter:title", content: frontmatter["twitter:title"] || title),
|
52
63
|
twitter_description: meta_tag(name: "twitter:description", content: frontmatter["twitter:description"] || description),
|
53
|
-
twitter_image: meta_tag(name: "twitter:image", content: twitter_image)
|
54
|
-
article_published: meta_tag(property: "article:published_time", content: @resource&.published_at),
|
55
|
-
|
56
|
-
og_url: meta_tag(property: "og:url", content: canonical_url)
|
64
|
+
twitter_image: meta_tag(name: "twitter:image", content: twitter_image)
|
57
65
|
}
|
58
66
|
end
|
59
67
|
end
|