lib/archival/builder.rb in archival-0.0.7 vs lib/archival/builder.rb in archival-0.0.8

- old
+ new

@@ -1,70 +1,89 @@ # frozen_string_literal: true require 'liquid' require 'tomlrb' -require 'tags/layout' require 'redcarpet' -Liquid::Template.error_mode = :strict -Liquid::Template.register_tag('layout', Layout) - module Archival class DuplicateKeyError < StandardError end class Builder attr_reader :page_templates def initialize(config, *_args) @config = config - @markdown = Redcarpet::Markdown.new( - Redcarpet::Render::HTML.new(prettify: true, - hard_wrap: true), no_intra_emphasis: true, - fenced_code_blocks: true, - autolink: true, - strikethrough: true, - underline: true - ) refresh_config end + def pages_dir + File.join(@config.root, @config.pages_dir) + end + + def objects_dir + File.join(@config.root, @config.objects_dir) + end + def refresh_config @file_system = Liquid::LocalFileSystem.new( - File.join(@config.root, @config.pages_dir), '%s.liquid' + pages_dir, '%s.liquid' ) - @variables = {} @object_types = {} @page_templates = {} - @dynamic_pages = Set.new + @dynamic_types = Set.new @dynamic_templates = {} + @parser = Archival::Parser.new(pages_dir) Liquid::Template.file_system = Liquid::LocalFileSystem.new( - File.join(@config.root, @config.pages_dir), '_%s.liquid' + pages_dir, '_%s.liquid' ) - objects_definition_file = File.join(@config.root, - 'objects.toml') - if File.file? objects_definition_file - @object_types = Tomlrb.load_file(objects_definition_file) - end + @objects_definition_file = File.join(@config.root, 'objects.toml') - update_objects update_pages end def full_rebuild Layout.reset_cache refresh_config end - def update_pages - do_update_pages(File.join(@config.root, @config.pages_dir)) + def update_objects(_updated_objects = nil) + @object_types = {} + if File.file? @objects_definition_file + @object_types = Tomlrb.load_file(@objects_definition_file) + end + @dynamic_types = Set.new + @object_types.each do |_name, definition| + is_template = definition.key? 'template' + @dynamic_types << definition['template'] if is_template + end + # TODO: remove deleted dynamic pages end + def update_pages(_updated_pages = nil, _updated_objects = nil) + update_objects + # TODO: remove deleted pages + do_update_pages(pages_dir) + end + + def update_assets(changes) + changes.each do |change| + asset_path = File.join(@config.build_dir, change.path) + case change.type + when :removed + FileUtils.rm_rf asset_path + else + puts change.path + FileUtils.copy_entry File.join(@config.root, change.path), asset_path + end + end + end + def dynamic?(file) - @dynamic_pages.include? File.basename(file, '.liquid') + @dynamic_types.include? File.basename(file, '.liquid') end def template_for_page(template_file) content = @file_system.read_template_file(template_file) content += dev_mode_content if @config.dev_mode @@ -94,38 +113,48 @@ end end end end - def update_objects - do_update_objects(File.join(@config.root, - @config.objects_dir)) + def read_objects(type) + obj_dir = File.join(objects_dir, type) + return unless File.directory? obj_dir + + Dir.foreach(obj_dir) do |file| + if file.end_with? '.toml' + object = Tomlrb.load_file(File.join( + obj_dir, file + )) + object[:name] = + File.basename(file, '.toml') + yield object[:name], object + end + end end - def do_update_objects(dir) + def path_for_template(name, type) + Pathname.new(File.join(pages_dir, type, "#{name}.html")) + end + + def objects_for_template(template_path) objects = {} - @object_types.each do |name, definition| - objects[name] = {} - obj_dir = File.join(dir, name) - if File.directory? obj_dir - Dir.foreach(obj_dir) do |file| - if file.end_with? '.toml' - object = Tomlrb.load_file(File.join( - obj_dir, file - )) - object[:name] = - File.basename(file, '.toml') - objects[name][object[:name]] = parse_object(object, definition) - if definition.key? 'template' - @dynamic_pages << definition['template'] - end - end + @object_types.each do |type, definition| + objects[type] = {} + is_dynamic = @dynamic_types.include? type + read_objects type do |name, object| + objects[type][name] = @parser.parse_object( + object, definition, template_path + ) + if is_dynamic + path = path_for_template(name, type) + objects[type][name]['path'] = + path.relative_path_from(File.dirname(template_path)).to_s end end - objects[name] = sort_objects(objects[name]) + objects[type] = sort_objects(objects[type]) end - @variables['objects'] = objects + objects end def sort_objects(objects) # Sort by either 'order' key or object name, depending on what is # available. @@ -140,63 +169,62 @@ sorted_objects[d[0]] = d[1] end sorted_objects end - def parse_object(object, definition) - definition.each do |name, type| - case type - when 'markdown' - object[name] = @markdown.render(object[name]) if object[name] - end - end - object - end - - def set_var(name, value) - @variables[name] = value - end - def render(page) + dir = File.join(pages_dir, File.dirname(page)) template = @page_templates[page] - template.render(@variables) + template_path = File.join(dir, page) + parsed_objects = objects_for_template(template_path) + template.render('objects' => parsed_objects, + 'template_path' => template_path) end - def render_dynamic(page, obj) - template = @dynamic_templates[page] - template.render(@variables.merge({ page => obj })) + def render_dynamic(type, name) + dir = File.join(pages_dir, type) + template = @dynamic_templates[type] + template_path = File.join(dir, name) + parsed_objects = objects_for_template(template_path) + obj = parsed_objects[type][name] + vars = {} + .merge( + 'objects' => parsed_objects, + 'template_path' => template_path + ) + .merge({ type => obj }) + template.render(vars) end def write_all Dir.mkdir(@config.build_dir) unless File.exist? @config.build_dir @page_templates.each_key do |template| out_dir = File.join(@config.build_dir, File.dirname(template)) Dir.mkdir(out_dir) unless File.exist? out_dir - out_path = File.join(out_dir, - "#{template}.html") + out_path = File.join(out_dir, "#{template}.html") File.open(out_path, 'w+') do |file| file.write(render(template)) end end - @dynamic_pages.each do |page| - out_dir = File.join(@config.build_dir, page) + @dynamic_types.each do |type| + out_dir = File.join(@config.build_dir, type) Dir.mkdir(out_dir) unless File.exist? out_dir - objects = @variables['objects'][page] - objects.each do |obj| - out_path = File.join(out_dir, "#{obj[:name]}.html") - obj['path'] = out_path + read_objects(type) do |name| + out_path = File.join(out_dir, "#{name}.html") File.open(out_path, 'w+') do |file| - file.write(render_dynamic(page, obj)) + file.write(render_dynamic(type, name)) end end end - return if @config.dev_mode - # in production, also copy all assets to the dist folder. + # in production (or init), also copy all assets to the dist folder. + # in dev, they will be copied as they change. @config.assets_dirs.each do |asset_dir| - FileUtils.copy_entry File.join(@config.root, asset_dir), - File.join(@config.build_dir, asset_dir) + asset_path = File.join(@config.build_dir, asset_dir) + next if @config.dev_mode || !File.exist?(asset_path) + + FileUtils.copy_entry File.join(@config.root, asset_dir), asset_path end end private