dimples 10.3.1 → 10.5.1

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: 9b26a3e1592398021aab828178c2dbb71bb521f99db69503b196195806745721
4
- data.tar.gz: aae282b44ca14b4a244ef9f1827c7f186f654b7ebd83ed8818b4af3388eb8910
3
+ metadata.gz: 8184ca5d9bfa136040e8f3c8156113b4513609ea1b51deb5b5c158e8e1dff141
4
+ data.tar.gz: 10339f5e0e2a64aea876a0047594479361433637c7b7ac39283b8242044d416a
5
5
  SHA512:
6
- metadata.gz: e6c9b35b7da2435a8361a006e668b18249b56c34747ca1f0bd0774ed0c6d652211e04a1a9edae0a5e776c018cdd1767a2261bc276cc67d1819d070c25a6aa8c4
7
- data.tar.gz: dc34dc37e9d0961a2445aea5132647cc88ab0da6886274a45c1a830e5d32f247e20c3c16f0a726582ae87b826a00df6da8804eb051088dd4a0a5799e415618cd
6
+ metadata.gz: b46cb1009cf405021d7fdd26a0183267c4cbd1c4221ea8c5cc004b5770fe6f0090dff1408aa06ffb1784da93c2a87565a3832c84e7f4ba5a9f5e2b7e26f53105
7
+ data.tar.gz: 74cf7f30146d038b2f137c47b35f965708105a7e69997a61e051e60caca9595085b0d0dfcc7bcc770c93cd71b04834995d4c21ac687fc9a6145f256fe64d18d7
data/bin/dimples CHANGED
@@ -18,7 +18,7 @@ if File.exist?(config_path)
18
18
  end
19
19
 
20
20
  begin
21
- Dimples::Site.generate(config:)
21
+ Dimples::Site.generate(config: config)
22
22
  rescue StandardError => e
23
23
  puts "Error generating site: #{e}"
24
24
  end
@@ -5,14 +5,16 @@ module Dimples
5
5
  class Config
6
6
  SOURCE_PATHS = { pages: 'pages', posts: 'posts', layouts: 'layouts', static: 'static' }.freeze
7
7
 
8
- attr_accessor :source_paths, :build_paths, :pagination
8
+ attr_accessor :source_paths, :build_paths, :site, :pagination, :generation
9
9
 
10
10
  def self.defaults
11
11
  {
12
- build: './site',
13
12
  source: Dir.pwd,
13
+ build: './site',
14
14
  pathnames: { posts: 'posts', categories: 'categories' },
15
- pagination: { page_prefix: 'page_', per_page: 5 }
15
+ site: { name: nil, domain: nil },
16
+ pagination: { page_prefix: 'page_', per_page: 5 },
17
+ generation: { api: false, main_feed: true, category_feeds: false }
16
18
  }
17
19
  end
18
20
 
@@ -21,7 +23,9 @@ module Dimples
21
23
 
22
24
  @source_paths = expand_paths(File.expand_path(options[:source]), SOURCE_PATHS.dup)
23
25
  @build_paths = expand_paths(File.expand_path(options[:build]), options[:pathnames])
26
+ @site = options[:site]
24
27
  @pagination = options[:pagination]
28
+ @generation = options[:generation]
25
29
  end
26
30
 
