dimples 6.6.0 → 7.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 +6 -74
- data/lib/dimples/document.rb +70 -0
- data/lib/dimples/page.rb +2 -65
- data/lib/dimples/pager.rb +6 -32
- data/lib/dimples/post.rb +10 -29
- data/lib/dimples/site.rb +99 -174
- data/lib/dimples/template.rb +2 -25
- data/lib/dimples/version.rb +1 -1
- data/lib/dimples.rb +0 -15
- metadata +11 -73
- data/lib/dimples/archive.rb +0 -64
- data/lib/dimples/category.rb +0 -18
- data/lib/dimples/configuration.rb +0 -76
- data/lib/dimples/errors.rb +0 -12
- data/lib/dimples/feed.rb +0 -14
- data/lib/dimples/frontmatter.rb +0 -19
- data/lib/dimples/renderer.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 882aeff0d91ba61d58f331bedabeba0c865dbb7ef355c1fdafde7e1605113d2e
|
4
|
+
data.tar.gz: 8ddfc8ea5bcbce38a35c8d0153f96adc4866f5529a074884e966b92a65dce642
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc9caa2de2a10ac6a30f84876ad3a3e9bd070b2e3e9783f38763035d286ec46d55343fa6fbf5cb44c6b72fe3c67d773af7918cbcb714cdb10f2c4b4a6b52b1e4
|
7
|
+
data.tar.gz: 04510c31f0ee4de0d1e035ddf56003f12e4553bdaaf1b4a8f82d24c0344bae443443b8d4f73c58e6ae7c3a5447e73f734f315964c30dcb400f85b28fa9066042
|
data/bin/dimples
CHANGED
@@ -4,79 +4,11 @@
|
|
4
4
|
$LOAD_PATH.unshift(File.join(__dir__, '..', 'lib'))
|
5
5
|
|
6
6
|
require 'dimples'
|
7
|
-
require 'dimples/version'
|
8
|
-
require 'optimist'
|
9
|
-
require 'json'
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
path = if ARGV[0]
|
9
|
+
File.expand_path(ARGV[0])
|
10
|
+
else
|
11
|
+
File.join(Dir.pwd(), 'site')
|
12
|
+
end
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
options = Optimist.options do
|
19
|
-
version "dimples v#{Dimples::VERSION}"
|
20
|
-
banner <<-BANNER
|
21
|
-
A simple static site generator.
|
22
|
-
|
23
|
-
Usage:
|
24
|
-
dimples <#{valid_commands.join('|')}> [options]
|
25
|
-
|
26
|
-
Options:
|
27
|
-
BANNER
|
28
|
-
|
29
|
-
opt :config, 'Config file path', type: :string
|
30
|
-
opt :source, 'Source directory', type: :string
|
31
|
-
opt :destination, 'Destination directory', type: :string
|
32
|
-
end
|
33
|
-
|
34
|
-
Optimist.educate if ARGV.empty?
|
35
|
-
command = ARGV[0]
|
36
|
-
|
37
|
-
unless valid_commands.include?(command)
|
38
|
-
Optimist.die "Command must be '#{valid_commands.join('\', \'')}'"
|
39
|
-
end
|
40
|
-
|
41
|
-
source_path = if options[:source]
|
42
|
-
File.expand_path(options[:source])
|
43
|
-
else
|
44
|
-
Dir.pwd
|
45
|
-
end
|
46
|
-
|
47
|
-
config_path = options[:config] || File.join(source_path, 'config.json')
|
48
|
-
|
49
|
-
unless File.exist?(config_path)
|
50
|
-
Optimist.die "Unable to find config file (#{config_path})"
|
51
|
-
end
|
52
|
-
|
53
|
-
begin
|
54
|
-
file_contents = File.read(config_path)
|
55
|
-
Optimist.die "Config file is empty (#{config_path})" if file_contents.empty?
|
56
|
-
|
57
|
-
config = JSON.parse(file_contents, symbolize_names: true)
|
58
|
-
rescue JSON::ParserError
|
59
|
-
Optimist.die "Invalid or malformed config file (#{config_path})"
|
60
|
-
end
|
61
|
-
|
62
|
-
config[:source] = source_path
|
63
|
-
|
64
|
-
if options[:destination]
|
65
|
-
config[:destination] = File.expand_path(options[:destination])
|
66
|
-
end
|
67
|
-
|
68
|
-
site = Dimples::Site.new(config)
|
69
|
-
|
70
|
-
case command.to_sym
|
71
|
-
when :build
|
72
|
-
puts 'Building site...'
|
73
|
-
|
74
|
-
site.generate
|
75
|
-
|
76
|
-
if site.errors.empty?
|
77
|
-
puts "Done! Your site has been built in #{site.paths[:destination]}."
|
78
|
-
else
|
79
|
-
puts 'Generation failed:'
|
80
|
-
site.errors.each { |error| puts error }
|
81
|
-
end
|
82
|
-
end
|
14
|
+
Dimples::Site.generate(path)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Dimples
|
4
|
+
class Document
|
5
|
+
FRONT_MATTER_PATTERN = /^(-{3}\n.*?\n?)^(-{3}*$\n?)/m.freeze
|
6
|
+
|
7
|
+
attr_accessor :metadata, :contents, :path, :rendered_contents
|
8
|
+
|
9
|
+
def initialize(path = nil)
|
10
|
+
@path = path
|
11
|
+
@metadata = {}
|
12
|
+
|
13
|
+
if @path
|
14
|
+
@contents = File.read(path)
|
15
|
+
|
16
|
+
if matches = contents.match(FRONT_MATTER_PATTERN)
|
17
|
+
@metadata = YAML.load(matches[1], symbolize_names: true)
|
18
|
+
@contents = matches.post_match.strip
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def filename
|
24
|
+
"#{basename}.#{extension}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def basename
|
28
|
+
@metadata.fetch(:filename, 'index')
|
29
|
+
end
|
30
|
+
|
31
|
+
def extension
|
32
|
+
@metadata.fetch(:extension, 'html')
|
33
|
+
end
|
34
|
+
|
35
|
+
def layout
|
36
|
+
@metadata.fetch(:layout, nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
def render(context = {}, content = '')
|
40
|
+
context_obj = Object.new
|
41
|
+
context.each do |key, value|
|
42
|
+
context_obj.instance_variable_set("@#{key}", value)
|
43
|
+
end
|
44
|
+
|
45
|
+
@rendered_contents = renderer.render(context_obj) { content }
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def renderer
|
51
|
+
@renderer ||= begin
|
52
|
+
callback = proc { contents }
|
53
|
+
|
54
|
+
if @path
|
55
|
+
Tilt.new(@path, {}, &callback)
|
56
|
+
else
|
57
|
+
Tilt::StringTemplate.new(&callback)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def method_missing(method_name, *args, &block)
|
63
|
+
if @metadata.key?(method_name)
|
64
|
+
@metadata[method_name]
|
65
|
+
else
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/dimples/page.rb
CHANGED
@@ -1,69 +1,6 @@
|
|
1
|
-
|
1
|
+
require_relative 'document'
|
2
2
|
|
3
3
|
module Dimples
|
4
|
-
|
5
|
-
class Page
|
6
|
-
attr_accessor :contents
|
7
|
-
attr_accessor :metadata
|
8
|
-
attr_accessor :path
|
9
|
-
|
10
|
-
def initialize(site, path = nil)
|
11
|
-
@site = site
|
12
|
-
@path = path
|
13
|
-
|
14
|
-
if @path
|
15
|
-
data = File.read(@path)
|
16
|
-
@contents, @metadata = FrontMatter.parse(data)
|
17
|
-
else
|
18
|
-
@contents = ''
|
19
|
-
@metadata = {}
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def filename
|
24
|
-
@metadata[:filename] || 'index'
|
25
|
-
end
|
26
|
-
|
27
|
-
def extension
|
28
|
-
@metadata[:extension] || 'html'
|
29
|
-
end
|
30
|
-
|
31
|
-
def render(context = {})
|
32
|
-
metadata = @metadata.dup
|
33
|
-
metadata.merge!(context[:page]) if context[:page]
|
34
|
-
|
35
|
-
context[:page] = Hashie::Mash.new(metadata)
|
36
|
-
|
37
|
-
renderer.render(context)
|
38
|
-
end
|
39
|
-
|
40
|
-
def write(output_directory, context = {})
|
41
|
-
FileUtils.mkdir_p(output_directory) unless Dir.exist?(output_directory)
|
42
|
-
output_path = File.join(output_directory, "#{filename}.#{extension}")
|
43
|
-
|
44
|
-
File.write(output_path, render(context))
|
45
|
-
rescue SystemCallError => e
|
46
|
-
raise PublishingError, "Failed to publish file at #{output_path} (#{e})"
|
47
|
-
end
|
48
|
-
|
49
|
-
private
|
50
|
-
|
51
|
-
def renderer
|
52
|
-
@renderer ||= Renderer.new(@site, self)
|
53
|
-
end
|
54
|
-
|
55
|
-
def method_missing(method_name, *args, &block)
|
56
|
-
if @metadata.key?(method_name)
|
57
|
-
@metadata[method_name]
|
58
|
-
elsif (matches = method_name.match(/([a-z_]+)=/))
|
59
|
-
@metadata[matches[1].to_sym] = args[0]
|
60
|
-
else
|
61
|
-
super
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def respond_to_missing?(method_name, include_private = false)
|
66
|
-
@metadata.key?(method_name) || method_name.match?(/([a-z_]+)=/) || super
|
67
|
-
end
|
4
|
+
class Page < Document
|
68
5
|
end
|
69
6
|
end
|
data/lib/dimples/pager.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Dimples
|
4
|
-
# A paginated collection of posts that can be walked forward or backwards.
|
5
4
|
class Pager
|
6
|
-
|
5
|
+
PER_PAGE = 5
|
7
6
|
|
8
7
|
include Enumerable
|
9
8
|
|
@@ -11,37 +10,12 @@ module Dimples
|
|
11
10
|
attr_reader :previous_page
|
12
11
|
attr_reader :next_page
|
13
12
|
attr_reader :page_count
|
14
|
-
attr_reader :item_count
|
15
|
-
|
16
|
-
def self.paginate(site, posts, path, layout, context = {})
|
17
|
-
pager = Pager.new(
|
18
|
-
path.sub(site.paths[:destination], '') + '/',
|
19
|
-
posts,
|
20
|
-
site.config.pagination
|
21
|
-
)
|
22
|
-
|
23
|
-
pager.each do |index|
|
24
|
-
page = Page.new(site)
|
25
|
-
page.layout = layout
|
26
|
-
|
27
|
-
page_path = if index == 1
|
28
|
-
path
|
29
|
-
else
|
30
|
-
File.join(path, "page_#{index}")
|
31
|
-
end
|
32
|
-
|
33
|
-
page.write(
|
34
|
-
page_path,
|
35
|
-
context.merge(pagination: pager.to_context)
|
36
|
-
)
|
37
|
-
end
|
38
|
-
end
|
39
13
|
|
40
|
-
def initialize(url, posts
|
14
|
+
def initialize(url, posts)
|
41
15
|
@url = url
|
42
16
|
@posts = posts
|
43
|
-
@per_page =
|
44
|
-
@page_prefix =
|
17
|
+
@per_page = PER_PAGE
|
18
|
+
@page_prefix = 'page_'
|
45
19
|
@page_count = (posts.length.to_f / @per_page.to_i).ceil
|
46
20
|
|
47
21
|
step_to(1)
|
@@ -94,7 +68,7 @@ module Dimples
|
|
94
68
|
end
|
95
69
|
|
96
70
|
def to_context
|
97
|
-
|
71
|
+
{
|
98
72
|
posts: posts_at(current_page),
|
99
73
|
current_page: @current_page,
|
100
74
|
page_count: @page_count,
|
@@ -108,7 +82,7 @@ module Dimples
|
|
108
82
|
previous_page: previous_page_url,
|
109
83
|
next_page: next_page_url
|
110
84
|
}
|
111
|
-
|
85
|
+
}
|
112
86
|
end
|
113
87
|
end
|
114
88
|
end
|
data/lib/dimples/post.rb
CHANGED
@@ -1,38 +1,19 @@
|
|
1
|
-
|
1
|
+
require_relative 'document'
|
2
2
|
|
3
|
-
|
4
|
-
# A single dated post on a site.
|
5
|
-
class Post < Page
|
6
|
-
POST_FILENAME = /(\d{4})-(\d{2})-(\d{2})-(.+)/.freeze
|
7
|
-
|
8
|
-
def initialize(site, path)
|
9
|
-
super
|
10
|
-
|
11
|
-
parts = File.basename(path, File.extname(path)).match(POST_FILENAME)
|
3
|
+
require 'date'
|
12
4
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@metadata
|
17
|
-
@metadata[:categories] ||= []
|
18
|
-
@metadata[:draft] ||= false
|
19
|
-
end
|
20
|
-
|
21
|
-
def url
|
22
|
-
path = date.strftime(draft ? @site.config.paths.drafts : @site.config.paths.posts)
|
23
|
-
"/#{path}/#{slug}/"
|
24
|
-
end
|
25
|
-
|
26
|
-
def year
|
27
|
-
@year ||= @metadata[:date].strftime('%Y')
|
5
|
+
module Dimples
|
6
|
+
class Post < Document
|
7
|
+
def date
|
8
|
+
@metadata.fetch(:date, DateTime.now)
|
28
9
|
end
|
29
10
|
|
30
|
-
def
|
31
|
-
@
|
11
|
+
def layout
|
12
|
+
@metadata.fetch(:layout, 'post')
|
32
13
|
end
|
33
14
|
|
34
|
-
def
|
35
|
-
@
|
15
|
+
def slug
|
16
|
+
File.basename(@path, '.markdown')
|
36
17
|
end
|
37
18
|
end
|
38
19
|
end
|
data/lib/dimples/site.rb
CHANGED
@@ -1,159 +1,125 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'pager'
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'tilt'
|
7
|
+
|
3
8
|
module Dimples
|
4
|
-
# A collection of pages, posts and templates that can generate a website.
|
5
9
|
class Site
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
paths[:source] = File.expand_path(@config.source)
|
21
|
-
paths[:destination] = File.expand_path(Time.now.strftime(@config.destination))
|
22
|
-
|
23
|
-
%w[pages posts static templates].each do |type|
|
24
|
-
paths[type.to_sym] = File.join(paths[:source], type)
|
25
|
-
end
|
10
|
+
def self.generate(output_path)
|
11
|
+
new(output_path).generate
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :posts, :categories
|
15
|
+
|
16
|
+
def initialize(output_path)
|
17
|
+
@paths = {
|
18
|
+
source: File.expand_path(Dir.pwd),
|
19
|
+
destination: File.expand_path(output_path)
|
20
|
+
}
|
21
|
+
|
22
|
+
%w[pages posts static templates].each do |type|
|
23
|
+
@paths[type.to_sym] = File.join(@paths[:source], type)
|
26
24
|
end
|
27
25
|
|
28
|
-
|
26
|
+
scan_posts
|
27
|
+
scan_pages
|
28
|
+
scan_templates
|
29
29
|
end
|
30
30
|
|
31
31
|
def generate
|
32
|
-
|
32
|
+
if Dir.exist?(@paths[:destination])
|
33
|
+
puts "Error: The output directory (#{@paths[:destination]}) already exists."
|
34
|
+
return
|
35
|
+
end
|
33
36
|
|
34
|
-
|
35
|
-
read_posts
|
36
|
-
read_pages
|
37
|
+
Dir.mkdir(@paths[:destination])
|
37
38
|
|
38
|
-
|
39
|
-
|
39
|
+
generate_posts
|
40
|
+
generate_pages
|
41
|
+
generate_categories
|
40
42
|
|
41
|
-
|
42
|
-
publish_pages
|
43
|
-
publish_archives if @config.generation.year_archives
|
44
|
-
publish_categories if @config.generation.categories
|
45
|
-
rescue PublishingError, RenderingError, GenerationError => e
|
46
|
-
@errors << e
|
43
|
+
copy_assets
|
47
44
|
end
|
48
45
|
|
49
|
-
|
50
|
-
@config.data || {}
|
51
|
-
end
|
46
|
+
private
|
52
47
|
|
53
|
-
def
|
54
|
-
|
48
|
+
def read_files(path)
|
49
|
+
Dir[File.join(path, '**', '*.*')].sort
|
55
50
|
end
|
56
51
|
|
57
|
-
|
52
|
+
def scan_posts
|
53
|
+
@posts = read_files(@paths[:posts]).map do |path|
|
54
|
+
Dimples::Post.new(path)
|
55
|
+
end
|
58
56
|
|
59
|
-
|
60
|
-
@archive = Dimples::Archive.new
|
57
|
+
@posts.sort_by! { |post| post.date }.reverse!
|
61
58
|
|
62
59
|
@categories = {}
|
63
|
-
@templates = {}
|
64
|
-
|
65
|
-
@pages = []
|
66
|
-
@posts = []
|
67
|
-
@errors = []
|
68
60
|
|
69
|
-
@
|
61
|
+
@posts.each do |post|
|
62
|
+
post.categories.each do |category|
|
63
|
+
@categories[category] ||= []
|
64
|
+
@categories[category] << post
|
65
|
+
end
|
66
|
+
end
|
70
67
|
end
|
71
68
|
|
72
|
-
def
|
73
|
-
|
69
|
+
def scan_pages
|
70
|
+
@pages = read_files(@paths[:pages]).map do |path|
|
71
|
+
Dimples::Page.new(path)
|
72
|
+
end
|
74
73
|
end
|
75
74
|
|
76
|
-
def
|
77
|
-
@templates = {}
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
dir_name = File.dirname(path)
|
82
|
-
|
83
|
-
unless dir_name == @paths[:templates]
|
84
|
-
basename = dir_name.split(File::SEPARATOR)[-1] + '.' + basename
|
75
|
+
def scan_templates
|
76
|
+
@templates = {}.tap do |templates|
|
77
|
+
read_files(@paths[:templates]).each do |path|
|
78
|
+
key = File.basename(path, '.erb')
|
79
|
+
templates[key] = Dimples::Template.new(path)
|
85
80
|
end
|
86
|
-
|
87
|
-
@templates[basename] = Template.new(self, path)
|
88
81
|
end
|
89
82
|
end
|
90
83
|
|
91
|
-
def
|
92
|
-
|
93
|
-
Post.new(self, path).tap do |post|
|
94
|
-
@archive.add_post(post)
|
95
|
-
categorise_post(post)
|
96
|
-
end
|
97
|
-
end.reverse
|
84
|
+
def write_file(path, content)
|
85
|
+
directory_path = File.dirname(path)
|
98
86
|
|
99
|
-
|
87
|
+
Dir.mkdir(directory_path) unless Dir.exist?(directory_path)
|
88
|
+
File.write(path, content)
|
100
89
|
end
|
101
90
|
|
102
|
-
def
|
103
|
-
|
104
|
-
end
|
91
|
+
def generate_paginated_posts(posts, path, context = {})
|
92
|
+
pager = Dimples::Pager.new(path.sub(@paths[:destination], '') + '/', posts)
|
105
93
|
|
106
|
-
|
107
|
-
|
108
|
-
|
94
|
+
pager.each do |index|
|
95
|
+
page = Dimples::Page.new()
|
96
|
+
page.metadata[:layout] = 'posts'
|
109
97
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
98
|
+
page_path = if index == 1
|
99
|
+
path
|
100
|
+
else
|
101
|
+
File.join(path, "page_#{index}")
|
102
|
+
end
|
114
103
|
|
115
|
-
|
116
|
-
|
117
|
-
FileUtils.rm_r(@paths[:destination], secure: true)
|
118
|
-
else
|
119
|
-
FileUtils.mkdir_p(@paths[:destination])
|
104
|
+
context.merge!(pagination: pager.to_context)
|
105
|
+
write_file(File.join(page_path, page.filename), render(page, context))
|
120
106
|
end
|
121
|
-
rescue StandardError => e
|
122
|
-
message = "Couldn't prepare the output directory (#{e.message})"
|
123
|
-
raise GenerationError, message
|
124
107
|
end
|
125
108
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
FileUtils.cp_r(File.join(@paths[:static], '.'), @paths[:destination])
|
130
|
-
rescue StandardError => e
|
131
|
-
raise GenerationError, "Failed to copy site assets (#{e.message})"
|
132
|
-
end
|
109
|
+
def generate_posts
|
110
|
+
directory_path = File.join(@paths[:destination], 'posts')
|
111
|
+
Dir.mkdir(directory_path)
|
133
112
|
|
134
|
-
def publish_posts
|
135
113
|
@posts.each do |post|
|
136
|
-
path = File.join(
|
137
|
-
|
114
|
+
path = File.join(directory_path, post.slug, post.filename)
|
115
|
+
write_file(path, render(post, post: post))
|
138
116
|
end
|
139
117
|
|
140
|
-
|
141
|
-
|
142
|
-
if @config.generation.main_feed
|
143
|
-
publish_feeds(published_posts, @paths[:destination])
|
144
|
-
end
|
145
|
-
|
146
|
-
return unless @config.generation.paginated_posts
|
147
|
-
|
148
|
-
Dimples::Pager.paginate(
|
149
|
-
self,
|
150
|
-
published_posts,
|
151
|
-
File.join(@paths[:destination], @config.paths.paginated_posts),
|
152
|
-
@config.layouts.paginated_post
|
153
|
-
)
|
118
|
+
generate_paginated_posts(@posts, directory_path)
|
119
|
+
generate_feed(@posts.slice(0, 10), @paths[:destination])
|
154
120
|
end
|
155
121
|
|
156
|
-
def
|
122
|
+
def generate_pages
|
157
123
|
@pages.each do |page|
|
158
124
|
path = if page.path
|
159
125
|
File.dirname(page.path).sub(
|
@@ -164,82 +130,41 @@ module Dimples
|
|
164
130
|
@paths[:destination]
|
165
131
|
end
|
166
132
|
|
167
|
-
|
133
|
+
write_file(File.join(path, page.filename), render(page, page: page))
|
168
134
|
end
|
169
135
|
end
|
170
136
|
|
171
|
-
def
|
172
|
-
@
|
173
|
-
|
174
|
-
next unless @config.generation.month_archives
|
175
|
-
|
176
|
-
@archive.months(year).each do |month|
|
177
|
-
publish_archive(year, month)
|
178
|
-
next unless @config.generation.day_archives
|
137
|
+
def generate_categories
|
138
|
+
@categories.each do |category, posts|
|
139
|
+
category_path = File.join(@paths[:destination], 'categories', category)
|
179
140
|
|
180
|
-
|
181
|
-
|
182
|
-
end
|
183
|
-
end
|
141
|
+
generate_paginated_posts(posts, category_path, category: category)
|
142
|
+
generate_feed(posts.slice(0, 10), category_path)
|
184
143
|
end
|
185
144
|
end
|
186
145
|
|
187
|
-
def
|
188
|
-
|
189
|
-
|
190
|
-
elsif month
|
191
|
-
'month'
|
192
|
-
else
|
193
|
-
'year'
|
194
|
-
end
|
195
|
-
|
196
|
-
posts = @archive.posts_for_date(year, month, day)
|
197
|
-
|
198
|
-
date_parts = [year, month, day].compact
|
199
|
-
path = File.join(@paths[:destination], @config.paths.archives, date_parts)
|
200
|
-
layout = @config.layouts.date_archive
|
201
|
-
|
202
|
-
data = {
|
203
|
-
page: {
|
204
|
-
title: posts[0].date.strftime(@config.date_formats[date_type]),
|
205
|
-
archive_date: posts[0].date,
|
206
|
-
archive_type: date_type
|
207
|
-
}
|
208
|
-
}
|
146
|
+
def generate_feed(posts, path)
|
147
|
+
page = Dimples::Page.new()
|
148
|
+
page.metadata[:layout] = 'feed'
|
209
149
|
|
210
|
-
|
150
|
+
write_file(File.join(path, 'feed.atom'), render(page, posts: posts))
|
211
151
|
end
|
212
152
|
|
213
|
-
def
|
214
|
-
|
215
|
-
|
216
|
-
@paths[:destination],
|
217
|
-
@config.paths.categories,
|
218
|
-
category.slug
|
219
|
-
)
|
220
|
-
|
221
|
-
category_posts = category.posts.reverse
|
222
|
-
context = { page: { title: category.name, category: category } }
|
223
|
-
|
224
|
-
Dimples::Pager.paginate(
|
225
|
-
self,
|
226
|
-
category_posts,
|
227
|
-
path,
|
228
|
-
@config.layouts.category,
|
229
|
-
context
|
230
|
-
)
|
231
|
-
|
232
|
-
publish_feeds(category_posts, path, context)
|
233
|
-
end
|
153
|
+
def copy_assets
|
154
|
+
return unless Dir.exist?(@paths[:static])
|
155
|
+
FileUtils.cp_r(File.join(@paths[:static], '.'), @paths[:destination])
|
234
156
|
end
|
235
157
|
|
236
|
-
def
|
237
|
-
|
238
|
-
|
158
|
+
def render(object, context = {}, content = nil)
|
159
|
+
context[:site] ||= self
|
160
|
+
|
161
|
+
output = object.render(context, content)
|
239
162
|
|
240
|
-
|
241
|
-
|
163
|
+
if object.layout && @templates[object.layout]
|
164
|
+
output = render(@templates[object.layout], context, output)
|
242
165
|
end
|
166
|
+
|
167
|
+
output
|
243
168
|
end
|
244
169
|
end
|
245
170
|
end
|
data/lib/dimples/template.rb
CHANGED
@@ -1,29 +1,6 @@
|
|
1
|
-
|
1
|
+
require_relative 'document'
|
2
2
|
|
3
3
|
module Dimples
|
4
|
-
|
5
|
-
class Template
|
6
|
-
attr_accessor :path
|
7
|
-
attr_accessor :contents
|
8
|
-
attr_accessor :metadata
|
9
|
-
|
10
|
-
def initialize(site, path)
|
11
|
-
@site = site
|
12
|
-
@path = path
|
13
|
-
|
14
|
-
data = File.read(path)
|
15
|
-
@contents, @metadata = FrontMatter.parse(data)
|
16
|
-
end
|
17
|
-
|
18
|
-
def render(context = {}, body = nil)
|
19
|
-
context[:template] ||= Hashie::Mash.new(@metadata)
|
20
|
-
renderer.render(context, body)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def renderer
|
26
|
-
@renderer ||= Renderer.new(@site, self)
|
27
|
-
end
|
4
|
+
class Template < Document
|
28
5
|
end
|
29
6
|
end
|
data/lib/dimples/version.rb
CHANGED
data/lib/dimples.rb
CHANGED
@@ -2,22 +2,7 @@
|
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift(__dir__)
|
4
4
|
|
5
|
-
require 'fileutils'
|
6
|
-
require 'hashie'
|
7
|
-
require 'tilt'
|
8
|
-
require 'yaml'
|
9
|
-
|
10
|
-
require 'dimples/archive'
|
11
|
-
require 'dimples/category'
|
12
|
-
require 'dimples/configuration'
|
13
|
-
require 'dimples/errors'
|
14
|
-
require 'dimples/frontmatter'
|
15
|
-
require 'dimples/pager'
|
16
|
-
require 'dimples/renderer'
|
17
|
-
|
18
5
|
require 'dimples/page'
|
19
|
-
require 'dimples/feed'
|
20
6
|
require 'dimples/post'
|
21
7
|
require 'dimples/template'
|
22
|
-
|
23
8
|
require 'dimples/site'
|
metadata
CHANGED
@@ -1,43 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dimples
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: '7.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:
|
11
|
+
date: 2022-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: erubi
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.10'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: optimist
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '3.0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '3.0'
|
26
|
+
version: '1.10'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: tilt
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,33 +39,19 @@ dependencies:
|
|
53
39
|
- !ruby/object:Gem::Version
|
54
40
|
version: '2.0'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: erubis
|
42
|
+
name: redcarpet
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
72
44
|
requirements:
|
73
45
|
- - "~>"
|
74
46
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
76
|
-
type: :
|
47
|
+
version: '3.5'
|
48
|
+
type: :runtime
|
77
49
|
prerelease: false
|
78
50
|
version_requirements: !ruby/object:Gem::Requirement
|
79
51
|
requirements:
|
80
52
|
- - "~>"
|
81
53
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
54
|
+
version: '3.5'
|
83
55
|
- !ruby/object:Gem::Dependency
|
84
56
|
name: rake
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,20 +66,6 @@ dependencies:
|
|
94
66
|
- - "~>"
|
95
67
|
- !ruby/object:Gem::Version
|
96
68
|
version: 12.3.3
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: redcarpet
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '3.5'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '3.5'
|
111
69
|
- !ruby/object:Gem::Dependency
|
112
70
|
name: rspec
|
113
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +80,6 @@ dependencies:
|
|
122
80
|
- - "~>"
|
123
81
|
- !ruby/object:Gem::Version
|
124
82
|
version: '3.10'
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: simplecov
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - "~>"
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: '0.21'
|
132
|
-
type: :development
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - "~>"
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: '0.21'
|
139
83
|
description: A simple tool for building static websites.
|
140
84
|
email:
|
141
85
|
- d+dimples@waferbaby.com
|
@@ -146,16 +90,10 @@ extra_rdoc_files: []
|
|
146
90
|
files:
|
147
91
|
- bin/dimples
|
148
92
|
- lib/dimples.rb
|
149
|
-
- lib/dimples/
|
150
|
-
- lib/dimples/category.rb
|
151
|
-
- lib/dimples/configuration.rb
|
152
|
-
- lib/dimples/errors.rb
|
153
|
-
- lib/dimples/feed.rb
|
154
|
-
- lib/dimples/frontmatter.rb
|
93
|
+
- lib/dimples/document.rb
|
155
94
|
- lib/dimples/page.rb
|
156
95
|
- lib/dimples/pager.rb
|
157
96
|
- lib/dimples/post.rb
|
158
|
-
- lib/dimples/renderer.rb
|
159
97
|
- lib/dimples/site.rb
|
160
98
|
- lib/dimples/template.rb
|
161
99
|
- lib/dimples/version.rb
|
@@ -178,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
178
116
|
- !ruby/object:Gem::Version
|
179
117
|
version: '0'
|
180
118
|
requirements: []
|
181
|
-
rubygems_version: 3.1.
|
119
|
+
rubygems_version: 3.1.6
|
182
120
|
signing_key:
|
183
121
|
specification_version: 4
|
184
122
|
summary: A basic static site generator
|
data/lib/dimples/archive.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dimples
|
4
|
-
# A collection of posts, organised by date.
|
5
|
-
class Archive
|
6
|
-
def initialize
|
7
|
-
@years = {}
|
8
|
-
end
|
9
|
-
|
10
|
-
def add_post(post)
|
11
|
-
year(post.year)[:posts] << post
|
12
|
-
month(post.year, post.month)[:posts] << post
|
13
|
-
day(post.year, post.month, post.day)[:posts] << post
|
14
|
-
end
|
15
|
-
|
16
|
-
def years
|
17
|
-
@years.keys
|
18
|
-
end
|
19
|
-
|
20
|
-
def months(year)
|
21
|
-
year(year)[:months].keys
|
22
|
-
end
|
23
|
-
|
24
|
-
def days(year, month)
|
25
|
-
month(year, month)[:days].keys
|
26
|
-
end
|
27
|
-
|
28
|
-
def posts_for_date(year, month = nil, day = nil)
|
29
|
-
if day
|
30
|
-
day_posts(year, month, day)
|
31
|
-
elsif month
|
32
|
-
month_posts(year, month)
|
33
|
-
else
|
34
|
-
year_posts(year)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def year_posts(year)
|
39
|
-
year(year)[:posts]
|
40
|
-
end
|
41
|
-
|
42
|
-
def month_posts(year, month)
|
43
|
-
month(year, month)[:posts]
|
44
|
-
end
|
45
|
-
|
46
|
-
def day_posts(year, month, day)
|
47
|
-
day(year, month, day)[:posts]
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def year(year)
|
53
|
-
@years[year.to_s] ||= { months: {}, posts: [] }
|
54
|
-
end
|
55
|
-
|
56
|
-
def month(year, month)
|
57
|
-
year(year)[:months][month.to_s] ||= { days: {}, posts: [] }
|
58
|
-
end
|
59
|
-
|
60
|
-
def day(year, month, day)
|
61
|
-
month(year, month)[:days][day.to_s] ||= { posts: [] }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/dimples/category.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dimples
|
4
|
-
# A single post category for a site.
|
5
|
-
class Category
|
6
|
-
attr_reader :name
|
7
|
-
attr_reader :slug
|
8
|
-
attr_accessor :posts
|
9
|
-
|
10
|
-
def initialize(site, slug)
|
11
|
-
@site = site
|
12
|
-
@slug = slug
|
13
|
-
@name = @site.config.category_names[slug.to_sym] || slug.capitalize
|
14
|
-
|
15
|
-
@posts = []
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dimples
|
4
|
-
# Default configuration options for a site.
|
5
|
-
module Configuration
|
6
|
-
def self.prepare(config)
|
7
|
-
Hashie::Mash.new(defaults).deep_merge(config)
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.defaults
|
11
|
-
{
|
12
|
-
source: Dir.pwd,
|
13
|
-
destination: File.join(Dir.pwd, 'public'),
|
14
|
-
paths: default_paths,
|
15
|
-
generation: default_generation,
|
16
|
-
layouts: default_layouts,
|
17
|
-
pagination: default_pagination,
|
18
|
-
date_formats: default_date_formats,
|
19
|
-
feed_formats: default_feed_formats,
|
20
|
-
category_names: {},
|
21
|
-
rendering: {}
|
22
|
-
}
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.default_paths
|
26
|
-
{
|
27
|
-
archives: 'archives',
|
28
|
-
paginated_posts: 'posts',
|
29
|
-
posts: 'archives/%Y/%m/%d',
|
30
|
-
drafts: 'archives/drafts/%Y/%m/%d',
|
31
|
-
categories: 'archives/categories'
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.default_generation
|
36
|
-
{
|
37
|
-
paginated_posts: true,
|
38
|
-
year_archives: true,
|
39
|
-
month_archives: true,
|
40
|
-
day_archives: true,
|
41
|
-
categories: true,
|
42
|
-
main_feed: true,
|
43
|
-
category_feeds: true
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.default_layouts
|
48
|
-
{
|
49
|
-
post: 'post',
|
50
|
-
category: 'category',
|
51
|
-
paginated_post: 'paginated_post',
|
52
|
-
archive: 'archive',
|
53
|
-
date_archive: 'archive'
|
54
|
-
}
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.default_date_formats
|
58
|
-
{
|
59
|
-
year: '%Y',
|
60
|
-
month: '%Y-%m',
|
61
|
-
day: '%Y-%m-%d'
|
62
|
-
}
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.default_feed_formats
|
66
|
-
['atom']
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.default_pagination
|
70
|
-
{
|
71
|
-
page_prefix: 'page_',
|
72
|
-
per_page: 10
|
73
|
-
}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
data/lib/dimples/errors.rb
DELETED
data/lib/dimples/feed.rb
DELETED
data/lib/dimples/frontmatter.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dimples
|
4
|
-
# Adds the ability to parse front matter from a file.
|
5
|
-
class FrontMatter
|
6
|
-
FRONT_MATTER_PATTERN = /^(-{3}\n.*?\n?)^(-{3}*$\n?)/m.freeze
|
7
|
-
|
8
|
-
def self.parse(contents)
|
9
|
-
if (matches = contents.match(FRONT_MATTER_PATTERN))
|
10
|
-
metadata = Hashie.symbolize_keys(YAML.safe_load(matches[1]))
|
11
|
-
contents = matches.post_match.strip
|
12
|
-
else
|
13
|
-
metadata = {}
|
14
|
-
end
|
15
|
-
|
16
|
-
[contents, metadata]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/dimples/renderer.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dimples
|
4
|
-
# A wrapper around Tilt, tied to a single post, page or template.
|
5
|
-
class Renderer
|
6
|
-
def initialize(site, source)
|
7
|
-
@site = site
|
8
|
-
@source = source
|
9
|
-
end
|
10
|
-
|
11
|
-
def render(context = {}, body = nil)
|
12
|
-
context[:site] ||= @site
|
13
|
-
context[:pagination] ||= nil
|
14
|
-
|
15
|
-
begin
|
16
|
-
output = engine.render(scope, context) { body }.strip
|
17
|
-
rescue StandardError => e
|
18
|
-
raise RenderingError,
|
19
|
-
"Unable to render #{@source.path || 'dynamic file'} (#{e})"
|
20
|
-
end
|
21
|
-
|
22
|
-
@source.metadata[:rendered_contents] = output
|
23
|
-
|
24
|
-
if @source.metadata[:layout]
|
25
|
-
template = @site.templates[@source.metadata[:layout]]
|
26
|
-
end
|
27
|
-
|
28
|
-
return output if template.nil?
|
29
|
-
|
30
|
-
template.render(context, output)
|
31
|
-
end
|
32
|
-
|
33
|
-
def engine
|
34
|
-
@engine ||= begin
|
35
|
-
callback = proc { @source.contents }
|
36
|
-
|
37
|
-
if @source.path
|
38
|
-
extension = File.extname(@source.path)
|
39
|
-
options = @site.config.rendering[extension.to_sym] || {}
|
40
|
-
|
41
|
-
Tilt.new(@source.path, options, &callback)
|
42
|
-
else
|
43
|
-
Tilt::StringTemplate.new(&callback)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def scope
|
49
|
-
@scope ||= Object.new.tap do |scope|
|
50
|
-
scope.instance_variable_set(:@site, @site)
|
51
|
-
|
52
|
-
scope.class.send(:define_method, :render) do |layout, locals = {}|
|
53
|
-
@site.templates[layout]&.render(locals)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|