metanorma/metanorma-cli

View on GitHub
exe/metanorma-manifest

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby

require "yaml"
require "optparse"
require "metanorma"
require "uuidtools"
require "uri"
require "metanorma-cli"

registry = Metanorma::Registry.instance
Metanorma::Cli.load_flavors

options = {}

def uuid
  UUIDTools::UUID.random_create
end

def extract_documents(m)
  return [] unless m && m["sections"]

  ret = []
  m["sections"].each do |s|
    ret << s if s["file"]
    ret << extract_documents(s) if s["sections"]
  end
  ret.flatten
end

def hyperlink(link, suffix)
  return unless link

  link.sub(/\.adoc(?=$|#)/, ".#{suffix}")
end

def iterate(sections, options)
  return "" unless sections

  ret = ""
  Array(sections).each do |m|
    ret += "<clause id='#{uuid}'>\n"
    title = m["title"] && m["number"] ? "#{m['number']}. #{m['title']}" : (m["number"] || m["title"] || "&mdash;")
    ret += "<title>#{title}</title>\n"
    ret += "<p>#{m['type']}</p>\n" if m["type"]
    if m["file"]
      ret += "<p>"
      file = hyperlink(m["file"], "html")
      ret += "<link target='#{file}'>HTML</link> |" if file
      file = hyperlink(m["file"], "pdf")
      ret += "<link target='#{file}'>PDF</link> |" if file
      file = hyperlink(m["file"], "xml")
      ret += "<link target='#{file}'>XML</link> " if file
      if options[:relaton]
        file = URI.escape("#{options[:relaton]}/id/#{m['number']}.xml")
        ret += "| <link target='#{file}'>Relaton XML</link> "
      end
      ret += "</p>\n"
    end
    ret += "<p>#{m['description']}</p>\n" if m["description"]
    if m["revdate"]
      ret += if m["status"]
               "<p>STAGE: #{m['status']} (#{m['revdate']})</p>\n"
             else
               "<p align='right'>#{m['revdate']}</p>\n"
             end
    elsif m["status"]
      ret += "<p>STAGE: #{m['status']}</p>\n"
    end
    ret += iterate(m["sections"], options)
    ret += "</clause>\n"
  end
  ret
end

opt_parser = OptionParser.new do |opts|
  opts.banner += " <file>"
  opts.on(
    "-t",
    "--type TYPE",
    "Type of standard to generate",
  ) { |v| options[:type] = v.to_sym }

  opts.on(
    "-r",
    "--require LIBRARY",
    "Require LIBRARY prior to execution",
  ) do |v|
    options[:require] ||= []
    options[:require] << v
  end

  opts.on(
    "-R dir",
    "--relaton",
    "Insert links to relaton XML, generated by relaton-server-csd, with root directory dir (/id/xxxx is supplied)",
  ) { |v| options[:relaton] = v }

  opts.on_tail("-h", "--help", "Show this message") do
    puts opts
    exit
  end
end
opt_parser.parse!(ARGV)
options[:filename] = ARGV.pop

if options[:require]
  options[:require].each do |r|
    require r
  end
end

manifest = YAML.load_file(options[:filename])

documents = extract_documents(manifest)

# TODO real lookup of namespaces and root elements

out = <<~END
  <#{options[:type]}-standard xmlns="http://riboseinc.com/isoxml">
  <bibdata type="standard">
    <title>#{manifest['title']}</title>
END

# TODO leave in anchor references?
#
documents.each do |d|
  out += <<~END
    <relation type="partOf">
      <bibdata type="standard">
        <title>#{d['title']}</title>
        <docidentifier>#{d['number']}</docidentifier>
        <abstract>#{d['description']}</abstract>
      </bibdata>
    </relation>
  END
end

out += <<~END
  </bibdata>
  <sections>
END

out += iterate(manifest["sections"], options)

out += <<~END
  </sections>
  <#{options[:type]}-standard>
END
outfilename = options[:filename].sub(/\.[^.]+$/, ".xml")
File.open(outfilename, "w") { |f| f.write out }

processor = registry.find_processor(options[:type].to_sym)
ext = :html
file_extension = "html" || processor.output_formats[ext]
outfilename = options[:filename].sub(/\.[^.]+$/, ".#{file_extension}")
isodoc_options = { suppressheadingnumbers: true }
if manifest["htmlstylesheet"]
  isodoc_options[:htmlstylesheet] =
    manifest["htmlstylesheet"]
end
processor.output(out, outfilename, ext, isodoc_options)