From f327809c5c105781f0ac97e48df2052a8d1908e6 Mon Sep 17 00:00:00 2001 From: Daniel Bogan Date: Sat, 3 Feb 2024 10:38:50 +0000 Subject: [PATCH] Refactor all the things --- lib/dimples.rb | 9 +++-- lib/dimples/config.rb | 4 +- lib/dimples/layout.rb | 21 ---------- lib/dimples/page.rb | 32 --------------- lib/dimples/pager.rb | 20 +++++---- lib/dimples/post.rb | 41 ------------------- lib/dimples/site.rb | 76 ++++++++++------------------------- lib/dimples/sources/base.rb | 11 ++--- lib/dimples/sources/layout.rb | 12 ++++++ lib/dimples/sources/page.rb | 31 ++++++++++++++ lib/dimples/sources/post.rb | 34 ++++++++++++++++ 11 files changed, 125 insertions(+), 166 deletions(-) delete mode 100644 lib/dimples/layout.rb delete mode 100644 lib/dimples/page.rb delete mode 100644 lib/dimples/post.rb create mode 100644 lib/dimples/sources/layout.rb create mode 100644 lib/dimples/sources/page.rb create mode 100644 lib/dimples/sources/post.rb diff --git a/lib/dimples.rb b/lib/dimples.rb index b946bfb..d586218 100644 --- a/lib/dimples.rb +++ b/lib/dimples.rb @@ -3,9 +3,10 @@ $LOAD_PATH.unshift(__dir__) require 'dimples/config' -require 'dimples/metadata' require 'dimples/pager' -require 'dimples/page' -require 'dimples/post' -require 'dimples/layout' require 'dimples/site' + +require 'dimples/sources/base' +require 'dimples/sources/page' +require 'dimples/sources/post' +require 'dimples/sources/layout' diff --git a/lib/dimples/config.rb b/lib/dimples/config.rb index 09bc3d0..1044e0f 100644 --- a/lib/dimples/config.rb +++ b/lib/dimples/config.rb @@ -13,8 +13,8 @@ def self.defaults def initialize(options = {}) @options = Config.defaults - options.each do |key, value| - @options[key].merge!(value) + options&.each do |key, value| + @options[key]&.merge!(value) end %i[sources output].each do |type| diff --git a/lib/dimples/layout.rb b/lib/dimples/layout.rb deleted file mode 100644 index aa3fc83..0000000 --- a/lib/dimples/layout.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -module Dimples - # A class for a single layout used on a site. - class Layout - include Metadata - - def initialize(path, config) - @config = config - parse_file(path) - end - - def layout - @metadata[:layout] - end - - def template - @template ||= Tilt::ERBTemplate.new { @contents } - end - end -end diff --git a/lib/dimples/page.rb b/lib/dimples/page.rb deleted file mode 100644 index 8178a5e..0000000 --- a/lib/dimples/page.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -module Dimples - # A single page on a site. - class Page - include Metadata - - def initialize(path, config) - @config = config - parse_file(path) - end - - def layout - @metadata[:layout] || 'default' - end - - def output_directory - @output_directory ||= File.dirname(@path).gsub(@config[:sources][:pages], @config[:output][:root]) << '/' - end - - def url - @url ||= String.new.tap do |url| - url << output_directory unless output_directory == '/' - url << "/#{filename}" unless basename == 'index' - end - end - - def template - @template ||= Tilt::ERBTemplate.new { @contents } - end - end -end diff --git a/lib/dimples/pager.rb b/lib/dimples/pager.rb index 085601c..87a5910 100644 --- a/lib/dimples/pager.rb +++ b/lib/dimples/pager.rb @@ -9,24 +9,30 @@ class Pager attr_reader :current_page, :previous_page, :next_page, :page_count - def self.paginate(url, posts, config, ...) - new(url, posts, config).each(...) + def self.paginate(site, url, posts, metadata = {}) + new(site, url, posts).paginate(metadata) end - def initialize(url, posts, config) + def initialize(site, url, posts) + @site = site @url = url @posts = posts - @per_page = config.dig(:pagination, :per_page) || PER_PAGE - @page_prefix = config.dig(:pagination, :page_prefix) || 'page_' + + @per_page = @site.config.dig(:pagination, :per_page) || PER_PAGE + @page_prefix = @site.config.dig(:pagination, :page_prefix) || 'page_' @page_count = (posts.length.to_f / @per_page.to_i).ceil step_to(1) end - def each + def paginate(metadata) (1..@page_count).each do |index| step_to(index) - yield metadata if block_given? + + @site.layouts['posts'].write( + File.join(@site.config[:output][:root], current_page_url, 'index.html'), + metadata.merge(pagination: self.metadata, url: current_page_url) + ) end end diff --git a/lib/dimples/post.rb b/lib/dimples/post.rb deleted file mode 100644 index 5a91635..0000000 --- a/lib/dimples/post.rb +++ /dev/null @@ -1,41 +0,0 @@ -# frozen_string_literal: true - -module Dimples - # A page from a site with a date. - class Post - include Metadata - - def initialize(path, config) - @config = config - parse_file(path) - end - - def date - @metadata[:date] || File.birthtime(@path) - end - - def layout - @metadata[:layout] || 'post' - end - - def categories - @metadata[:categories] || [] - end - - def slug - @metadata[:slug] || File.basename(@path, '.markdown') - end - - def output_directory - @output_directory ||= File.dirname(@path).gsub(@config[:sources][:posts], @config[:output][:posts]) << "/#{slug}/" - end - - def url - @url ||= output_directory.gsub(@config[:output][:root], '') - end - - def template - @template ||= Tilt::RedcarpetTemplate.new { @contents } - end - end -end diff --git a/lib/dimples/site.rb b/lib/dimples/site.rb index 39c322a..daa2459 100644 --- a/lib/dimples/site.rb +++ b/lib/dimples/site.rb @@ -27,23 +27,21 @@ def generate copy_assets end - private - def posts @posts ||= Dir.glob(File.join(@config[:sources][:posts], '**', '*.markdown')).map do |path| - Dimples::Post.new(path, @config) + Dimples::Sources::Post.new(self, path) end.sort_by!(&:date).reverse! end def pages @pages ||= Dir.glob(File.join(@config[:sources][:pages], '**', '*.erb')).map do |path| - Dimples::Page.new(path, @config) + Dimples::Sources::Page.new(self, path) end end def layouts @layouts ||= Dir.glob(File.join(@config[:sources][:layouts], '**', '*.erb')).to_h do |path| - [File.basename(path, '.erb'), Dimples::Layout.new(path, @config)] + [File.basename(path, '.erb'), Dimples::Sources::Layout.new(self, path)] end end @@ -58,66 +56,36 @@ def categories end end + def metadata + @metadata ||= { posts: posts, categories: categories } + end + + private + def generate_posts - posts.each do |post| - write_item(post) - end + posts.each(&:write) + Pager.paginate(self, '/interviews/', posts) - Pager.paginate('/interviews/', posts, @config) do |pagination| - path = File.join(@config[:output][:root], pagination[:urls][:current_page]) - write_item(layouts['posts'], output_path: path, metadata: { pagination: pagination }) - end + layouts['feed'].write( + File.join(@config[:output][:root], 'feed.atom'), + posts: posts.slice(0, 10) + ) end def generate_categories categories.each do |category, posts| - Pager.paginate("/categories/#{category}/", posts, @config) do |pagination| - path = File.join(@config[:output][:root], pagination[:urls][:current_page]) - metadata = { title: category.capitalize, category: category, pagination: pagination } + metadata = { title: category.capitalize, category: category } + Pager.paginate(self, "/categories/#{category}/", posts, metadata) - write_item(layouts['posts'], output_path: path, metadata: metadata) - end + layouts['feed'].write( + File.join(@config[:output][:root], 'categories', category, 'feed.atom'), + posts: posts.slice(0, 10) + ) end end def generate_pages - pages.each do |page| - write_item(page) - end - end - - def write_item(item, output_path: nil, metadata: {}) - output_path ||= item.output_directory - - FileUtils.mkdir_p(output_path) unless File.directory?(output_path) - - contents = render_item(item, metadata: metadata) - File.write(File.join(output_path, item.filename), contents) - end - - def render_item(item, body: nil, metadata: {}) - metadata = item.metadata.merge(metadata) - output = item.template.render(metadata_context(metadata)) { body } - return output unless item.layout && layouts[item.layout] - - render_item(layouts[item.layout], body: output, metadata: metadata) - rescue StandardError => e - raise "Failed to render #{item.path}: #{e}" - end - - def metadata_context(metadata) - Object.new.tap do |context| - shared_metadata.merge(metadata).each do |key, value| - context.instance_variable_set("@#{key}", value) - end - end - end - - def shared_metadata - @shared_metadata ||= { - posts: posts, - categories: categories - } + pages.each(&:write) end def prepare_output_directory diff --git a/lib/dimples/sources/base.rb b/lib/dimples/sources/base.rb index 6b8f32d..f8fba68 100644 --- a/lib/dimples/sources/base.rb +++ b/lib/dimples/sources/base.rb @@ -20,16 +20,17 @@ def initialize(site, path) @contents = matches.post_match.strip end - def write(output_directory = nil, metadata = {}) - output_directory ||= self.output_directory - + def write(output_path = nil, metadata = {}) metadata[:site] ||= @site metadata[context_key] ||= self output = render(metadata) - FileUtils.mkdir_p(output_directory) unless File.directory?(output_directory) - File.write(File.join(output_directory, filename), output) + output_path = File.join(output_directory, filename) if output_path.nil? + output_dir = File.dirname(output_path) + + FileUtils.mkdir_p(output_dir) unless File.directory?(output_dir) + File.write(output_path, output) end def render(metadata = {}, body = nil) diff --git a/lib/dimples/sources/layout.rb b/lib/dimples/sources/layout.rb new file mode 100644 index 0000000..1fc2e58 --- /dev/null +++ b/lib/dimples/sources/layout.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Dimples + module Sources + # A class for a single layout used on a site. + class Layout < Base + def template + @template ||= Tilt::ERBTemplate.new { @contents } + end + end + end +end diff --git a/lib/dimples/sources/page.rb b/lib/dimples/sources/page.rb new file mode 100644 index 0000000..b6d32a9 --- /dev/null +++ b/lib/dimples/sources/page.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Dimples + module Sources + # A single page on a site. + class Page < Base + def output_directory + @output_directory ||= File.dirname(@path).gsub( + @site.config[:sources][:pages], + @site.config[:output][:root] + ).concat('/') + end + + def url + @metadata[:url] || super.tap do |url| + url.concat(filename) unless filename == 'index.html' + end + end + + def template + @template ||= Tilt::ERBTemplate.new { @contents } + end + + private + + def default_metadata + super.merge!(layout: 'page') + end + end + end +end diff --git a/lib/dimples/sources/post.rb b/lib/dimples/sources/post.rb new file mode 100644 index 0000000..fac96d1 --- /dev/null +++ b/lib/dimples/sources/post.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Dimples + module Sources + # A page from a site with a date. + class Post < Base + def output_directory + @output_directory ||= File.dirname(@path).gsub( + @site.config[:sources][:posts], + @site.config[:output][:posts] + ).concat("/#{@metadata[:slug]}/") + end + + def template + @template ||= Tilt::RedcarpetTemplate.new { @contents } + end + + private + + def context_key + :post + end + + def default_metadata + super.tap do |defaults| + defaults[:layout] = 'post' + defaults[:slug] = File.basename(@path, '.markdown') + defaults[:date] = File.birthtime(@path) + defaults[:categories] = [] + end + end + end + end +end