Top Level Namespace
Defined Under Namespace
Modules: CustomFilters, Liquidoc Classes: AsciiDoctorConfig, AsciiDocument, Build, BuildConfig, BuildConfigStep, DataSrc, String
Instance Method Summary collapse
- #asciidocify(doc, build) ⇒ Object
-
#config_build(config_file) ⇒ Object
Establish source, template, index, etc details for build jobs from a config file.
-
#copy_assets(src, dest, inclusive = true) ⇒ Object
Copy images and other files into target dir.
- #derive_backend(type, out_file) ⇒ Object
-
#ingest_attributes(attr_file) ⇒ Object
Gather attributes from one or more fixed attributes files.
-
#ingest_data(datasrc) ⇒ Object
Pull in a semi-structured data file, converting contents to a Ruby hash.
- #iterate_build(cfg) ⇒ Object
-
#liquify(datasrc, template_file, output) ⇒ Object
Parse given data using given template, generating given output.
- #parse_regex(data_file, pattern) ⇒ Object
- #validate_config_structure(config) ⇒ Object
-
#validate_file_input(file, type) ⇒ Object
Verify files exist.
Instance Method Details
#asciidocify(doc, build) ⇒ Object
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
# File 'lib/liquidoc.rb', line 574 def asciidocify doc, build @logger.debug "Executing Asciidoctor render operation for #{build.output}." to_file = build.output unless doc.type == build.doctype if build.doctype.nil? build.set("doctype", doc.type) end end back = derive_backend(doc.type, build.output) unless build.style.nil? case back when "pdf" doc.add_attrs!({"pdf-style"=>build.style}) when "html5" doc.add_attrs!({"stylesheet"=>build.style}) else raise "UnrecognizedBackend" 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 unless back == "pdf" Asciidoctor.convert_file( doc.index, to_file: to_file, attributes: doc.attributes, require: "pdf", backend: back, doctype: build.doctype, safe: "unsafe", sourcemap: true, verbose: @verbose, mkdirs: true ) else # For PDFs, we're calling the asciidoctor-pdf CLI, as the main dependency doesn't seem to perform the same way attributes = '-a ' + doc.attributes.map{|k,v| "#{k}='#{v}'"}.join(' -a ') command = "asciidoctor-pdf -o #{to_file} -b pdf -d #{build.doctype} -S unsafe #{attributes} -a no-header-footer --trace #{doc.index}" @logger.debug "Running #{command}" system command end @logger.info "Rendered file #{to_file}." end |
#config_build(config_file) ⇒ Object
Establish source, template, index, etc details for build jobs from a config file
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/liquidoc.rb', line 58 def config_build config_file @logger.debug "Using config file #{config_file}." validate_file_input(config_file, "config") begin config = YAML.load_file(config_file) rescue unless File.exists?(config_file) @logger.error "Config file #{config_file} not found." else @logger.error "Problem loading config file #{config_file}. Exiting." end raise "ConfigFileError" end cfg = BuildConfig.new(config) # convert the config file to a new object called 'cfg' iterate_build(cfg) end |
#copy_assets(src, dest, inclusive = true) ⇒ Object
Copy images and other files into target dir
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/liquidoc.rb', line 502 def copy_assets src, dest, inclusive=true if File.file?(src) # for sources that are files target_dir = File.dirname(dest) else # if src is a directory unless inclusive then src = src + "/." end target_dir = dest end @logger.debug "Copying #{src} to #{dest}" begin FileUtils.mkdir_p(target_dir) unless File.directory?(target_dir) if File.directory?(src) FileUtils.cp_r(src, dest) else FileUtils.cp(src, dest) end @logger.info "Copied #{src} to #{dest}." rescue Exception => ex @logger.warn "Problem while copying assets. #{ex.message}" raise end end |
#derive_backend(type, out_file) ⇒ Object
564 565 566 567 568 569 570 571 572 |
# File 'lib/liquidoc.rb', line 564 def derive_backend type, out_file case File.extname(out_file) when ".pdf" backend = "pdf" else backend = "html5" end return backend end |
#ingest_attributes(attr_file) ⇒ Object
Gather attributes from one or more fixed attributes files
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 |
# File 'lib/liquidoc.rb', line 529 def ingest_attributes attr_file file_array = attr_file.split(",") attrs = {} for f in file_array if f.include? ":" file = f.split(":") filename = file[0] block_name = file[1] else filename = f block_name = false end validate_file_input(filename, "attributes") begin new_attrs = YAML.load_file(filename) if block_name begin new_attrs = new_attrs[block_name] rescue raise "InvalidAttributesBlock" end end rescue Exception => ex @logger.error "Attributes block invalid. #{ex.class}: #{ex.message}" raise "AttributeBlockError" end begin attrs.merge!new_attrs rescue Exception => ex raise "AttributesMergeError #{ex.message}" end end return attrs end |
#ingest_data(datasrc) ⇒ Object
Pull in a semi-structured data file, converting contents to a Ruby hash
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/liquidoc.rb', line 382 def ingest_data datasrc # Must be passed a proper data object (there must be a better way to validate arg datatypes) unless datasrc.is_a? Object raise "InvalidDataObject" end # This proc should really begin here, once the datasrc object is in order case datasrc.type when "yml" begin data = YAML.load_file(datasrc.file) rescue Exception => ex @logger.error "There was a problem with the data file. #{ex.message}" end when "json" begin data = JSON.parse(File.read(datasrc.file)) rescue Exception => ex @logger.error "There was a problem with the data file. #{ex.message}" end when "xml" begin data = Crack::XML.parse(File.read(datasrc.file)) data = data['root'] rescue Exception => ex @logger.error "There was a problem with the data file. #{ex.message}" end when "csv" output = [] i = 0 begin CSV.foreach(datasrc.file, headers: true, skip_blanks: true) do |row| output[i] = row.to_hash i = i+1 end output = {"data" => output} data = output rescue @logger.error "The CSV format is invalid." end when "regex" if datasrc.pattern data = parse_regex(datasrc.file, datasrc.pattern) else @logger.error "You must supply a regex pattern with your free-form data file." raise "MissingRegexPattern" end end end |
#iterate_build(cfg) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/liquidoc.rb', line 75 def iterate_build cfg stepcount = 0 for step in cfg.steps # iterate through each node in the 'config' object, which should start with an 'action' parameter stepcount = stepcount + 1 step = BuildConfigStep.new(step) # create an instance of the Action class, validating the top-level step hash (now called 'step') in the process type = step.type case type # a switch to evaluate the 'action' parameter for each step in the iteration... when "parse" data = DataSrc.new(step.data) 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' liquify(data, build.template, build.output) # perform the liquify operation end when "migrate" inclusive = true inclusive = step.['inclusive'] if defined?(step.['inclusive']) copy_assets(step.source, step.target, inclusive) when "render" if defined?(step.data) # if we're passing attributes as a YAML file, let's ingest that up front 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 end end |
#liquify(datasrc, template_file, output) ⇒ Object
Parse given data using given template, generating given output
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
# File 'lib/liquidoc.rb', line 458 def liquify datasrc, template_file, output @logger.debug "Executing liquify parsing operation." if datasrc.is_a? String datasrc = DataSrc.new(datasrc) end validate_file_input(datasrc.file, "data") validate_file_input(template_file, "template") data = ingest_data(datasrc) begin template = File.read(template_file) # reads the template file template = Liquid::Template.parse(template) # compiles template rendered = template.render(data) # renders the output rescue Exception => ex = "Problem rendering Liquid template. #{template_file}\n" \ "#{ex.class} thrown. #{ex.message}" @logger.error raise end unless output.downcase == "stdout" output_file = output base_path = File.dirname(output) begin FileUtils::mkdir_p(base_path) unless File.exists?(base_path) File.open(output_file, 'w') { |file| file.write(rendered) } # saves file rescue Exception => ex @logger.error "Failed to save output.\n#{ex.class} #{ex.message}" raise "FileNotBuilt" end if File.exists?(output_file) @logger.info "File built: #{File.basename(output_file)}" else @logger.error "Hrmp! File not built." raise "FileNotBuilt" end else # if stdout puts "========\nOUTPUT: Rendered with template #{template_file}:\n\n#{rendered}\n" end end |
#parse_regex(data_file, pattern) ⇒ Object
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/liquidoc.rb', line 431 def parse_regex data_file, pattern records = [] pattern_re = /#{pattern}/ @logger.debug "Using regular expression #{pattern} to parse data file." groups = pattern_re.names begin File.open(data_file, "r") do |file_proc| file_proc.each_line do |row| matches = row.match(pattern_re) if matches row_h = {} groups.each do |var| # loop over the named groups, adding their key & value to the row_h hash row_h.merge!(var => matches[var]) end records << row_h # add the row to the records array end end end output = {"data" => records} rescue Exception => ex @logger.error "Something went wrong trying to parse the free-form file. #{ex.class} thrown. #{ex.message}" raise "Freeform parse error" end return output end |
#validate_config_structure(config) ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/liquidoc.rb', line 132 def validate_config_structure config unless config.is_a? Array = "The configuration file is not properly structured." @logger.error raise "ConfigStructError" else if (defined?(config['action'])).nil? = "Every listing in the configuration file needs an action type declaration." @logger.error raise "ConfigStructError" end end # TODO More validation needed end |
#validate_file_input(file, type) ⇒ Object
Verify files exist
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/liquidoc.rb', line 116 def validate_file_input file, type @logger.debug "Validating input file for #{type} file #{file}" error = false unless file.is_a?(String) and !file.nil? error = "The #{type} filename (#{file}) is not valid." else unless File.exists?(file) error = "The #{type} file (#{file}) was not found." end end if error @logger.error "Could not validate input file: #{error}" raise "InvalidInput" end end |