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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8a5a0e150bc568f6593260d6af73dfcdfc2979ff7e39866d3cc798c706955ff
4
- data.tar.gz: 7c5521a81ac0325d431c1027287bf216e4669b341bcf5e6f6fabfa9f05beb0a5
3
+ metadata.gz: 882aeff0d91ba61d58f331bedabeba0c865dbb7ef355c1fdafde7e1605113d2e
4
+ data.tar.gz: 8ddfc8ea5bcbce38a35c8d0153f96adc4866f5529a074884e966b92a65dce642
5
5
  SHA512:
6
- metadata.gz: 73b0502dcdd803eef073c4d075d7f3d2eaa9f6a9b8897f1c5d21d0c49b7c3682c91aba70b7b89c4140c65a14df7e6a0ed83fdaa42b6925327521929cdd37f58b
7
- data.tar.gz: 3750f6c5e82b6d4f84a659bb8f15a36c969cd4698eaa736946f4fd81d7a5a28ec49e3d3529820d6a0b1cd3b3ac6f2e786b83431b0de40bf21a16d60fbd505de3
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
- trap('SIGINT') do
12
- puts 'Generation cancelled!'
13
- exit!
14
- end
8
+ path = if ARGV[0]
9
+ File.expand_path(ARGV[0])
10
+ else
11
+ File.join(Dir.pwd(), 'site')
12
+ end
15
13
 
16
- valid_commands = %w[build]
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
- # frozen_string_literal: true
1
+ require_relative 'document'
2
2
 
3
3
  module Dimples
4
- # A single page on a site.
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
- PER_PAGE_DEFAULT = 10
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, options = {})
14
+ def initialize(url, posts)
41
15
  @url = url
42
16
  @posts = posts
