dimples 10.7.2 → 11.0.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: 4b348602f3096e0062a5bfe4a1a69c7396e28e06fb505b86e6f265418b31ae1e
4
- data.tar.gz: 2335b720796fdbd545f0ca7813f720de50ad6cf39f6aabf9a624f26cf569707c
3
+ metadata.gz: 4c840b0dffbd13241c53322349b2d4d8cc27702fd24e23e634f8aa3c68ccb7ef
4
+ data.tar.gz: a84f8dd4b99af20ad44a60bc42e4155731ed34aadd245987552f105cbc744ad2
5
5
  SHA512:
6
- metadata.gz: 907c0fec40c9bbd9f2b572021008f30cfa8e37a5c07a696eafdc9c7f4f45328e07ce05945be9806bc0df6dc9c67b090688a73918645df5b7d46390f10c9fc37b
7
- data.tar.gz: 9ad1d9698bd51ca77010a172e4901887f919a724285b20b0e451f11d33742aada0442aacb66f3ecd6e338ab195794dab40773be208131744188171892d8099c8
6
+ metadata.gz: 81dfeb441b90d5861bb75353317e71f9e528a6d6008f221f65af1b5ab98529d0046afc0fdf4bcb2cbb7507d94546784dea360366e427a0394664cbecf19c8f7b
7
+ data.tar.gz: f66eaa19302fe7c177160fb935fdab210d6e6c02afbeee936ae80880b1a225de94c3432433cee4773b3d4667d111903aaf552d6e7c0955b8f5662e22b1e28209
data/bin/dimples CHANGED
@@ -19,9 +19,9 @@ if File.exist?(config_path)
19
19
  end
20
20
 
21
21
  OptionParser.new do |parser|
22
- parser.banner = "Usage: dimples [options]"
22
+ parser.banner = 'Usage: dimples [options]'
23
23
 
24
- parser.on("-o [path]", "--output-path [path]", String, "The directory where your site will be generated") do |option|
24
+ parser.on('-o [path]', '--output-path [path]', String, 'The directory where your site will be generated') do |option|
25
25
  config[:build] = option unless option.nil?
26
26
  end
27
27
  end.parse!
@@ -6,7 +6,7 @@ module Dimples
6
6
  SOURCE_PATHS = {
7
7
  pages: 'pages',
8
8
  posts: 'posts',
9
- layouts: 'layouts',
9
+ templates: 'templates',
10
10
  static: 'static'
11
11
  }.freeze
12
12
 
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dimples
4
+ # Context used when rendering an item in a template
5
+ class Context
6
+ def self.from_hash(hash)
7
+ hash.transform_values! { |value| value.is_a?(Hash) ? Context.from_hash(value) : value }
8
+
9
+ Struct.new(*hash.keys) do |_klass|
10
+ def method_missing(_method_name, *_args)
11
+ nil
12
+ end
13
+
14
+ def respond_to_missing?(_method_name, _include_private = false)
15
+ true
16
+ end
17
+ end.new(*hash.values)
18
+ end
19
+ end
20
+ end
data/lib/dimples/entry.rb CHANGED
@@ -4,18 +4,15 @@ require 'forwardable'
4
4
  require 'pathname'
5
5
 
6
6
  module Dimples
7
- # A class representing a dynamic source entry
7
+ # A class representing a dynamic source entry that can generate rendered content
8
8
  class Entry
9
- include Forwardable
10
-
11
9
  FRONT_MATTER_PATTERN = /^(-{3}\n.*?\n?)^(-{3}*$\n?)/m
10
+ DEFAULT_FILENAME = 'index.html'
12
11
 
13
12
  attr_accessor :path, :contents, :rendered_contents
14
13
  attr_reader :metadata
15
14
 
16
- def initialize(site:, source:)
17
- @site = site
18
-
15
+ def initialize(source:)
19
16
  contents = case source
20
17
  when Pathname
21
18
  @path = File.expand_path(source)
@@ -28,79 +25,36 @@ module Dimples
28
25
  end
29
26
 
30
27
  def parse_metadata(contents)
31
- metadata = default_metadata
28
+ @metadata = default_metadata
32
29
 
33
30
  matches = contents.match(FRONT_MATTER_PATTERN)
34
31
  if matches
