middleman-blog 4.0.3 → 4.2.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/.gitattributes +3 -0
- data/.github/workflows/ci.yml +25 -0
- data/.github/workflows/stale.yml +21 -0
- data/.gitignore +1 -3
- data/CHANGELOG.md +78 -60
- data/Gemfile +12 -26
- data/README.md +20 -30
- data/Rakefile +8 -14
- data/features/alias.feature +41 -0
- data/features/summary.feature +21 -2
- data/features/support/env.rb +2 -0
- data/features/support/time_steps.rb +9 -7
- data/features/tags.feature +4 -0
- data/fixtures/alias-app/config.rb +10 -0
- data/fixtures/alias-app/source/2024-03-14-pi-day.html.markdown +7 -0
- data/fixtures/alias-app/source/index.html +1 -0
- data/fixtures/alias-prefix-app/config.rb +11 -0
- data/fixtures/alias-prefix-app/source/blog/2024-01-15-prefix-test.html.markdown +7 -0
- data/fixtures/alias-prefix-app/source/index.html +1 -0
- data/fixtures/article-dirs-app/config-directory-indexes.rb +2 -0
- data/fixtures/article-dirs-app/config-permalink-with-dot.rb +2 -0
- data/fixtures/article-dirs-app/config.rb +2 -0
- data/fixtures/blog-sources-app/config.rb +2 -0
- data/fixtures/blog-sources-no-date-app/config.rb +2 -0
- data/fixtures/blog-sources-no-day-app/config.rb +2 -0
- data/fixtures/blog-sources-no-title-app/config.rb +2 -0
- data/fixtures/blog-sources-subdirs-app/config.rb +2 -0
- data/fixtures/calendar-and-tag-app/config-directory-indexes.rb +2 -0
- data/fixtures/calendar-and-tag-app/config.rb +2 -0
- data/fixtures/calendar-app/config-directory-indexes.rb +2 -0
- data/fixtures/calendar-app/config-only-year.rb +2 -0
- data/fixtures/calendar-app/config.rb +2 -0
- data/fixtures/calendar-multiblog-app/config.rb +2 -0
- data/fixtures/custom-article-template-app/config.rb +2 -0
- data/fixtures/custom-collections-app/config-blog-prefix.rb +2 -0
- data/fixtures/custom-collections-app/config-directory-indexes.rb +2 -0
- data/fixtures/custom-collections-app/config.rb +2 -0
- data/fixtures/custom-collections-multiblog-app/config.rb +2 -0
- data/fixtures/custom-collections-sources-app/config.rb +2 -0
- data/fixtures/custom-permalinks-app/config-directory-indexes.rb +2 -0
- data/fixtures/custom-permalinks-app/config.rb +2 -0
- data/fixtures/filename-date-app/config.rb +2 -0
- data/fixtures/future-date-app/config.rb +2 -0
- data/fixtures/indexes-app/config.rb +2 -0
- data/fixtures/lang-path-app/config.rb +2 -0
- data/fixtures/language-app/config.rb +3 -1
- data/fixtures/layouts-app/config.rb +2 -0
- data/fixtures/paginate-app/config-directory-indexes.rb +2 -0
- data/fixtures/paginate-app/config-paginate-off.rb +2 -0
- data/fixtures/paginate-app/config.rb +2 -0
- data/fixtures/paginate-multiblog-app/config.rb +2 -0
- data/fixtures/permalink-app/config.rb +2 -0
- data/fixtures/preview-app/config.rb +2 -0
- data/fixtures/published-app/config.rb +2 -0
- data/fixtures/summary-app/config.rb +2 -0
- data/fixtures/summary-app/source/layout.erb +6 -0
- data/fixtures/tags-app/config-directory-indexes.rb +2 -0
- data/fixtures/tags-app/config-filters.rb +2 -0
- data/fixtures/tags-app/config-no-tags.rb +2 -0
- data/fixtures/tags-app/config.rb +2 -0
- data/fixtures/tags-app/source/blog/2011-01-01-new-article.html.markdown +1 -1
- data/fixtures/tags-app/source/blog/2011-01-02-another-article.html.markdown +1 -0
- data/fixtures/tags-multiblog-app/config.rb +2 -0
- data/fixtures/time-zone-app/config.rb +2 -0
- data/lib/middleman-blog/alias_pages.rb +161 -0
- data/lib/middleman-blog/blog_article.rb +17 -11
- data/lib/middleman-blog/blog_data.rb +4 -8
- data/lib/middleman-blog/calendar_pages.rb +8 -6
- data/lib/middleman-blog/commands/article.rb +10 -6
- data/lib/middleman-blog/commands/article.tt +2 -2
- data/lib/middleman-blog/custom_pages.rb +3 -1
- data/lib/middleman-blog/extension.rb +32 -12
- data/lib/middleman-blog/helpers.rb +4 -2
- data/lib/middleman-blog/paginator.rb +3 -1
- data/lib/middleman-blog/tag_pages.rb +3 -1
- data/lib/middleman-blog/truncate_html.rb +21 -5
- data/lib/middleman-blog/uri_templates.rb +12 -6
- data/lib/middleman-blog/version.rb +3 -1
- data/lib/middleman-blog.rb +2 -0
- data/lib/middleman_extension.rb +2 -0
- data/middleman-blog.gemspec +15 -22
- data/spec/alias_spec.rb +116 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/uri_templates_spec.rb +14 -0
- metadata +30 -34
- data/.rubocop.yml +0 -69
- data/.travis.yml +0 -30
- data/Gemfile-4.x +0 -38
- data/fixtures/default-template-app/Gemfile +0 -6
- data/fixtures/default-template-app/config.rb +0 -35
- data/fixtures/default-template-app/source/2013-04-01-new-article.html.markdown +0 -25
- data/fixtures/default-template-app/source/about-me.html.erb +0 -0
- data/fixtures/default-template-app/source/archives.html.erb +0 -10
- data/fixtures/default-template-app/source/index.html.erb +0 -11
- data/fixtures/default-template-app/source/javascripts/_zepto.pjax.js +0 -744
- data/fixtures/default-template-app/source/javascripts/app.js +0 -11
- data/fixtures/default-template-app/source/javascripts/modernizr.js +0 -1
- data/fixtures/default-template-app/source/layouts/layout.erb +0 -62
- data/fixtures/default-template-app/source/stylesheets/app.css.scss +0 -109
- /data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
- /data/{ISSUE_TEMPLATE.md → .github/ISSUE_TEMPLATE.md} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
activate :blog do |blog|
|
|
4
|
+
blog.prefix = 'blog'
|
|
5
|
+
blog.sources = ':year-:month-:day-:title.html'
|
|
6
|
+
blog.permalink = ':year/:month/:day/:title.html'
|
|
7
|
+
blog.aliases = [
|
|
8
|
+
':year-:month-:day-:title.html',
|
|
9
|
+
'archive/:year/:title'
|
|
10
|
+
]
|
|
11
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<h1>Blog with Prefix</h1>
|
data/fixtures/tags-app/config.rb
CHANGED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'middleman-core'
|
|
4
|
+
require 'middleman-core/sitemap/resource'
|
|
5
|
+
require 'middleman-blog/uri_templates'
|
|
6
|
+
|
|
7
|
+
module Middleman
|
|
8
|
+
module Blog
|
|
9
|
+
##
|
|
10
|
+
# A sitemap resource manipulator that adds alias/redirect pages to the sitemap
|
|
11
|
+
# for each blog article based on the configured alias patterns
|
|
12
|
+
##
|
|
13
|
+
class AliasPages
|
|
14
|
+
include UriTemplates
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# Initialise Alias pages
|
|
18
|
+
#
|
|
19
|
+
# @param app [Object] Middleman app
|
|
20
|
+
# @param blog_controller [Object] Blog controller
|
|
21
|
+
##
|
|
22
|
+
def initialize(app, blog_controller)
|
|
23
|
+
@sitemap = app.sitemap
|
|
24
|
+
@blog_controller = blog_controller
|
|
25
|
+
@blog_data = blog_controller.data
|
|
26
|
+
@alias_patterns = blog_controller.options.aliases || []
|
|
27
|
+
@alias_templates = @alias_patterns.map { |pattern| uri_template(pattern) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Update the main sitemap resource list
|
|
32
|
+
#
|
|
33
|
+
# @param resources [Array] Existing resources
|
|
34
|
+
# @return [Array] Resources with alias pages added
|
|
35
|
+
##
|
|
36
|
+
def manipulate_resource_list(resources)
|
|
37
|
+
return resources if @alias_patterns.empty?
|
|
38
|
+
|
|
39
|
+
alias_resources = []
|
|
40
|
+
|
|
41
|
+
@blog_data.articles.each do |article|
|
|
42
|
+
@alias_templates.each do |template|
|
|
43
|
+
alias_path = generate_alias_path(template, article)
|
|
44
|
+
next if alias_path == article.destination_path # Don't create alias to itself
|
|
45
|
+
|
|
46
|
+
alias_resources << alias_page_resource(alias_path, article)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
resources + alias_resources
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Generate an alias path for an article using the given template
|
|
57
|
+
#
|
|
58
|
+
# @param template [Addressable::Template] URI template for the alias
|
|
59
|
+
# @param article [BlogArticle] The blog article
|
|
60
|
+
# @return [String] The generated alias path
|
|
61
|
+
##
|
|
62
|
+
def generate_alias_path(template, article)
|
|
63
|
+
# Get the same parameters used for the main permalink
|
|
64
|
+
params = permalink_options(article)
|
|
65
|
+
apply_uri_template(template, params)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Generate permalink options for an article (same as BlogData uses)
|
|
70
|
+
#
|
|
71
|
+
# @param article [BlogArticle] The blog article
|
|
72
|
+
# @return [Hash] Parameters for URL generation
|
|
73
|
+
##
|
|
74
|
+
def permalink_options(article)
|
|
75
|
+
# Get variables from all alias templates
|
|
76
|
+
all_variables = @alias_templates.flat_map(&:variables).uniq
|
|
77
|
+
|
|
78
|
+
# Allow any frontmatter data to be substituted into the alias URL
|
|
79
|
+
page_data = article.metadata[:page] || {}
|
|
80
|
+
params = page_data.slice(*all_variables.map(&:to_sym))
|
|
81
|
+
|
|
82
|
+
params.each do |k, v|
|
|
83
|
+
params[k] = safe_parameterize(v)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
params
|
|
87
|
+
.merge(date_to_params(article.date))
|
|
88
|
+
.merge(lang: article.lang.to_s, locale: article.locale.to_s, title: article.slug)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
##
|
|
92
|
+
# Create an alias page resource that redirects to the main article
|
|
93
|
+
#
|
|
94
|
+
# @param alias_path [String] The path for the alias
|
|
95
|
+
# @param article [BlogArticle] The target article
|
|
96
|
+
# @return [Sitemap::Resource] A redirect resource
|
|
97
|
+
##
|
|
98
|
+
def alias_page_resource(alias_path, article)
|
|
99
|
+
target_url = article.destination_path
|
|
100
|
+
# Ensure target URL starts with '/' for absolute URLs
|
|
101
|
+
target_url = "/#{target_url}" unless target_url.start_with?('/')
|
|
102
|
+
AliasResource.new(@sitemap, alias_path, target_url, article)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# A resource that generates redirect HTML for alias pages
|
|
108
|
+
##
|
|
109
|
+
class AliasResource < ::Middleman::Sitemap::Resource
|
|
110
|
+
def initialize(store, path, target_url, alias_resource)
|
|
111
|
+
@target_url = target_url
|
|
112
|
+
@alias_resource = alias_resource
|
|
113
|
+
super(store, path)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def source_file
|
|
117
|
+
@alias_resource.source_file
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def template?
|
|
121
|
+
false
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def render(*args, &block)
|
|
125
|
+
%[
|
|
126
|
+
<html>
|
|
127
|
+
<head>
|
|
128
|
+
<link rel="canonical" href="#{@target_url}" />
|
|
129
|
+
<meta name="robots" content="noindex,follow" />
|
|
130
|
+
<meta http-equiv="cache-control" content="no-cache" />
|
|
131
|
+
<script>
|
|
132
|
+
// Attempt to keep search and hash
|
|
133
|
+
window.location.replace("#{@target_url}"+window.location.search+window.location.hash);
|
|
134
|
+
</script>
|
|
135
|
+
<meta http-equiv=refresh content="0; url=#{@target_url}" />
|
|
136
|
+
</head>
|
|
137
|
+
<body>
|
|
138
|
+
<a href="#{@target_url}">You are being redirected.</a>
|
|
139
|
+
</body>
|
|
140
|
+
</html>
|
|
141
|
+
]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def binary?
|
|
145
|
+
false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def raw_data
|
|
149
|
+
@alias_resource.raw_data
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def ignored?
|
|
153
|
+
false
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def metadata
|
|
157
|
+
@alias_resource.metadata
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'active_support/time_with_zone'
|
|
2
4
|
require 'active_support/core_ext/time/acts_like'
|
|
3
5
|
require 'active_support/core_ext/time/calculations'
|
|
@@ -14,9 +16,6 @@ module Middleman
|
|
|
14
16
|
module BlogArticle
|
|
15
17
|
extend Gem::Deprecate
|
|
16
18
|
|
|
17
|
-
##
|
|
18
|
-
#
|
|
19
|
-
##
|
|
20
19
|
def self.extended(base)
|
|
21
20
|
base.class.send(:attr_accessor, :blog_controller)
|
|
22
21
|
end
|
|
@@ -58,7 +57,14 @@ module Middleman
|
|
|
58
57
|
|
|
59
58
|
content = super(opts, locs, &block)
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
# Handle summary separator: if not keeping separator and separator exists,
|
|
61
|
+
# return only content after separator
|
|
62
|
+
if blog_options.summary_separator && !opts[:keep_separator]
|
|
63
|
+
if content.match?(blog_options.summary_separator)
|
|
64
|
+
require 'middleman-blog/truncate_html'
|
|
65
|
+
content = TruncateHTML.content_after_separator(content, blog_options.summary_separator)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
62
68
|
|
|
63
69
|
content
|
|
64
70
|
end
|
|
@@ -204,10 +210,10 @@ module Middleman
|
|
|
204
210
|
|
|
205
211
|
# First get the date from frontmatter
|
|
206
212
|
@_date = if frontmatter_date.is_a? Time
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
frontmatter_date.in_time_zone
|
|
214
|
+
else
|
|
215
|
+
Time.zone.parse(frontmatter_date.to_s)
|
|
216
|
+
end
|
|
211
217
|
|
|
212
218
|
# Next figure out the date from the filename
|
|
213
219
|
source_vars = blog_data.source_template.variables
|
|
@@ -239,13 +245,13 @@ module Middleman
|
|
|
239
245
|
##
|
|
240
246
|
def slug
|
|
241
247
|
if data['slug']
|
|
242
|
-
Blog::UriTemplates.safe_parameterize(data['slug'])
|
|
248
|
+
Blog::UriTemplates.safe_parameterize(data['slug'], preserve_underscores: blog_options.preserve_underscores_in_slugs)
|
|
243
249
|
|
|
244
250
|
elsif blog_data.source_template.variables.include?('title')
|
|
245
|
-
Blog::UriTemplates.safe_parameterize(path_part('title'))
|
|
251
|
+
Blog::UriTemplates.safe_parameterize(path_part('title'), preserve_underscores: blog_options.preserve_underscores_in_slugs)
|
|
246
252
|
|
|
247
253
|
elsif title
|
|
248
|
-
Blog::UriTemplates.safe_parameterize(title)
|
|
254
|
+
Blog::UriTemplates.safe_parameterize(title, preserve_underscores: blog_options.preserve_underscores_in_slugs)
|
|
249
255
|
|
|
250
256
|
else
|
|
251
257
|
raise "Can't generate a slug for #{path} because it has no :title in its path pattern or title/slug in its frontmatter."
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'middleman-blog/uri_templates'
|
|
2
4
|
|
|
3
5
|
module Middleman
|
|
@@ -49,7 +51,7 @@ module Middleman
|
|
|
49
51
|
# @return [Array<Middleman::Sitemap::Resource>]
|
|
50
52
|
##
|
|
51
53
|
def articles
|
|
52
|
-
@_articles.select(&
|
|
54
|
+
@_articles.select(&options.filter || proc { |a| a }).sort_by(&:date).reverse
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
##
|
|
@@ -207,7 +209,7 @@ module Middleman
|
|
|
207
209
|
params = resource.metadata[:page].slice(*@permalink_template.variables.map(&:to_sym))
|
|
208
210
|
|
|
209
211
|
params.each do |k, v|
|
|
210
|
-
params[k] = safe_parameterize(v)
|
|
212
|
+
params[k] = safe_parameterize(v, preserve_underscores: @options.preserve_underscores_in_slugs)
|
|
211
213
|
end
|
|
212
214
|
|
|
213
215
|
params
|
|
@@ -216,9 +218,6 @@ module Middleman
|
|
|
216
218
|
.merge(extra)
|
|
217
219
|
end
|
|
218
220
|
|
|
219
|
-
##
|
|
220
|
-
#
|
|
221
|
-
##
|
|
222
221
|
def convert_to_article(resource)
|
|
223
222
|
return resource if resource.is_a?(BlogArticle)
|
|
224
223
|
|
|
@@ -232,9 +231,6 @@ module Middleman
|
|
|
232
231
|
resource
|
|
233
232
|
end
|
|
234
233
|
|
|
235
|
-
##
|
|
236
|
-
#
|
|
237
|
-
##
|
|
238
234
|
def template_path(template, article, extras = {})
|
|
239
235
|
apply_uri_template template, permalink_options(article, extras)
|
|
240
236
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'middleman-blog/uri_templates'
|
|
2
4
|
|
|
3
5
|
module Middleman
|
|
@@ -31,12 +33,12 @@ module Middleman
|
|
|
31
33
|
# @return [String]
|
|
32
34
|
def link(year, month = nil, day = nil)
|
|
33
35
|
template = if day
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
@day_link_template
|
|
37
|
+
elsif month
|
|
38
|
+
@month_link_template
|
|
39
|
+
else
|
|
40
|
+
@year_link_template
|
|
41
|
+
end
|
|
40
42
|
|
|
41
43
|
apply_uri_template template, date_to_params(Date.new(year, month || 1, day || 1))
|
|
42
44
|
end
|