27
31
  def expand_paths(root, paths)
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require 'pathname'
5
+
6
+ module Dimples
7
+ module Entries
8
+ # A class representing a dynamic source entry
9
+ class Base
10
+ include Forwardable
11
+
12
+ FRONT_MATTER_PATTERN = /^(-{3}\n.*?\n?)^(-{3}*$\n?)/m
13
+
14
+ attr_accessor :path, :contents, :rendered_contents
15
+ attr_reader :metadata
16
+
17
+ def initialize(site:, source:)
18
+ @site = site
19
+
20
+ contents = case source
21
+ when Pathname
22
+ @path = File.expand_path(source)
23
+ File.read(@path)
24
+ when String
25
+ source
26
+ end
27
+
28
+ parse_metadata(contents)
29
+ end
30
+
31
+ def parse_metadata(contents)
32
+ metadata = default_metadata
33
+
34
+ matches = contents.match(FRONT_MATTER_PATTERN)
35
+ if matches
36
+ metadata.merge!(YAML.safe_load(matches[1], symbolize_names: true, permitted_classes: [Date]))
37
+ @contents = matches.post_match.strip
38
+ else
39
+ @contents = contents
40
+ end
41
+
42
+ @metadata = Metadata.new(metadata)
43
+ end
44
+
45
+ def write(output_path: nil, context: {})
46
+ output_path = File.join(output_directory, @metadata[:filename]) if output_path.nil?
47
+
48
+ parent_directory = File.dirname(output_path)
49
+ output = render(context: context)
50
+
51
+ FileUtils.mkdir_p(parent_directory) unless File.directory?(parent_directory)
52
+ File.write(output_path, output)
53
+ end
54
+
55
+ def render(context: {}, body: nil)
56
+ context[:site] ||= @site.metadata
57
+ context[:page] ||= @metadata
58
+
59
+ @rendered_contents = template.render(Metadata.new(context)) { body }
60
+
61
+ layout = @site.layouts[@metadata.layout.to_sym] if @metadata.layout
62
+ return @rendered_contents if layout.nil?
63
+
64
+ layout.render(context: context, body: @rendered_contents)
65
+ end
66
+
67
+ def output_directory
68
+ @output_directory ||= @site.config.build_paths[:root]
69
+ end
70
+
71
+ def template
72
+ @template ||= Tilt::ERBTemplate.new { @contents }
73
+ end
74
+
75
+ def method_missing(method_name, *_args)
76
+ @metadata.send(method_name)
77
+ end
78
+
79
+ def respond_to_missing?(method_name, include_private = false)
80
+ true
81
+ end
82
+
83
+ private
84
+
85
+ def default_metadata
86
+ {
87
+ layout: nil,
88
+ filename: 'index.html'
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- module Sources
4
+ module Entries
5
5
  # A class for a single layout used on a site.
6
6
  class Layout < Base
7
- def template
8
- @template ||= Tilt::ERBTemplate.new { @contents }
7
+ def initialize(site:, path:)
8
+ super(site: site, source: Pathname.new(path))
9
9
  end
10
10
  end
11
11
  end
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- module Sources
4
+ module Entries
5
5
  # A single page on a site.
6
6
  class Page < Base
7
+ def initialize(site:, path:)
8
+ super(site: site, source: Pathname.new(path))
9
+ end
10
+
7
11
  def output_directory
8
12
  @output_directory ||= File.dirname(@path).gsub(
9
13
  @site.config.source_paths[:pages],
@@ -12,13 +16,7 @@ module Dimples
12
16
  end
13
17
 
14
18
  def url
15
- super.tap do |url|
16
- url.concat(filename) unless filename == 'index.html'
17
- end
18
- end
19
-
20
- def template
21
- @template ||= Tilt::ERBTemplate.new { @contents }
19
+ output_directory.tap { |url| url.concat(filename) unless filename == 'index.html' }
22
20
  end
23
21
 
24
22
  private
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- module Sources
4
+ module Entries
5
5
  # A page from a site with a date.
6
6
  class Post < Base
7
+ def initialize(site:, path:)
8
+ super(site: site, source: Pathname.new(path))
9
+ end
10
+
7
11
  def output_directory
8
12
  @output_directory ||= File.dirname(@path).gsub(
9
13
  @site.config.source_paths[:posts],
@@ -12,7 +16,7 @@ module Dimples
12
16
  end
13
17
 
14
18
  def slug
15
- File.basename(@path)
19
+ File.basename(@path, '.markdown')
16
20
  end
17
21
 
18
22
  def template
@@ -24,7 +28,7 @@ module Dimples
24
28
  def default_metadata
25
29
  super.tap do |defaults|
26
30
  defaults[:layout] = 'post'
27
- defaults[:slug] = File.basename(@path, '.markdown')
31
+ defaults[:slug] = slug
28
32
  defaults[:date] = File.birthtime(@path)
29
33
  defaults[:categories] = []
30
34
  end
@@ -1,9 +1,6 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Dimples
4
- # A class representing metadata passed into a template for rendering.
5
2
  class Metadata
6
- attr_reader :keys
3
+ include Enumerable
7
4
 
8
5
  def initialize(source)
9
6
  source.each do |key, value|
@@ -11,9 +8,37 @@ module Dimples
11
8
  instance_variable_set("@#{key}", build(value))
12
9
  end
13
10
 
14
- @keys = source.keys
11
+ @data = source
12
+ end
13
+
14
+ def keys
15
+ @data.keys
15
16
  end
16
17
 
18
+ def [](key)
19
+ @data[key]
20
+ end
21
+
22
+ def each(&block)
23
+ @data.each(&block)
24
+ end
25
+
26
+ def each_key(&block)
27
+ @data.keys.each(&block)
28
+ end
29
+
30
+ def method_missing(method_name, *_args)
31
+ return @data[method_name] if @data.key?(method_name)
32
+
33
+ nil
34
+ end
35
+
36
+ def respond_to_missing?(method_name, include_private = false)
37
+ @data.key?(method_name) || super
38
+ end
39
+
40
+ private
41
+
17
42
  def build(item)
18
43
  case item
19
44
  when Array
@@ -24,13 +49,5 @@ module Dimples
24
49
  item
25
50
  end
26
51
  end
27
-
28
- def method_missing(_method_name, *_args)
29
- nil
30
- end
31
-
32
- def respond_to_missing?(_method_name, _include_private)
33
- true
34
- end
35
52
  end
36
53
  end
data/lib/dimples/pager.rb CHANGED
@@ -7,8 +7,8 @@ module Dimples
7
7
 
8
8
  attr_reader :current_page, :previous_page, :next_page, :page_count
9
9
 
10
- def self.paginate(site:, url:, posts:, metadata: {})
11
- new(site:, url:, posts:).paginate(metadata)
10
+ def self.paginate(site:, url:, posts:, context: {})
11
+ new(site: site, url: url, posts: posts).paginate(context: context)
12
12
  end
13
13
 
14
14
  def initialize(site:, url:, posts:)
@@ -23,13 +23,13 @@ module Dimples
23
23
  step_to(1)
24
24
  end
25
25
 
26
- def paginate(metadata)
26
+ def paginate(context: {})
27
27
  (1..@page_count).each do |index|
28
28
  step_to(index)
29
29
 
30
- @site.layouts['posts']&.write(
30
+ @site.layouts[:posts]&.write(
31
31
  output_path: File.join(@site.config.build_paths[:root], current_page_url, 'index.html'),
32
- metadata: metadata.merge(pagination: self.metadata, url: current_page_url)
32
+ context: context.merge(pagination: self.metadata, url: current_page_url)
33
33
  )
34
34
  end
35
35
  end
data/lib/dimples/site.rb CHANGED
@@ -11,7 +11,7 @@ module Dimples
11
11
  attr_accessor :config
12
12
 
13
13
  def self.generate(config: {})
14
- new(config:).generate
14
+ new(config: config).generate
15
15
  end
16
16
 
17
17
  def initialize(config: {})
@@ -30,26 +30,26 @@ module Dimples
30
30
 
31
31
  def posts
32
32
  @posts ||= Dir.glob(File.join(@config.source_paths[:posts], '**', '*.markdown')).map do |path|
33
- Dimples::Sources::Post.new(site: self, path:)
34
- end.sort_by!(&:date).reverse!
33
+ Dimples::Entries::Post.new(site: self, path: path)
34
+ end.sort_by! { |post| post.metadata[:date] }.reverse!
35
35
  end
36
36
 
37
37
  def pages
38
38
  @pages ||= Dir.glob(File.join(@config.source_paths[:pages], '**', '*.erb')).map do |path|
39
- Dimples::Sources::Page.new(site: self, path:)
39
+ Dimples::Entries::Page.new(site: self, path: path)
40
40
  end
41
41
  end
42
42
 
43
43
  def layouts
44
44
  @layouts ||= Dir.glob(File.join(@config.source_paths[:layouts], '**', '*.erb')).to_h do |path|
45
- [File.basename(path, '.erb'), Dimples::Sources::Layout.new(site: self, path:)]
45
+ [File.basename(path, '.erb').to_sym, Dimples::Entries::Layout.new(site: self, path: path)]
46
46
  end
47
47
  end
48
48
 
49
49
  def categories
50
50
  @categories ||= {}.tap do |categories|
51
51
  posts.each do |post|
52
- post.categories.each do |category|
52
+ post.metadata[:categories].each do |category|
53
53
  categories[category] ||= []
54
54
  categories[category].append(post)
55
55
  end
@@ -69,10 +69,10 @@ module Dimples
69
69
  Pager.paginate(
70
70
  site: self,
71
71
  url: @config.build_paths[:posts].gsub(@config.build_paths[:root], '').concat('/'),
72
- posts:
72
+ posts: posts
73
73
  )
74
74
 
75
- generate_feed(output_path: @config.build_paths[:root], posts:)
75
+ generate_feed(output_path: @config.build_paths[:root], posts: posts) if @config.generation[:main_feed]
76
76
  end
77
77
 
78
78
  def generate_post(post)
@@ -89,25 +89,27 @@ module Dimples
89
89
 
90
90
  def generate_categories
91
91
  categories.each do |category, posts|
92
- metadata = { title: category.capitalize, category: category }
92
+ context = { title: category.capitalize, category: category }
93
93
 
94
94
  Pager.paginate(
95
95
  site: self,
96
96
  url: "/categories/#{category}/",
97
- posts:,
98
- metadata:
97
+ posts: posts,
98
+ context: context
99
99
  )
100
100
 
101
- generate_feed(output_path: File.join(@config.build_paths[:root], 'categories', category), posts:)
101
+ if @config.generation[:category_feeds]
102
+ generate_feed(output_path: File.join(@config.build_paths[:root], 'categories', category), posts: posts)
103
+ end
102
104
  end
103
105
  end
104
106
 
105
107
  def generate_feed(output_path:, posts:)
106
- return if layouts['feed'].nil?
108
+ return if layouts[:feed].nil?
107
109
 
108
- layouts['feed'].write(
110
+ layouts[:feed].write(
109
111
  output_path: File.join(output_path, 'feed.atom'),
110
- metadata: { posts: posts.slice(0, 10) }
112
+ context: { posts: posts.slice(0, 10) }
111
113
  )
112
114
  end
113
115
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dimples
4
- VERSION = '10.3.1'
4
+ VERSION = '10.5.1'
5
5
  end
data/lib/dimples.rb CHANGED
@@ -7,7 +7,7 @@ require 'dimples/metadata'
7
7
  require 'dimples/pager'
8
8
  require 'dimples/site'
9
9
 
10
- require 'dimples/sources/base'
11
- require 'dimples/sources/page'
12
- require 'dimples/sources/post'
13
- require 'dimples/sources/layout'
10
+ require 'dimples/entries/base'
11
+ require 'dimples/entries/page'
12
+ require 'dimples/entries/post'
13
+ require 'dimples/entries/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.3.1
4
+ version: 10.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Bogan
@@ -62,13 +62,13 @@ files:
62
62
  - bin/dimples
63
63
  - lib/dimples.rb
64
64
  - lib/dimples/config.rb
65
+ - lib/dimples/entries/base.rb
66
+ - lib/dimples/entries/layout.rb
67
+ - lib/dimples/entries/page.rb
68
+ - lib/dimples/entries/post.rb
65
69
  - lib/dimples/metadata.rb
66
70
  - lib/dimples/pager.rb
67
71
  - lib/dimples/site.rb
68
- - lib/dimples/sources/base.rb
69
- - lib/dimples/sources/layout.rb
70
- - lib/dimples/sources/page.rb
71
- - lib/dimples/sources/post.rb
72
72
  - lib/dimples/version.rb
73
73
  homepage: http://github.com/waferbaby/dimples
74
74
  licenses:
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dimples
4
- module Sources
5
- # A base class representing a source file with frontmatter metadata that can be rendered.
6
- class Base
7
- FRONT_MATTER_PATTERN = /^(-{3}\n.*?\n?)^(-{3}*$\n?)/m
8
-
9
- attr_accessor :path, :metadata, :contents, :rendered_contents
10
-
11
- def initialize(site:, path:)
12
- @site = site
13
- @path = File.expand_path(path)
14
- @contents = File.read(@path)
15
-
16
- parse_metadata(@contents)
17
- end
18
-
19
- def parse_metadata(contents)
20
- @metadata = default_metadata
21
-
22
- matches = contents.match(FRONT_MATTER_PATTERN)
23
- return unless matches
24
-
25
- @metadata.merge!(YAML.safe_load(matches[1], symbolize_names: true, permitted_classes: [Date]))
26
- @contents = matches.post_match.strip
27
-
28
- @metadata.each_key do |key|
29
- self.class.send(:define_method, key.to_sym) { @metadata[key] }
30
- end
31
- end
32
-
33
- def write(output_path: nil, metadata: {})
34
- output_path = File.join(output_directory, filename) if output_path.nil?
35
- output_dir = File.dirname(output_path)
36
-
37
- @metadata[:url] = url_for(output_dir)
38
-
39
- output = render(context: metadata)
40
-
41
- FileUtils.mkdir_p(output_dir) unless File.directory?(output_dir)
42
- File.write(output_path, output)
43
- end
44
-
45
- def render(context: {}, body: nil)
46
- context[:site] ||= @site.metadata
47
- context[:page] ||= metadata
48
-
49
- @rendered_contents = template.render(Metadata.new(context)) { body }
50
- return @rendered_contents unless @metadata[:layout] && @site.layouts[@metadata[:layout]]
51
-
52
- @site.layouts[@metadata[:layout]].render(context:, body: @rendered_contents)
53
- end
54
-
55
- def output_directory
56
- @site.config.build_paths[:root]
57
- end
58
-
59
- def url_for(path)
60
- path.gsub(@site.config.build_paths[:root], '').concat('/')
61
- end
62
-
63
- def template
64
- raise NotImplementedError, 'You must set a Tilt template for this class.'
65
- end
66
-
67
- private
68
-
69
- def default_metadata
70
- {
71
- layout: nil,
72
- filename: 'index.html'
73
- }
74
- end
75
- end
76
- end
77
- end