35
- metadata.merge!(YAML.safe_load(matches[1], symbolize_names: true, permitted_classes: [Date]))
32
+ @metadata.merge!(YAML.safe_load(matches[1], symbolize_names: true, permitted_classes: [Date]))
36
33
  @contents = matches.post_match.strip
37
34
  else
38
35
  @contents = contents
39
36
  end
40
-
41
- @metadata = Metadata.new(metadata)
42
- end
43
-
44
- def generate(output_path: nil, context: {})
45
- output_path = File.join(output_directory, filename) if output_path.nil?
46
- write(output_path: output_path, body: render(context: context))
47
37
  end
48
38
 
49
- def write(output_path:, body:)
50
- parent_directory = File.dirname(output_path)
51
-
52
- FileUtils.mkdir_p(parent_directory) unless File.directory?(parent_directory)
53
- File.write(output_path, body)
54
- end
55
-
56
- def url
57
- @url ||= output_directory.gsub(@site.config.build_paths[:root], '').tap do |url|
58
- url.concat(filename) unless filename == 'index.html'
59
- end
60
- end
61
-
62
- def render(context: {}, body: nil)
63
- context[:site] ||= @site
64
- context[:page] ||= self
65
-
66
- @rendered_contents = template.render(
67
- Object.new.tap do |render_context|
68
- context.each do |key, value|
69
- render_context.instance_variable_set("@#{key}", value)
70
- end
71
- end
72
- ) { body }
73
-
74
- template = @site.layouts[layout.to_sym] unless layout.nil?
75
- return @rendered_contents if template.nil?
76
-
77
- template.render(context: context, body: @rendered_contents)
78
- end
79
-
80
- def output_directory
81
- @output_directory ||= @site.config.build_paths[:root]
82
- end
83
-
84
- def template
85
- @template ||= Tilt::ERBTemplate.new { @contents }
39
+ def render(context: nil)
40
+ contents
86
41
  end
87
42
 
88
43
  def method_missing(method_name, *_args)
89
- method_sym = method_name.to_sym
90
-
91
- @metadata.send(method_sym)
44
+ metadata[method_name.to_sym]
92
45
  end
93
46
 
94
47
  def respond_to_missing?(method_name, _include_private = false)
95
- @metadata.respond_to?(method_name.to_sym) || super
48
+ metadata.key?(method_name.to_sym) || super
96
49
  end
97
50
 
98
51
  private
99
52
 
100
53
  def default_metadata
101
54
  {
55
+ date: @path ? File.birthtime(@path) : Time.now,
102
56
  layout: nil,
103
- filename: 'index.html'
57
+ filename: DEFAULT_FILENAME
104
58
  }
105
59
  end
106
60
  end
data/lib/dimples/pager.rb CHANGED
@@ -5,19 +5,21 @@ module Dimples
5
5
  class Pager
6
6
  include Enumerable
7
7
 
8
+ DEFAULT_PER_PAGE = 5
9
+
8
10
  attr_reader :current_page, :previous_page, :next_page, :page_count
9
11
 
10
- def self.paginate(site:, url:, posts:, context: {}, &block)
11
- new(site: site, url: url, posts: posts).paginate(context: context, &block)
12
+ def self.paginate(url:, posts:, per_page: DEFAULT_PER_PAGE, context: {}, &block)
13
+ new(url: url, posts: posts).paginate(context: context, &block)
12
14
  end
13
15
 
14
- def initialize(site:, url:, posts:)
15
- @site = site
16
+ def initialize(url:, posts:, per_page: DEFAULT_PER_PAGE)
16
17
  @url = url
18
+ @url << '/' unless @url[-1] == '/'
19
+
17
20
  @posts = posts
18
21
 
19
- @per_page = @site.config.pagination[:per_page]
20
- @page_prefix = @site.config.pagination[:page_prefix]
22
+ @per_page = per_page
21
23
  @page_count = (posts.length.to_f / @per_page.to_i).ceil
22
24
 
23
25
  step_to(1)
@@ -27,14 +29,7 @@ module Dimples
27
29
  (1..@page_count).each do |index|
28
30
  step_to(index)
29
31
 
30
- output_directory = File.join(@site.config.build_paths[:root], current_page_path)
31
-
32
- @site.layouts[:posts]&.generate(
33
- output_path: File.join(output_directory, 'index.html'),
34
- context: metadata.merge(context, url: current_page_url)
35
- )
36
-
37
- yield(output_directory, context) if block_given?
32
+ yield(current_page_path, context.merge(metadata)) if block_given?
38
33
  end