43
- @per_page = options[:per_page] || PER_PAGE_DEFAULT
44
- @page_prefix = options[:page_prefix] || 'page_'
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
- Hashie::Mash.new(
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
- # frozen_string_literal: true
1
+ require_relative 'document'
2
2
 
3
- module Dimples
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
- @metadata[:layout] ||= @site.config.layouts.post
14
-
15
- @metadata[:date] = Date.new(parts[1].to_i, parts[2].to_i, parts[3].to_i)
16
- @metadata[:slug] = parts[4]
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 month
31
- @month ||= @metadata[:date].strftime('%m')
11
+ def layout
12
+ @metadata.fetch(:layout, 'post')
32
13
  end
33
14
 
34
- def day
35
- @day ||= @metadata[:date].strftime('%d')
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
- attr_reader :config
7
- attr_reader :categories
8
- attr_reader :errors
9
- attr_reader :paths
10
- attr_reader :posts
11
- attr_reader :pages
12
- attr_reader :archive
13
- attr_reader :templates
14
- attr_reader :latest_post
15
-
16
- def initialize(config = {})
17
- @config = Configuration.prepare(config)
18
-
19
- @paths = {}.tap do |paths|
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
- prepare
26
+ scan_posts
27
+ scan_pages
28
+ scan_templates
29
29
  end
30
30
 
31
31
  def generate
32
- prepare
32
+ if Dir.exist?(@paths[:destination])
33
+ puts "Error: The output directory (#{@paths[:destination]}) already exists."
34
+ return
35
+ end
33
36
 
34
- read_templates
35
- read_posts
36
- read_pages
37
+ Dir.mkdir(@paths[:destination])
37
38
 
38
- create_output_directory
39
- copy_static_assets
39
+ generate_posts
40
+ generate_pages
41
+ generate_categories
40
42
 
41
- publish_posts
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
- def data
50
- @config.data || {}
51
- end
46
+ private
52
47
 
53
- def inspect
54
- "#<#{self.class} @paths=#{paths}>"
48
+ def read_files(path)
49
+ Dir[File.join(path, '**', '*.*')].sort
55
50
  end
56
51
 
57
- private
52
+ def scan_posts
53
+ @posts = read_files(@paths[:posts]).map do |path|
54
+ Dimples::Post.new(path)
55
+ end
58
56
 
59
- def prepare
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
- @latest_post = nil
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 read_files(path)
73
- Dir[File.join(path, '**', '*.*')].sort
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 read_templates
77
- @templates = {}
78
-
79
- read_files(@paths[:templates]).each do |path|
80
- basename = File.basename(path, File.extname(path))
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 read_posts
92
- @posts = read_files(@paths[:posts]).map do |path|
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
- @latest_post = @posts[0]
87
+ Dir.mkdir(directory_path) unless Dir.exist?(directory_path)
88
+ File.write(path, content)
100
89
  end
101
90
 
102
- def read_pages
103
- @pages = read_files(@paths[:pages]).map { |path| Page.new(self, path) }
104
- end
91
+ def generate_paginated_posts(posts, path, context = {})
92
+ pager = Dimples::Pager.new(path.sub(@paths[:destination], '') + '/', posts)
105
93
 
106
- def categorise_post(post)
107
- post.categories.each do |slug|
108
- slug_sym = slug.to_sym
94
+ pager.each do |index|
95
+ page = Dimples::Page.new()
96
+ page.metadata[:layout] = 'posts'
109
97
 
110
- @categories[slug_sym] ||= Category.new(self, slug)
111
- @categories[slug_sym].posts << post
112
- end
113
- end
98
+ page_path = if index == 1
99
+ path
100
+ else
101
+ File.join(path, "page_#{index}")
102
+ end
114
103
 
115
- def create_output_directory
116
- if Dir.exist?(@paths[:destination])
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 copy_static_assets
127
- return unless Dir.exist?(@paths[:static])
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(@paths[:destination], post.url.split('/'))
137
- post.write(path)
114
+ path = File.join(directory_path, post.slug, post.filename)
115
+ write_file(path, render(post, post: post))
138
116
  end
139
117
 
140
- published_posts = @posts.select { |post| !post.draft }
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 publish_pages
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
- page.write(path)
133
+ write_file(File.join(path, page.filename), render(page, page: page))
168
134
  end
169
135
  end
170
136
 
171
- def publish_archives
172
- @archive.years.each do |year|
173
- publish_archive(year)
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
- @archive.days(year, month).each do |day|
181
- publish_archive(year, month, day)
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 publish_archive(year, month = nil, day = nil)
188
- date_type = if day
189
- 'day'
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
- Dimples::Pager.paginate(self, posts.reverse, path, layout, data)
150
+ write_file(File.join(path, 'feed.atom'), render(page, posts: posts))
211
151
  end
212
152
 
213
- def publish_categories
214
- @categories.each_value do |category|
215
- path = File.join(
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 publish_feeds(posts, path, context = {})
237
- @config.feed_formats.each do |format|
238
- feed = Feed.new(self, format)
158
+ def render(object, context = {}, content = nil)
159
+ context[:site] ||= self
160
+
161
+ output = object.render(context, content)
239
162
 
240
- feed.feed_posts = posts.slice(0, @config.pagination.per_page)
241
- feed.write(path, context)
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
@@ -1,29 +1,6 @@
1
- # frozen_string_literal: true
1
+ require_relative 'document'
2
2
 
3
3
  module Dimples
4
- # A single template used when rendering pages, posts and other templates.
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- VERSION = '6.6.0'
4
+ VERSION = '7.0'
5
5
  end
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: 6.6.0
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: 2021-02-20 00:00:00.000000000 Z
11
+ date: 2022-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: hashie
14
+ name: erubi
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.1'
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: '4.1'
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: codeclimate-test-reporter
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: '2.7'
76
- type: :development
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: '2.7'
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/archive.rb
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.4
119
+ rubygems_version: 3.1.6
182
120
  signing_key:
183
121
  specification_version: 4
184
122
  summary: A basic static site generator
@@ -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
@@ -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
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- class PublishingError < StandardError
5
- end
6
-
7
- class RenderingError < StandardError
8
- end
9
-
10
- class GenerationError < StandardError
11
- end
12
- end
data/lib/dimples/feed.rb DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- # A single feed.
5
- class Feed < Page
6
- def initialize(site, format)
7
- super(site)
8
-
9
- self.filename = 'feed'
10
- self.extension = format
11
- self.layout = "feeds.#{format}"
12
- end
13
- end
14
- end
@@ -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
@@ -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