dimples 2.4.1 → 2.5.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/bin/dimples +22 -20
- data/lib/dimples.rb +3 -0
- data/lib/dimples/category.rb +8 -4
- data/lib/dimples/configuration.rb +6 -5
- data/lib/dimples/errors.rb +2 -0
- data/lib/dimples/frontable.rb +11 -13
- data/lib/dimples/logger.rb +9 -5
- data/lib/dimples/page.rb +4 -1
- data/lib/dimples/post.rb +13 -11
- data/lib/dimples/renderable.rb +10 -9
- data/lib/dimples/site.rb +132 -116
- data/lib/dimples/template.rb +4 -1
- data/lib/dimples/version.rb +3 -1
- data/lib/dimples/writeable.rb +5 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab668fba29311d490d3187f339fb6092ddce1b39
|
4
|
+
data.tar.gz: e86ce790ccd489891f8ee06d88a9cdddce099015
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d41ec0a5a57ae5f1a5e7c4d31398a8a925ae78a2c956574aec11b9a7510da53b46ff8ab0fed38a6abd8c50f582a3aaf86f01a60bbe3ea9924cb1a9834dc9b12e
|
7
|
+
data.tar.gz: e975c1a286092a240a0721e7eac2a445e1b6143f9004bb668b10631716c197ddccd70b24cb5107a7281c3e837c7a32a19704043158ee704e3536301b1010290b
|
data/bin/dimples
CHANGED
@@ -1,52 +1,54 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
$LOAD_PATH.unshift(File.join(__dir__,
|
4
|
+
$LOAD_PATH.unshift(File.join(__dir__, '..', 'lib'))
|
4
5
|
|
5
6
|
require 'dimples'
|
6
7
|
require 'dimples/version'
|
7
8
|
require 'trollop'
|
8
9
|
|
9
10
|
trap('SIGINT') do
|
10
|
-
puts
|
11
|
+
puts 'Generation cancelled!'
|
11
12
|
exit!
|
12
13
|
end
|
13
14
|
|
14
15
|
valid_commands = %w[build]
|
15
16
|
|
16
|
-
options = Trollop
|
17
|
+
options = Trollop.options do
|
17
18
|
version "dimples v#{Dimples::VERSION}"
|
18
|
-
banner
|
19
|
-
A very, very simple static site generator.
|
19
|
+
banner <<~EOS
|
20
|
+
A very, very simple static site generator.
|
20
21
|
|
21
|
-
Usage:
|
22
|
-
|
22
|
+
Usage:
|
23
|
+
dimples <#{valid_commands.join('|')}> [options]
|
23
24
|
|
24
|
-
Options:
|
25
|
+
Options:
|
25
26
|
EOS
|
26
|
-
opt :config,
|
27
|
-
opt :lib,
|
28
|
-
opt :verbose,
|
27
|
+
opt :config, 'Config file path', type: :string
|
28
|
+
opt :lib, 'Library file path', default: 'lib'
|
29
|
+
opt :verbose, 'Verbose mode', default: false
|
29
30
|
end
|
30
31
|
|
31
|
-
Trollop
|
32
|
+
Trollop.educate if ARGV.empty?
|
32
33
|
command = ARGV[0]
|
33
34
|
|
34
35
|
unless valid_commands.include?(command)
|
35
|
-
Trollop
|
36
|
+
Trollop.die "Command must be '#{valid_commands.join('\', \'')}'"
|
36
37
|
end
|
37
38
|
|
38
39
|
lib_path = File.join(Dir.pwd, options[:lib])
|
39
40
|
config_path = File.join(Dir.pwd, options[:config] || 'config', 'site.yml')
|
40
41
|
|
41
|
-
config_hash =
|
42
|
+
config_hash = {}
|
43
|
+
|
44
|
+
if File.exist?(config_path)
|
42
45
|
begin
|
43
|
-
YAML.load_file(config_path) || {}
|
46
|
+
config_hash = YAML.load_file(config_path) || {}
|
44
47
|
rescue
|
45
|
-
Trollop
|
48
|
+
Trollop.die 'Invalid or malformed YAML config file'
|
46
49
|
end
|
47
|
-
|
48
|
-
Trollop
|
49
|
-
{}
|
50
|
+
elsif options[:config]
|
51
|
+
Trollop.die 'Unable to find config file'
|
50
52
|
end
|
51
53
|
|
52
54
|
config_hash['verbose_logging'] = true if options[:verbose]
|
@@ -58,7 +60,7 @@ if Dir.exist?(lib_path)
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
site_klass = config.class_override(:site) || Dimples
|
63
|
+
site_klass = config.class_override(:site) || Dimples.Site
|
62
64
|
site = site_klass.new(config)
|
63
65
|
|
64
66
|
case command.to_sym
|
data/lib/dimples.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
$LOAD_PATH.unshift(__dir__)
|
2
4
|
|
3
5
|
require 'benchmark'
|
@@ -20,6 +22,7 @@ require 'dimples/post'
|
|
20
22
|
require 'dimples/site'
|
21
23
|
require 'dimples/template'
|
22
24
|
|
25
|
+
# A static site generator.
|
23
26
|
module Dimples
|
24
27
|
class << self
|
25
28
|
def logger
|
data/lib/dimples/category.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a single interview category.
|
2
5
|
class Category
|
3
6
|
attr_accessor :name
|
4
7
|
attr_accessor :slug
|
5
8
|
attr_accessor :posts
|
6
9
|
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
def initialize(site, slug)
|
11
|
+
@site = site
|
12
|
+
@slug = slug
|
13
|
+
@name = @site.config['category_names'][slug] || slug.capitalize
|
14
|
+
@posts = []
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a site's configuration.
|
2
5
|
class Configuration
|
3
6
|
def initialize(config = {})
|
4
7
|
@settings = Dimples::Configuration.default_settings
|
@@ -17,16 +20,14 @@ module Dimples
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def class_override(type)
|
20
|
-
klass = @settings['class_overrides'][
|
23
|
+
klass = @settings['class_overrides'][type.to_s]
|
21
24
|
Object.const_get(klass) unless klass.nil?
|
22
25
|
end
|
23
26
|
|
24
27
|
def self.default_settings
|
25
|
-
current_path = Dir.pwd
|
26
|
-
|
27
28
|
{
|
28
|
-
'source_path' =>
|
29
|
-
'destination_path' => File.join(
|
29
|
+
'source_path' => Dir.pwd,
|
30
|
+
'destination_path' => File.join(Dir.pwd, 'site'),
|
30
31
|
'verbose_logging' => false,
|
31
32
|
'class_overrides' => { site: nil, post: nil, page: nil },
|
32
33
|
'rendering' => {},
|
data/lib/dimples/errors.rb
CHANGED
data/lib/dimples/frontable.rb
CHANGED
@@ -1,20 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A mixin class that handles reading and parsing front matter from a file.
|
2
5
|
module Frontable
|
3
|
-
def
|
4
|
-
|
5
|
-
|
6
|
-
metadata = YAML.load_file(path)
|
7
|
-
else
|
8
|
-
contents = File.read(path)
|
9
|
-
matches = contents.match(/^(-{3}\n.*?\n?)^(-{3}*$\n?)/m)
|
6
|
+
def read_with_front_matter(path)
|
7
|
+
contents = File.read(path)
|
8
|
+
matches = contents.match(/^(-{3}\n.*?\n?)^(-{3}*$\n?)/m)
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
10
|
+
if matches
|
11
|
+
metadata = YAML.safe_load(matches[1])
|
12
|
+
contents = matches.post_match.strip
|
16
13
|
|
17
|
-
|
14
|
+
apply_metadata(metadata) if metadata
|
15
|
+
end
|
18
16
|
|
19
17
|
contents
|
20
18
|
end
|
data/lib/dimples/logger.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A simple Logger subclass.
|
2
5
|
class Logger < Logger
|
3
6
|
def initialize(*)
|
4
7
|
super
|
@@ -14,13 +17,14 @@ module Dimples
|
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
20
|
+
# A simple Logger formatting subclass.
|
17
21
|
class LogFormatter < Logger::Formatter
|
18
|
-
def self.call(severity,
|
19
|
-
|
20
|
-
when
|
21
|
-
"\033[31mError:\033[0m "
|
22
|
+
def self.call(severity, _time, _program_name, message)
|
23
|
+
case severity
|
24
|
+
when 'ERROR'
|
25
|
+
prefix = "\033[31mError:\033[0m "
|
22
26
|
when 'DEBUG'
|
23
|
-
"\033[93m- "
|
27
|
+
prefix = "\033[93m- "
|
24
28
|
end
|
25
29
|
|
26
30
|
"#{prefix}#{message}\033[0m\n"
|
data/lib/dimples/page.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a single site page.
|
2
5
|
class Page
|
3
6
|
include Frontable
|
4
7
|
include Writeable
|
@@ -20,7 +23,7 @@ module Dimples
|
|
20
23
|
|
21
24
|
if @path
|
22
25
|
@filename = File.basename(@path, File.extname(@path))
|
23
|
-
@contents =
|
26
|
+
@contents = read_with_front_matter(@path)
|
24
27
|
else
|
25
28
|
@filename = 'index'
|
26
29
|
@contents = ''
|
data/lib/dimples/post.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a single site post.
|
2
5
|
class Post
|
3
6
|
include Frontable
|
4
7
|
include Writeable
|
@@ -13,42 +16,41 @@ module Dimples
|
|
13
16
|
attr_accessor :layout
|
14
17
|
attr_accessor :contents
|
15
18
|
attr_accessor :slug
|
16
|
-
attr_accessor :date
|
17
19
|
attr_accessor :year
|
18
20
|
attr_accessor :month
|
19
21
|
attr_accessor :day
|
20
22
|
attr_accessor :rendered_contents
|
21
23
|
attr_accessor :previous_post
|
22
24
|
attr_accessor :next_post
|
23
|
-
|
25
|
+
attr_reader :date
|
26
|
+
|
27
|
+
FILENAME_DATE = /(\d{4})-(\d{2})-(\d{2})-(.+)/
|
24
28
|
|
25
29
|
def initialize(site, path)
|
26
30
|
@site = site
|
27
31
|
@path = path
|
28
|
-
|
29
32
|
@filename = 'index'
|
30
33
|
@extension = 'html'
|
31
34
|
|
32
|
-
|
33
|
-
parts = File.basename(path, File.extname(path)).match(date_format)
|
35
|
+
parts = File.basename(path, File.extname(path)).match(FILENAME_DATE)
|
34
36
|
|
35
37
|
@slug = parts[4]
|
36
|
-
|
38
|
+
self.date = Time.mktime(parts[1], parts[2], parts[3])
|
37
39
|
|
38
40
|
@layout = @site.config['layouts']['post']
|
39
|
-
@
|
41
|
+
@contents = read_with_front_matter(path)
|
42
|
+
end
|
40
43
|
|
41
|
-
|
44
|
+
def date=(date)
|
45
|
+
@date = date
|
42
46
|
|
43
47
|
@year = @date.strftime('%Y')
|
44
48
|
@month = @date.strftime('%m')
|
45
49
|
@day = @date.strftime('%d')
|
46
|
-
|
47
|
-
@contents = read_with_yaml(path)
|
48
50
|
end
|
49
51
|
|
50
52
|
def output_path(parent_path)
|
51
|
-
parent_path = @date.strftime(parent_path) if parent_path
|
53
|
+
parent_path = @date.strftime(parent_path) if parent_path.match?(/%/)
|
52
54
|
File.join([parent_path, @slug.to_s, "#{@filename}.#{@extension}"])
|
53
55
|
end
|
54
56
|
end
|
data/lib/dimples/renderable.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A mixin class that handles rendering via a Tilt template.
|
2
5
|
module Renderable
|
3
6
|
def render(context = {}, body = nil, use_layout = true)
|
4
|
-
|
5
|
-
|
6
|
-
@rendered_contents = output
|
7
|
-
rescue RuntimeError, TypeError, NoMethodError, SyntaxError, NameError => e
|
8
|
-
sanitised_error_name = e.class.to_s.gsub(/([A-Z])/, " \\1").strip.downcase
|
9
|
-
error_message = "Unable to render #{@path || "a dynamic #{self.class}"} (#{sanitised_error_name})"
|
10
|
-
|
11
|
-
raise Errors::RenderingError.new(error_message)
|
12
|
-
end
|
7
|
+
output = renderer.render(build_scope(context)) { body }.strip
|
8
|
+
@rendered_contents = output
|
13
9
|
|
14
10
|
if use_layout && defined?(@layout) && @site.templates[@layout]
|
15
11
|
output = @site.templates[@layout].render(context, output)
|
16
12
|
end
|
17
13
|
|
18
14
|
output
|
15
|
+
rescue => e
|
16
|
+
error_name = e.class.to_s.gsub(/([A-Z])/, ' \\1').strip.downcase
|
17
|
+
error_message = "Unable to render #{@path || self.class} (#{error_name})"
|
18
|
+
|
19
|
+
raise Errors::RenderingError.new, error_message
|
19
20
|
end
|
20
21
|
|
21
22
|
def build_scope(context)
|
data/lib/dimples/site.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a single site.
|
2
5
|
class Site
|
3
6
|
attr_accessor :source_paths
|
4
7
|
attr_accessor :output_paths
|
@@ -14,32 +17,40 @@ module Dimples
|
|
14
17
|
attr_accessor :errors
|
15
18
|
|
16
19
|
def initialize(config)
|
17
|
-
@
|
18
|
-
|
20
|
+
@config = config
|
21
|
+
|
19
22
|
@templates = {}
|
20
23
|
@categories = {}
|
21
|
-
@archives = { year: {}, month: {}, day: {} }
|
22
|
-
|
23
24
|
@pages = []
|
24
25
|
@posts = []
|
26
|
+
@errors = []
|
25
27
|
|
28
|
+
@archives = { year: {}, month: {}, day: {} }
|
26
29
|
@latest_post = false
|
27
30
|
|
28
|
-
@config = config
|
29
|
-
|
30
31
|
@page_class = @config.class_override(:page) || Dimples::Page
|
31
32
|
@post_class = @config.class_override(:post) || Dimples::Post
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
set_source_paths
|
35
|
+
set_output_paths
|
36
|
+
end
|
35
37
|
|
36
|
-
|
38
|
+
def set_source_paths
|
39
|
+
@source_paths = {
|
40
|
+
root: File.expand_path(@config['source_path'])
|
41
|
+
}
|
37
42
|
|
38
|
-
%w
|
43
|
+
%w[pages posts public templates].each do |path|
|
39
44
|
@source_paths[path.to_sym] = File.join(@source_paths[:root], path)
|
40
45
|
end
|
46
|
+
end
|
41
47
|
|
42
|
-
|
48
|
+
def set_output_paths
|
49
|
+
@output_paths = {
|
50
|
+
site: File.expand_path(@config['destination_path'])
|
51
|
+
}
|
52
|
+
|
53
|
+
%w[archives posts categories].each do |path|
|
43
54
|
output_path = File.join(@output_paths[:site], @config['paths'][path])
|
44
55
|
@output_paths[path.to_sym] = output_path
|
45
56
|
end
|
@@ -50,12 +61,14 @@ module Dimples
|
|
50
61
|
scan_files
|
51
62
|
generate_files
|
52
63
|
copy_assets
|
53
|
-
rescue Errors::RenderingError,
|
64
|
+
rescue Errors::RenderingError,
|
65
|
+
Errors::PublishingError,
|
66
|
+
Errors::GenerationError => e
|
54
67
|
@errors << e.message
|
55
68
|
end
|
56
69
|
|
57
70
|
def generated?
|
58
|
-
@errors.count
|
71
|
+
@errors.count.zero?
|
59
72
|
end
|
60
73
|
|
61
74
|
private
|
@@ -67,7 +80,8 @@ module Dimples
|
|
67
80
|
|
68
81
|
Dir.mkdir(@output_paths[:site])
|
69
82
|
rescue => e
|
70
|
-
|
83
|
+
error_message = "Couldn't prepare the output directory (#{e.message})"
|
84
|
+
raise Errors::GenerationError, error_message
|
71
85
|
end
|
72
86
|
|
73
87
|
def scan_files
|
@@ -85,39 +99,25 @@ module Dimples
|
|
85
99
|
|
86
100
|
def scan_pages
|
87
101
|
Dir.glob(File.join(@source_paths[:pages], '**', '*.*')).each do |path|
|
88
|
-
|
89
|
-
@pages << page
|
102
|
+
@pages << scan_page(path)
|
90
103
|
end
|
91
104
|
end
|
92
105
|
|
106
|
+
def scan_page(path)
|
107
|
+
@page_class.new(self, path)
|
108
|
+
end
|
109
|
+
|
93
110
|
def scan_posts
|
94
111
|
Dir.glob(File.join(@source_paths[:posts], '*.*')).reverse_each do |path|
|
95
|
-
|
96
|
-
|
97
|
-
next if post.draft
|
98
|
-
|
99
|
-
post.categories.each do |slug|
|
100
|
-
unless @categories[slug]
|
101
|
-
name = @config['category_names'][slug] || slug.capitalize
|
102
|
-
@categories[slug] = Dimples::Category.new(name, slug)
|
103
|
-
end
|
104
|
-
|
105
|
-
@categories[slug].posts << post
|
106
|
-
end
|
107
|
-
|
108
|
-
archive_year(post.year) << post
|
109
|
-
archive_month(post.year, post.month) << post
|
110
|
-
archive_day(post.year, post.month, post.day) << post
|
111
|
-
|
112
|
-
@posts << post
|
112
|
+
@posts << scan_post(path)
|
113
113
|
end
|
114
114
|
|
115
115
|
@posts.each_index do |index|
|
116
|
-
if index - 1 >= 0
|
116
|
+
if (index - 1) >= 0
|
117
117
|
@posts[index].next_post = @posts.fetch(index - 1, nil)
|
118
118
|
end
|
119
119
|
|
120
|
-
if index + 1 < @posts.count
|
120
|
+
if (index + 1) < @posts.count
|
121
121
|
@posts[index].previous_post = @posts.fetch(index + 1, nil)
|
122
122
|
end
|
123
123
|
end
|
@@ -125,6 +125,23 @@ module Dimples
|
|
125
125
|
@latest_post = @posts.first
|
126
126
|
end
|
127
127
|
|
128
|
+
def scan_post(path)
|
129
|
+
@post_class.new(self, path).tap do |post|
|
130
|
+
post.categories.each do |slug|
|
131
|
+
@categories[slug] ||= Dimples::Category.new(self, slug)
|
132
|
+
@categories[slug].posts << post
|
133
|
+
end
|
134
|
+
|
135
|
+
add_post_to_archives(post)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_post_to_archives(post)
|
140
|
+
archive_year(post.year) << post
|
141
|
+
archive_month(post.year, post.month) << post
|
142
|
+
archive_day(post.year, post.month, post.day) << post
|
143
|
+
end
|
144
|
+
|
128
145
|
def archive_year(year)
|
129
146
|
@archives[:year][year] ||= []
|
130
147
|
end
|
@@ -138,31 +155,29 @@ module Dimples
|
|
138
155
|
end
|
139
156
|
|
140
157
|
def generate_files
|
141
|
-
unless @pages.
|
142
|
-
generate_pages
|
143
|
-
end
|
158
|
+
generate_pages unless @pages.count.zero?
|
144
159
|
|
145
|
-
|
146
|
-
generate_posts
|
147
|
-
generate_archives
|
160
|
+
return if @posts.count.zero?
|
148
161
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
end
|
162
|
+
generate_posts
|
163
|
+
generate_archives
|
164
|
+
generate_categories if @config['generation']['categories']
|
153
165
|
end
|
154
166
|
|
155
167
|
def generate_posts
|
156
|
-
|
168
|
+
if @config['verbose_logging']
|
169
|
+
Dimples.logger.debug_generation('posts', @posts.length)
|
170
|
+
end
|
157
171
|
|
158
172
|
@posts.each do |post|
|
159
173
|
generate_post(post)
|
160
174
|
end
|
161
175
|
|
162
|
-
paths = [@output_paths[:archives]]
|
163
176
|
layout = @config['layouts']['posts']
|
164
177
|
|
165
|
-
paginate(posts: @posts,
|
178
|
+
paginate(posts: @posts, path: @output_paths[:archives], layout: layout)
|
179
|
+
|
180
|
+
generate_posts_feeds if @config['generation']['feeds']
|
166
181
|
end
|
167
182
|
|
168
183
|
def generate_post(post)
|
@@ -170,7 +185,9 @@ module Dimples
|
|
170
185
|
end
|
171
186
|
|
172
187
|
def generate_pages
|
173
|
-
|
188
|
+
if @config['verbose_logging']
|
189
|
+
Dimples.logger.debug_generation('pages', @pages.length)
|
190
|
+
end
|
174
191
|
|
175
192
|
@pages.each do |page|
|
176
193
|
generate_page(page)
|
@@ -182,63 +199,73 @@ module Dimples
|
|
182
199
|
end
|
183
200
|
|
184
201
|
def generate_categories
|
185
|
-
|
202
|
+
if @config['verbose_logging']
|
203
|
+
Dimples.logger.debug_generation('category pages', @categories.length)
|
204
|
+
end
|
186
205
|
|
187
206
|
@categories.each_value do |category|
|
188
207
|
generate_category(category)
|
189
208
|
end
|
209
|
+
|
210
|
+
generate_category_feeds if @config['generation']['category_feeds']
|
190
211
|
end
|
191
212
|
|
192
213
|
def generate_category(category)
|
193
|
-
|
194
|
-
|
195
|
-
|
214
|
+
params = {
|
215
|
+
posts: category.posts,
|
216
|
+
title: category.name,
|
217
|
+
path: File.join(@output_paths[:categories], category.slug),
|
218
|
+
layout: @config['layouts']['category'],
|
219
|
+
context: { category: category.slug }
|
220
|
+
}
|
196
221
|
|
197
|
-
paginate(
|
222
|
+
paginate(params)
|
198
223
|
end
|
199
224
|
|
200
225
|
def generate_archives
|
201
|
-
%w
|
226
|
+
%w[year month day].each do |date_type|
|
202
227
|
if @config['generation']["#{date_type}_archives"]
|
203
|
-
|
204
|
-
|
205
|
-
if @config['verbose_logging']
|
206
|
-
Dimples.logger.debug_generation("#{date_type} archives", @archives[date_type_sym].count)
|
207
|
-
end
|
208
|
-
|
209
|
-
layout = @config['layouts']["#{date_type}_archives"]
|
210
|
-
|
211
|
-
@archives[date_type_sym].each_value do |posts|
|
212
|
-
title = posts[0].date.strftime(@config['date_formats'][date_type])
|
213
|
-
paths = [@output_paths[:archives], posts[0].year]
|
214
|
-
dates = { year: posts[0].year }
|
215
|
-
|
216
|
-
case date_type
|
217
|
-
when 'month'
|
218
|
-
paths << posts[0].month
|
219
|
-
dates[:month] = posts[0].month
|
220
|
-
when 'day'
|
221
|
-
paths.concat([posts[0].month, posts[0].day])
|
222
|
-
dates.merge(month: posts[0].month, day: posts[0].day)
|
223
|
-
end
|
224
|
-
|
225
|
-
paginate(posts: posts, title: title, paths: paths, layout: layout, context: dates)
|
226
|
-
end
|
228
|
+
generate_archive_posts(date_type)
|
227
229
|
end
|
228
230
|
end
|
229
231
|
end
|
230
232
|
|
233
|
+
def generate_archive_posts(date_type)
|
234
|
+
@archives[date_type.to_sym].each_value do |posts|
|
235
|
+
post = posts[0]
|
236
|
+
|
237
|
+
dates = case date_type
|
238
|
+
when 'year'
|
239
|
+
{ year: post.year }
|
240
|
+
when 'month'
|
241
|
+
{ year: post.year, month: post.month }
|
242
|
+
when 'day'
|
243
|
+
{ year: post.year, month: post.month, day: post.day }
|
244
|
+
end
|
245
|
+
|
246
|
+
params = {
|
247
|
+
posts: posts,
|
248
|
+
title: post.date.strftime(@config['date_formats'][date_type]),
|
249
|
+
path: File.join(@output_paths[:archives], dates.values),
|
250
|
+
layout: @config['layouts']["#{date_type}_archives"],
|
251
|
+
context: dates
|
252
|
+
}
|
253
|
+
|
254
|
+
paginate(params)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
231
258
|
def generate_feeds(path, options)
|
232
259
|
@config['feed_formats'].each do |format|
|
233
|
-
|
234
|
-
feed = @page_class.new(self)
|
260
|
+
next unless @templates[format]
|
235
261
|
|
236
|
-
|
237
|
-
feed.extension = format
|
238
|
-
feed.layout = format
|
262
|
+
feed = @page_class.new(self)
|
239
263
|
|
240
|
-
|
241
|
-
|
264
|
+
feed.filename = 'feed'
|
265
|
+
feed.extension = format
|
266
|
+
feed.layout = format
|
267
|
+
|
268
|
+
feed.write(feed.output_path(path), options)
|
242
269
|
end
|
243
270
|
end
|
244
271
|
|
@@ -252,64 +279,52 @@ module Dimples
|
|
252
279
|
path = File.join(@output_paths[:categories], category.slug)
|
253
280
|
posts = category.posts[0..@config['pagination']['per_page'] - 1]
|
254
281
|
|
255
|
-
generate_feeds(path, posts:
|
282
|
+
generate_feeds(path, posts: posts, category: category.slug)
|
256
283
|
end
|
257
284
|
end
|
258
285
|
|
259
286
|
def copy_assets
|
260
287
|
if Dir.exist?(@source_paths[:public])
|
261
|
-
Dimples.logger.debug(
|
288
|
+
Dimples.logger.debug('Copying assets...') if @config['verbose_logging']
|
262
289
|
|
263
290
|
path = File.join(@source_paths[:public], '.')
|
264
291
|
FileUtils.cp_r(path, @output_paths[:site])
|
265
292
|
end
|
266
293
|
rescue => e
|
267
|
-
raise Errors::GenerationError
|
294
|
+
raise Errors::GenerationError, "Site assets failed to copy (#{e.message})"
|
268
295
|
end
|
269
296
|
|
270
|
-
def paginate(posts:, title: nil,
|
271
|
-
raise Errors::GenerationError.new("'#{layout}' template not found during pagination") unless @templates.key?(layout)
|
272
|
-
|
297
|
+
def paginate(posts:, title: nil, path:, layout: false, context: {})
|
273
298
|
per_page = @config['pagination']['per_page']
|
274
|
-
|
275
|
-
|
276
|
-
page_path = paths[0].gsub(@output_paths[:site], '') + '/'
|
277
|
-
page_path += paths[1..-1].join('/') + '/' if paths.length > 1
|
299
|
+
pages = (posts.length.to_f / per_page.to_i).ceil
|
300
|
+
url = path.gsub(@output_paths[:site], '') + '/'
|
278
301
|
|
279
|
-
(1..
|
302
|
+
(1..pages).each do |index|
|
280
303
|
page = @page_class.new(self)
|
281
304
|
|
282
305
|
page.layout = layout
|
283
306
|
page.title = title || @templates[layout].title
|
284
307
|
|
285
|
-
|
286
|
-
output_path = File.join(paths, index != 1 ? "page#{index}" : '')
|
308
|
+
output_path = File.join(path, index != 1 ? "page#{index}" : '')
|
287
309
|
|
288
310
|
context[:posts] = posts.slice((index - 1) * per_page, per_page)
|
289
|
-
context[:pagination] =
|
311
|
+
context[:pagination] = build_pagination(index, pages, posts.count, url)
|
290
312
|
|
291
313
|
page.write(page.output_path(output_path), context)
|
292
314
|
end
|
293
315
|
end
|
294
316
|
|
295
|
-
def build_pagination(index,
|
317
|
+
def build_pagination(index, pages, item_count, url)
|
296
318
|
pagination = {
|
297
319
|
page: index,
|
298
|
-
pages:
|
320
|
+
pages: pages,
|
299
321
|
post_count: item_count,
|
300
|
-
|
322
|
+
url: url
|
301
323
|
}
|
302
324
|
|
303
|
-
if (
|
304
|
-
pagination[:previous_page] =
|
305
|
-
|
306
|
-
|
307
|
-
if (pagination[:page] + 1) <= pagination[:pages]
|
308
|
-
pagination[:next_page] = pagination[:page] + 1
|
309
|
-
end
|
310
|
-
|
311
|
-
if pagination[:previous_page]
|
312
|
-
pagination[:previous_page_url] = pagination[:path]
|
325
|
+
if (index - 1).positive?
|
326
|
+
pagination[:previous_page] = index - 1
|
327
|
+
pagination[:previous_page_url] = url
|
313
328
|
|
314
329
|
if pagination[:previous_page] != 1
|
315
330
|
page_string = "page#{pagination[:previous_page]}"
|
@@ -317,8 +332,9 @@ module Dimples
|
|
317
332
|
end
|
318
333
|
end
|
319
334
|
|
320
|
-
if
|
321
|
-
|
335
|
+
if (index + 1) <= pages
|
336
|
+
pagination[:next_page] = index + 1
|
337
|
+
page_string = "#{url}page#{pagination[:next_page]}"
|
322
338
|
pagination[:next_page_url] = page_string
|
323
339
|
end
|
324
340
|
|
data/lib/dimples/template.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A class that models a single template.
|
2
5
|
class Template
|
3
6
|
include Frontable
|
4
7
|
include Renderable
|
@@ -14,7 +17,7 @@ module Dimples
|
|
14
17
|
@slug = File.basename(path, File.extname(path))
|
15
18
|
@path = path
|
16
19
|
|
17
|
-
@contents =
|
20
|
+
@contents = read_with_front_matter(path)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
data/lib/dimples/version.rb
CHANGED
data/lib/dimples/writeable.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dimples
|
4
|
+
# A mixin class that neatly handles writing out a file.
|
2
5
|
module Writeable
|
3
6
|
def write(path, context = {})
|
4
7
|
output = context ? render(context) : contents
|
@@ -10,7 +13,8 @@ module Dimples
|
|
10
13
|
file.write(output)
|
11
14
|
end
|
12
15
|
rescue SystemCallError => e
|
13
|
-
|
16
|
+
error_message = "Failed to write #{path} (#{e.message})"
|
17
|
+
raise Errors::PublishingError, error_message
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dimples
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Bogan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-05-
|
11
|
+
date: 2017-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tilt
|