require "nokogiri" module Metanorma module Input class Asciidoc < Base def process(file, filename, type, options = {}) require "asciidoctor" out_opts = { to_file: false, safe: :safe, backend: type, header_footer: true, attributes: ["nodoc", "stem", "xrefstyle=short", "docfile=#{filename}", "output_dir=#{options[:output_dir]}"] } unless asciidoctor_validate(file, filename, out_opts) warn "Cannot continue compiling Asciidoctor document" abort end ::Asciidoctor.convert(file, out_opts) end def asciidoctor_validate(file, filename, options) err = nil begin previous_stderr = $stderr $stderr = StringIO.new ::Asciidoctor.load(file, options) %r{(\n|^)asciidoctor: ERROR: ['"]?#{Regexp.escape(filename || "")}['"]?: line \d+: include file not found: } .match($stderr.string) and err = $stderr.string ensure $stderr = previous_stderr end warn err unless err.nil? err.nil? end def extract_metanorma_options(file) headerextract = file.sub(/\n\n.*$/m, "\n") /\n:mn-document-class: (?[^\n]+)\n/ =~ headerextract /\n:mn-output-extensions: (?[^\n]+)\n/ =~ headerextract /\n:mn-relaton-output-file: (?[^\n]+)\n/ =~ headerextract /\n(?:mn-keep-asciimath:[^\n]*)\n/ =~ headerextract asciimath = if defined?(asciimath) (!asciimath.nil? && asciimath != ":mn-keep-asciimath: false") end asciimath = nil if asciimath == false { type: defined?(type) ? type : nil, extensions: defined?(extensions) ? extensions : nil, relaton: defined?(relaton) ? relaton : nil, asciimath: asciimath, }.reject { |_, val| val.nil? } end def empty_attr(attr, name) attr&.sub(/^#{name}:\s*$/, "#{name}: true")&.sub(/^#{name}:\s+/, "") end ADOC_OPTIONS = %w(htmlstylesheet htmlcoverpage htmlintropage scripts scripts-override scripts-pdf wordstylesheet bare i18nyaml standardstylesheet header wordcoverpage wordintropage ulstyle olstyle htmlstylesheet-override htmltoclevels doctoclevels sectionsplit body-font header-font monospace-font title-font wordstylesheet-override).freeze def extract_options(file) header = file.sub(/\n\n.*$/m, "\n") ret = ADOC_OPTIONS.each_with_object({}) do |w, acc| m = /\n:#{w}: ([^\n]+)\n/.match(header) or next acc[w.gsub(/-/, "").sub(/override$/, "_override") .sub(/pdf$/, "_pdf").to_sym] = m[1] end /\n:data-uri-image: (?[^\n]+)\n/ =~ header /\n:(?hierarchical-assets:[^\n]*)\n/ =~ header /\n:(?use-xinclude:[^\n]*)\n/ =~ header /\n:(?break-up-urls-in-tables:[^\n]*)\n/ =~ header defined?(hier_assets) and hier_assets = empty_attr(hier_assets, "hierarchical-assets") defined?(use_xinclude) and use_xinclude = empty_attr(use_xinclude, "use-xinclude") defined?(break_up) and break_up = empty_attr(break_up, "break-up-urls-in-tables") ret.merge( datauriimage: defined?(datauriimage) ? datauriimage != "false" : nil, hierarchical_assets: defined?(hier_assets) ? hier_assets : nil, use_xinclude: defined?(use_xinclude) ? use_xinclude : nil, break_up_urls_in_tables: defined?(break_up) ? break_up : nil, ).reject { |_, val| val.nil? } end end end end