39
34
  end
40
35
 
@@ -63,7 +58,7 @@ module Dimples
63
58
  end
64
59
 
65
60
  def current_page_url
66
- @current_page == 1 ? @url : "#{@url}#{@page_prefix}#{@current_page}"
61
+ @current_page == 1 ? @url : "#{@url}page_#{@current_page}"
67
62
  end
68
63
 
69
64
  def first_page_url
@@ -71,17 +66,17 @@ module Dimples
71
66
  end
72
67
 
73
68
  def last_page_url
74
- @page_count == 1 ? @url : "#{@url}#{@page_prefix}#{@page_count}"
69
+ @page_count == 1 ? @url : "#{@url}page_#{@page_count}"
75
70
  end
76
71
 
77
72
  def previous_page_url
78
73
  return unless @previous_page
79
74
 
80
- @previous_page == 1 ? @url : "#{@url}#{@page_prefix}#{@previous_page}"
75
+ @previous_page == 1 ? @url : "#{@url}page_#{@previous_page}"
81
76
  end
82
77
 
83
78
  def next_page_url
84
- "#{@url}#{@page_prefix}#{@next_page}" if @next_page
79
+ "#{@url}page_#{@next_page}" if @next_page
85
80
  end
86
81
 
87
82
  def urls
@@ -97,14 +92,14 @@ module Dimples
97
92
  def metadata
98
93
  {
99
94
  posts: posts_at(current_page),
100
- pagination: Metadata.new(
95
+ pagination: {
101
96
  current_page: @current_page,
102
97
  page_count: @page_count,
103
98
  post_count: @posts.count,
104
99
  previous_page: @previous_page,
105
100
  next_page: @next_page,
106
101
  urls: urls
107
- )
102
+ }
108
103
  }
109
104
  end
110
105
  end
data/lib/dimples/post.rb CHANGED
@@ -1,36 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- # A page from a site with a date.
4
+ # A single post for a site.
5
5
  class Post < Entry
6
- def initialize(site:, path:)
7
- super(site: site, source: Pathname.new(path))
6
+ @markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML)
7
+
8
+ class << self
9
+ attr_reader :markdown
8
10
  end
9
11
 
10
- def output_directory
11
- @output_directory ||= File.dirname(@path).gsub(
12
- @site.config.source_paths[:posts],
13
- @site.config.build_paths[:posts]
14
- ).concat("/#{slug}/")
12
+ def initialize(path:)
13
+ super(source: Pathname.new(path))
15
14
  end
16
15
 
17
16
  def slug
18
- File.basename(@path, File.extname(@path))&.downcase
17
+ File.basename(path, File.extname(path))&.downcase
19
18
  end
20
19
 
21
- def template
22
- @template ||= Tilt::RedcarpetTemplate.new { @contents }
20
+ def render(context: nil)
21
+ Dimples::Post.markdown.render(contents)
23
22
  end
24
23
 
25
24
  private
26
25
 
27
26
  def default_metadata
28
- super.tap do |defaults|
29
- defaults[:layout] = 'post'
30
- defaults[:slug] = slug
31
- defaults[:date] = File.birthtime(@path)
32
- defaults[:categories] = []
33
- end
27
+ super.merge!(
28
+ layout: 'post',
29
+ slug: slug,
30
+ categories: []
31
+ )
34
32
  end
35
33
  end
36
34
  end
data/lib/dimples/site.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'date'
4
4
  require 'fileutils'
5
- require 'tilt'
5
+ require 'redcarpet'
6
6
  require 'yaml'
7
7
 
8
8
  module Dimples
@@ -29,20 +29,22 @@ module Dimples
29
29
  end
30
30
 
31
31
  def posts
32
- @posts ||= Dir.glob(File.join(@config.source_paths[:posts], '**', '*.markdown')).map do |path|
33
- Dimples::Post.new(site: self, path: path)
34
- end.sort_by! { |post| post.date }.reverse!
32
+ @posts ||= source_files(path: :posts, extension: 'markdown').map do |path|
33
+ Dimples::Post.new(path: path)
34
+ end
35
+ .sort_by!(&:date)
36
+ .reverse!
35
37
  end
