module Quarto
Constants
- EXTENSIONS_TO_SOURCE_FORMATS
- SECTION_TEMPLATE
- SPINE_TEMPLATE
- VERSION
- XINCLUDE_NS
Public Class Methods
configure() { |self| ... }
click to toggle source
# File lib/quarto.rb, line 10 def self.configure yield self end
stylesheets()
click to toggle source
# File lib/quarto.rb, line 14 def self.stylesheets @stylesheets ||= [code_stylesheet] end
Public Instance Methods
build_dir()
click to toggle source
# File lib/quarto.rb, line 54 def build_dir "build" end
code_stylesheet()
click to toggle source
# File lib/quarto.rb, line 125 def code_stylesheet "#{build_dir}/code.css" end
codex_file()
click to toggle source
# File lib/quarto.rb, line 165 def codex_file "build/codex.xhtml" end
configuration()
click to toggle source
# File lib/quarto.rb, line 18 def configuration Quarto end
create_codex_file(codex_file, spine_file)
click to toggle source
# File lib/quarto.rb, line 169 def create_codex_file(codex_file, spine_file) expand_xinclude(codex_file, spine_file) end
create_master_file(master_file, skeleton_file)
click to toggle source
# File lib/quarto.rb, line 245 def create_master_file(master_file, skeleton_file) expand_xinclude(master_file, skeleton_file, format: false) end
create_skeleton_file(skeleton_file, codex_file)
click to toggle source
# File lib/quarto.rb, line 181 def create_skeleton_file(skeleton_file, codex_file) puts "scan #{codex_file} for source code listings" skel_doc = open(codex_file) do |f| Nokogiri::XML(f) end skel_doc.css("pre.sourceCode").each_with_index do |pre_elt, i| lang = pre_elt["class"].split[1] ext = {"ruby" => "rb"}.fetch(lang){ lang.downcase } code = pre_elt.at_css("code").text digest = Digest::SHA1.hexdigest(code) listing_path = "#{listings_dir}/#{digest}.#{ext}" puts "extract listing #{i} to #{listing_path}" open(listing_path, 'w') do |f| f.write(strip_listing(code)) end highlight_path = "#{highlights_dir}/#{digest}.html" inc_elt = skel_doc.create_element("xi:include") do |elt| elt["href"] = highlight_path elt.add_child( "<xi:fallback>"\ "<p>[Missing code listing: #{highlight_path}]</p>"\ "</xi:fallback>") end pre_elt.replace(inc_elt) end puts "create #{skeleton_file}" open(skeleton_file, "w") do |f| format_xml(f) do |format_input| skel_doc.write_xml_to(format_input) end end end
create_spine_file(spine_file, section_files, options={})
click to toggle source
# File lib/quarto.rb, line 133 def create_spine_file(spine_file, section_files, options={}) options = {stylesheets: configuration.stylesheets}.merge(options) puts "create #{spine_file}" doc = Nokogiri::XML.parse(SPINE_TEMPLATE) doc.root.add_namespace("xi", "http://www.w3.org/2001/XInclude") head_elt = doc.root.at_css("head") stylesheets = Array(options[:stylesheets]) stylesheets.each do |stylesheet| head_elt.add_child( doc.create_element( "style", File.read(stylesheet))) end section_files.each do |section_file| doc.root["xml:base"] = ".." body = doc.root.at_css("body") body.add_child(doc.create_element("xi:include") do |inc_elt| inc_elt["href"] = section_file inc_elt["xpointer"] = "xmlns(ns=http://www.w3.org/1999/xhtml)xpointer(//ns:body/*)" inc_elt.add_child(doc.create_element("xi:fallback") do |fallback_elt| fallback_elt.add_child(doc.create_element("p", "[Missing section: #{section_file}]")) end) end) end open(spine_file, 'w') do |f| format_xml(f) do |format_input| doc.write_to(format_input) end end end
deliverable_dir()
click to toggle source
# File lib/quarto.rb, line 249 def deliverable_dir "#{build_dir}/deliverables" end
deliverable_files()
click to toggle source
# File lib/quarto.rb, line 253 def deliverable_files [pdf_file] end
export_command_for(source_file, export_file)
click to toggle source
# File lib/quarto.rb, line 85 def export_command_for(source_file, export_file) %W[pandoc --no-highlight -w html5 -o #{export_file} #{source_file}] end
export_dir()
click to toggle source
# File lib/quarto.rb, line 71 def export_dir "build/exports" end
export_files()
click to toggle source
# File lib/quarto.rb, line 75 def export_files source_files.pathmap("#{export_dir}/%p").ext('.html') end
export_for_section_file(section_file)
click to toggle source
# File lib/quarto.rb, line 97 def export_for_section_file(section_file) section_file.pathmap("%{^#{section_dir},#{export_dir}}X%{xhtml,html}x") end
format_of_source_file(source_file)
click to toggle source
# File lib/quarto.rb, line 62 def format_of_source_file(source_file) ext = source_file.pathmap("%x")[1..-1] EXTENSIONS_TO_SOURCE_FORMATS.fetch(ext) end
highlights_dir()
click to toggle source
# File lib/quarto.rb, line 214 def highlights_dir "#{build_dir}/highlights" end
highlights_needed_by(skeleton_file)
click to toggle source
# File lib/quarto.rb, line 218 def highlights_needed_by(skeleton_file) doc = open(skeleton_file) do |f| Nokogiri::XML(f) end doc.xpath("//xi:include", "xi" => XINCLUDE_NS).map{|e| e["href"]} end
listing_for_highlight_file(highlight_file)
click to toggle source
# File lib/quarto.rb, line 225 def listing_for_highlight_file(highlight_file) base = highlight_file.pathmap("%n") FileList["#{listings_dir}/#{base}.*"].first end
listings_dir()
click to toggle source
# File lib/quarto.rb, line 177 def listings_dir "#{build_dir}/listings" end
master_file()
click to toggle source
# File lib/quarto.rb, line 241 def master_file "#{build_dir}/master.xhtml" end
normalize_export(export_file, section_file, format)
click to toggle source
# File lib/quarto.rb, line 101 def normalize_export(export_file, section_file, format) format ||= "NO_FORMAT_GIVEN" send("normalize_#{format}_export", export_file, section_file) end
normalize_markdown_export(export_file, section_file)
click to toggle source
# File lib/quarto.rb, line 106 def normalize_markdown_export(export_file, section_file) puts "normalize #{export_file} to #{section_file}" doc = open(export_file) do |f| Nokogiri::HTML(f) end normal_doc = Nokogiri::XML.parse(SECTION_TEMPLATE) normal_doc.at_css("body").replace(doc.at_css("body")) normal_doc.at_css("title").content = export_file.pathmap("%n") open(section_file, "w") do |f| format_xml(f) do |pipe_input| normal_doc.write_xml_to(pipe_input) end end end
pdf_file()
click to toggle source
# File lib/quarto.rb, line 257 def pdf_file "#{deliverable_dir}/book.pdf" end
section_dir()
click to toggle source
# File lib/quarto.rb, line 89 def section_dir "build/sections" end
section_files()
click to toggle source
# File lib/quarto.rb, line 93 def section_files export_files.pathmap("%{^#{export_dir},#{section_dir}}X%{html,xhtml}x") end
skeleton_file()
click to toggle source
# File lib/quarto.rb, line 173 def skeleton_file "#{build_dir}/skeleton.xhtml" end
source_exts()
click to toggle source
# File lib/quarto.rb, line 58 def source_exts EXTENSIONS_TO_SOURCE_FORMATS.keys end
source_files()
click to toggle source
# File lib/quarto.rb, line 67 def source_files FileList["**/*.{#{source_exts.join(',')}}"] end
source_for_export_file(export_file)
click to toggle source
# File lib/quarto.rb, line 79 def source_for_export_file(export_file) base = export_file.sub(/^#{export_dir}\//,'').ext('') pattern = "#{base}.{#{source_exts.join(',')}}" FileList[pattern].first end
source_list_file()
click to toggle source
# File lib/quarto.rb, line 121 def source_list_file "build/sources" end
spine_file()
click to toggle source
# File lib/quarto.rb, line 129 def spine_file "build/spine.xhtml" end
strip_listing(code)
click to toggle source
Strip extraneous whitespace from around a code listing
# File lib/quarto.rb, line 231 def strip_listing(code) code.gsub!(/\t/, " ") lines = code.split("\n") first_code_line = lines.index{|l| l =~ /\S/} last_code_line = lines.rindex{|l| l =~ /\S/} lines = lines[first_code_line..last_code_line] indent = lines.map{|l| l.index(/[^ ]/)}.min lines.map{|l| l.slice(indent..-1)}.join("\n") + "\n" end
Private Instance Methods
expand_xinclude(output_file, input_file, options={})
click to toggle source
# File lib/quarto.rb, line 272 def expand_xinclude(output_file, input_file, options={}) options = {format: true}.merge(options) puts "expand #{input_file} to #{output_file}" cleanup_args = %W[--nsclean --xmlout] if options[:format] cleanup_args << "--format" end Open3.pipeline_r( %W[xmllint --xinclude --xmlout #{input_file}], # In order to clean up extraneous namespace declarations we need a second # xmllint process ["xmllint", *cleanup_args, "-"]) do |output, wait_thr| open(output_file, 'w') do |f| IO.copy_stream(output, f) end end end
format_xml(output_io) { |stdin| ... }
click to toggle source
# File lib/quarto.rb, line 263 def format_xml(output_io) Open3.popen2(*%W[xmllint --format --xmlout -]) do |stdin, stdout, wait_thr| yield(stdin) stdin.close IO.copy_stream(stdout, output_io) end end