lib/liquidoc.rb in liquidoc-0.4.0 vs lib/liquidoc.rb in liquidoc-0.5.0

- old
+ new

@@ -2,10 +2,11 @@ require 'yaml' require 'json' require 'optparse' require 'liquid' require 'asciidoctor' +require 'asciidoctor-pdf' require 'logger' require 'csv' require 'crack/xml' require 'fileutils' @@ -38,10 +39,12 @@ @attributes_file = @attributes_file_def @pdf_theme_file = 'theme/pdf-theme.yml' @fonts_dir = 'theme/fonts/' @output_filename = 'index' @attributes = {} +@passed_attrs = {} +@verbose = false @logger = Logger.new(STDOUT) @logger.level = Logger::INFO @logger.formatter = proc do |severity, datetime, progname, msg| "#{severity}: #{msg}\n" @@ -86,11 +89,23 @@ when "migrate" inclusive = true inclusive = step.options['inclusive'] if defined?(step.options['inclusive']) copy_assets(step.source, step.target, inclusive) when "render" - @logger.warn "Render actions not yet implemented." + if defined?(step.data) + attrs = ingest_attributes(step.data) + else + attrs = {} + end + validate_file_input(step.source, "source") + doc = AsciiDocument.new(step.source) + doc.add_attrs!(attrs) + builds = step.builds + for bld in builds + build = Build.new(bld, type) # create an instance of the Build class; Build.new accepts a 'bld' hash & action 'type' + asciidocify(doc, build) # perform the liquify operation + end when "deploy" @logger.warn "Deploy actions not yet implemented." else @logger.warn "The action `#{type}` is not valid." end @@ -167,15 +182,14 @@ class BuildConfigStep def initialize step @@step = step - @@logger = Logger.new(STDOUT) if (defined?(@@step['action'])).nil? - @logger.error "Every step in the configuration file needs an 'action' type declared." raise "ConfigStructError" end + validate() end def type return @@step['action'] end @@ -198,11 +212,19 @@ def builds return @@step['builds'] end - def self.validate reqs + def validate + case self.type + when "parse" + reqs = ["data,builds"] + when "migrate" + reqs = ["source,target"] + when "render" + reqs = ["source,builds"] + end for req in reqs if (defined?(@@step[req])).nil? @@logger.error "Every #{@@step['action']}-type in the configuration file needs a '#{req}' declaration." raise "ConfigStructError" end @@ -214,38 +236,51 @@ class Build def initialize build, type @@build = build @@type = type - required = [] - case type - when "parse" - required = ["template,output"] - when "migrate" - required = ["source,target"] - when "render" - required = ["index,output"] - end - for req in required - if (defined?(req)).nil? - raise ActionSettingMissing - end - end end def template @@build['template'] end def output @@build['output'] end - def index - @@build['index'] + def style + @@build['style'] end + def doctype + @@build['doctype'] + end + + def backend + @@build['backend'] + end + + def attributes + @@build['attributes'] + end + + def validate + reqs = [] + case self.type + when "parse" + reqs = ["template,output"] + when "render" + reqs = ["output"] + end + for req in required + if (defined?(req)).nil? + raise "ActionSettingMissing" + end + end + end + end #class Build class DataSrc # initialization means establishing a proper hash for the 'data' param def initialize datasrc @@ -307,10 +342,41 @@ def pattern @@datasrc['pattern'] end end +class AsciiDocument + def initialize map, type='article' + @@index = map + @@attributes = {} + @@type = type + end + + def index + @@index + end + + def add_attrs! attrs + raise "InvalidAttributesFormat" unless attrs.is_a?(Hash) + self.attributes.merge!attrs + end + + def attributes + @@attributes + end + + def type + @@type + end +end + +class AsciiDoctorConfig + def initialize out, type, back + + end +end + # === # Action-specific procs # === # PARSE-type build procs # === @@ -449,11 +515,11 @@ if File.directory?(src) FileUtils.cp_r(src, dest) else FileUtils.cp(src, dest) end - @logger.info "Copied assets." + @logger.info "Copied #{src} to #{dest}." rescue Exception => ex @logger.warn "Problem while copying assets. #{ex.message}" raise end end @@ -462,37 +528,58 @@ # RENDER-type procs # === # Gather attributes from a fixed attributes file # Use _data/attributes.yml or designate as -a path/to/filename.yml -def get_attributes attributes_file - if attributes_file == nil - attributes_file = @attributes_file_def - end +def ingest_attributes attributes_file validate_file_input(attributes_file, "attributes") begin attributes = YAML.load_file(attributes_file) return attributes rescue @logger.warn "Attributes file invalid." end end -# Set attributes for direct Asciidoctor operations -def set_attributes attributes - unless attributes.is_a?(Enumerable) - attributes = { } +def derive_backend type, out_file + case File.extname(out_file) + when ".pdf" + backend = "pdf" + else + backend = "html5" end - attributes["basedir"] = @base_path - attributes.merge!get_attributes(@attributes_file) - attributes = '-a ' + attributes.map{|k,v| "#{k}='#{v}'"}.join(' -a ') - return attributes + return backend end -# To be replaced with a gem call -def publish pub, bld - @logger.warn "Publish actions not yet implemented." +def asciidocify doc, build + @logger.debug "Executing Asciidoctor render operation for #{build.output}." + to_file = build.output + back = derive_backend(doc.type, build.output) + if back == "pdf" # pass optional style file and set a default pdf-fontsdir + unless defined?(build.style).nil? + doc.add_attrs!({"pdf-style"=>build.style}) + end + end + # Add attributes from config file build section + doc.add_attrs!(build.attributes.to_h) + # Add attributes from command-line -a args + doc.add_attrs!(@passed_attrs) + @logger.debug "Final pre-parse attributes: #{doc.attributes}" + # Perform the aciidoctor convert + Asciidoctor.convert_file( + doc.index, + to_file: to_file, + attributes: doc.attributes, + require: "pdf", + backend: back, + doctype: build.doctype, + safe: "server", + sourcemap: true, + verbose: @verbose, + mkdirs: true + ) + @logger.info "Rendered file #{to_file}." end # === # Text manipulation Classes, Modules, filters, etc # === @@ -580,18 +667,17 @@ # From the root directory of your project: # $ liquidoc --help command_parser = OptionParser.new do|opts| opts.banner = "Usage: liquidoc [options]" - opts.on("-a PATH", "--attributes-file=PATH", "For passing in a standard YAML AsciiDoc attributes file. Default: #{@attributes_file_def}") do |n| - @assets_path = n + opts.on("-a KEY=VALUE", "For passing an AsciiDoc attribute parameter to Asciidoctor. Ex: -a basedir=some/path -a custom_var='my value'") do |n| + pair = {} + k,v = n.split('=') + pair[k] = v + @passed_attrs.merge!pair end - opts.on("--attr=STRING", "For passing an AsciiDoc attribute parameter to Asciidoctor. Ex: --attr basedir=some/path --attr imagesdir=some/path/images") do |n| - @passed_attrs = @passed_attrs.merge!n - end - # Global Options opts.on("-b PATH", "--base=PATH", "The base directory, relative to this script. Defaults to `.`, or pwd." ) do |n| @data_file = @base_dir + n end @@ -619,10 +705,11 @@ @template_file = @base_dir + n end opts.on("--verbose", "Run verbose") do |n| @logger.level = Logger::DEBUG + @verbose = true end opts.on("--stdout", "Puts the output in STDOUT instead of writing to a file.") do @output_type = "stdout" end @@ -637,10 +724,9 @@ command_parser.parse! # Upfront debug output @logger.debug "Base dir: #{@base_dir}" @logger.debug "Config file: #{@config_file}" -@logger.debug "Index file: #{@index_file}" # === # Execute # ===