36
38
 
37
39
  def pages
38
- @pages ||= Dir.glob(File.join(@config.source_paths[:pages], '**', '*.erb')).map do |path|
39
- Dimples::Page.new(site: self, path: path)
40
+ @pages ||= source_files(path: :pages, extension: 'erb').map do |path|
41
+ Dimples::Template.new(path: path)
40
42
  end
41
43
  end
42
44
 
43
- def layouts
44
- @layouts ||= Dir.glob(File.join(@config.source_paths[:layouts], '**', '*.erb')).to_h do |path|
45
- [File.basename(path, '.erb').to_sym, Dimples::Layout.new(site: self, path: path)]
45
+ def templates
46
+ @templates ||= source_files(path: :templates, extension: 'erb').to_h do |path|
47
+ [File.basename(path, '.erb').to_sym, Dimples::Template.new(path: path)]
46
48
  end
47
49
  end
48
50
 
@@ -59,20 +61,33 @@ module Dimples
59
61
 
60
62
  private
61
63
 
64
+ def source_files(path:, extension:)
65
+ Dir.glob(File.join(@config.source_paths[path], '**', "*.#{extension}"))
66
+ end
67
+
62
68
  def generate_posts
63
69
  posts.each { |post| generate_post(post) }
64
70
 
65
- Pager.paginate(
66
- site: self,
67
- url: @config.build_paths[:posts].gsub(@config.build_paths[:root], '').concat('/'),
68
- posts: posts
69
- )
71
+ url = @config.build_paths[:posts].gsub(@config.build_paths[:root], '').concat('/')
72
+
73
+ Pager.paginate(url: url, posts: posts) do |url, page_context|
74
+ generate_entry(
75
+ entry: templates[:posts],
76
+ output_path: File.join(@config.build_paths[:root], url),
77
+ context: page_context
78
+ )
79
+ end
70
80
 
71
81
  generate_feed(output_path: @config.build_paths[:root], posts: posts) if @config.generation[:main_feed]
72
82
  end
73
83
 
74
84
  def generate_post(post)
75
- post.generate
85
+ path = File.dirname(post.path).gsub(
86
+ @config.source_paths[:posts],
87
+ @config.build_paths[:posts]
88
+ ).concat("/#{post.slug}/")
89
+
90
+ generate_entry(entry: post, output_path: path)
76
91
  end
77
92
 
78
93
  def generate_pages
@@ -80,7 +95,12 @@ module Dimples
80
95
  end
81
96
 
82
97
  def generate_page(page)
83
- page.generate
98
+ path = File.dirname(page.path).gsub(
99
+ @config.source_paths[:pages],
100
+ @config.build_paths[:root]
101
+ ).concat('/')
102
+
103
+ generate_entry(entry: page, output_path: path)
84
104
  end
85
105
 
86
106
  def generate_categories
@@ -88,11 +108,16 @@ module Dimples
88
108
  context = { title: category.capitalize, category: category }
89
109
 
90
110
  Pager.paginate(
91
- site: self,
92
111
  url: "/categories/#{category}/",
93
112
  posts: posts,
94
113
  context: context
95
- )
114
+ ) do |url, page_context|
115
+ generate_entry(
116
+ entry: templates[:posts],
117
+ output_path: File.join(@config.build_paths[:root], url),
118
+ context: page_context
119
+ )
120
+ end
96
121
 
97
122
  if @config.generation[:category_feeds]
98
123
  generate_feed(output_path: File.join(@config.build_paths[:root], 'categories', category), posts: posts)
@@ -101,14 +126,36 @@ module Dimples
101
126
  end
102
127
 
103
128
  def generate_feed(output_path:, posts:)
104
- return if layouts[:feed].nil?
129
+ return if templates[:feed].nil?
105
130
 
106
- layouts[:feed].generate(
107
- output_path: File.join(output_path, 'feed.atom'),
131
+ generate_entry(
132
+ entry: templates[:feed],
133
+ output_path: output_path,
108
134
  context: { posts: posts.slice(0, 10) }
109
135
  )
110
136
  end
111
137
 
138
+ def generate_entry(entry:, output_path:, context: {})
139
+ unless context[:url]
140
+ url = output_path.gsub(@config.build_paths[:root], '')
141
+ url = File.join(url, entry.filename) unless entry.filename == Dimples::Entry::DEFAULT_FILENAME
142
+
143
+ context[:url] = url
144
+ end
145
+
146
+ context = { page: Context.from_hash(entry.metadata.merge(context)), site: self }
147
+ body = entry.contents
148
+ full_path = File.join(output_path, entry.filename)
149
+
150
+ until entry.nil?
151
+ body = entry.render(context: context) { body }
152
+ entry = templates[entry.layout&.to_sym]
153
+ end
154
+
155
+ FileUtils.mkdir_p(output_path) unless File.directory?(output_path)
156
+ File.write(full_path, body)
157
+ end
158
+
112
159
  def prepare_output_directory
113
160
  if Dir.exist?(@config.build_paths[:root])
114
161
  unless @config.generation[:overwrite_existing_site]
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module Dimples
6
+ # A class for a single ERB template file used on a site.
7
+ class Template < Entry
8
+ def initialize(path:)
9
+ super(source: Pathname.new(path))
10
+ end
11
+
12
+ def render(context:)
13
+ context.merge!(metadata)
14
+
15
+ context.each do |key, value|
16
+ instance_variable_set("@#{key}", value)
17
+ end
18
+
19
+ erb = ERB.new(contents)
20
+ erb.result(binding)
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- VERSION = '10.7.2'
4
+ VERSION = '11.0.0'
5
5
  end
data/lib/dimples.rb CHANGED
@@ -3,10 +3,9 @@
3
3
  $LOAD_PATH.unshift(__dir__)
4
4
 
5
5
  require 'dimples/config'
6
- require 'dimples/metadata'
6
+ require 'dimples/context'
7
7
  require 'dimples/pager'
8
8
  require 'dimples/site'
9
9
  require 'dimples/entry'
10
- require 'dimples/page'
10
+ require 'dimples/template'
11
11
  require 'dimples/post'
12
- require 'dimples/layout'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dimples
3
3
  version: !ruby/object:Gem::Version
4
- version: 10.7.2
4
+ version: 11.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Bogan
@@ -37,20 +37,6 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.6'
40
- - !ruby/object:Gem::Dependency
41
- name: tilt
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '2.3'
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '2.3'
54
40
  description: A simple tool for building static websites.
55
41
  email:
56
42
  - d+dimples@waferbaby.com
@@ -62,13 +48,12 @@ files:
62
48
  - bin/dimples
63
49
  - lib/dimples.rb
64
50
  - lib/dimples/config.rb
51
+ - lib/dimples/context.rb
65
52
  - lib/dimples/entry.rb
66
- - lib/dimples/layout.rb
67
- - lib/dimples/metadata.rb
68
- - lib/dimples/page.rb
69
53
  - lib/dimples/pager.rb
70
54
  - lib/dimples/post.rb
71
55
  - lib/dimples/site.rb
56
+ - lib/dimples/template.rb
72
57
  - lib/dimples/version.rb
73
58
  homepage: http://github.com/waferbaby/dimples
74
59
  licenses:
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- # A class for a single layout used on a site.
5
- class Layout < Entry
6
- def initialize(site:, path:)
7
- super(site: site, source: Pathname.new(path))
8
- end
9
- end
10
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- # A tiny wrapper around metadata for rendering
5
- class Metadata
6
- def initialize(source)
7
- source.each do |key, value|
8
- self.class.send(:attr_reader, key)
9
- instance_variable_set("@#{key}", value.is_a?(Hash) ? Metadata.new(value) : value)
10
- end
11
- end
12
-
13
- def method_missing(_method_name, *_args)
14
- nil
15
- end
16
-
17
- def respond_to_missing?(_method_name, _include_private = false)
18
- true
19
- end
20
- end
21
- end
data/lib/dimples/page.rb DELETED
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- # A single page on a site.
5
- class Page < Entry
6
- def initialize(site:, path:)
7
- super(site: site, source: Pathname.new(path))
8
- end
9
-
10
- def output_directory
11
- @output_directory ||= File.dirname(@path).gsub(
12
- @site.config.source_paths[:pages],
13
- @site.config.build_paths[:root]
14
- ).concat('/')
15
- end
16
-
17
- private
18
-
19
- def default_metadata
20
- super.merge!(layout: 'page')
21
- end
22
- end
23
- end