require"asciidoctor"require"sterile"require"uuidtools"moduleMetanormamoduleUtilsNAMECHAR="\u0000-\u0022\u0024\u002c\u002f\u003a-\u0040\\u005b-\u005e"\"\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e\u2000-\u200b"\"\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze#"\ud800-\uf8ff\ufdd0-\ufdef\ufffe-\uffff".freezeNAMESTARTCHAR="\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\"\u203f-\u2040".freezeclass<<selfdefto_ncname(s)start=s[0]ret1=%r([#{NAMECHAR}#]).match(start)?"_":(%r([#{NAMESTARTCHAR}#]).match(start)?"_#{start}":start)ret2=s[1..-1]||""ret=(ret1||"")+ret2.gsub(%r([#{NAMECHAR}#]),"_")retenddefanchor_or_uuid(node=nil)uuid=UUIDTools::UUID.random_createnode.nil?||node.id.nil?||node.id.empty??"_"+uuid:node.idenddefasciidoc_sub(x)returnnilifx.nil?return""ifx.empty?d=Asciidoctor::Document.new(x.lines.entries,{header_footer: false,backend: :html})b=d.parse.blocks.firstb.apply_subs(b.source)enddeflocaldir(node)docfile=node.attr("docfile")docfile.nil??'./':Pathname.new(docfile).parent.to_s+'/'end# TODO needs internationalisationdefsmartformat(n)n.gsub(/ --? /," — ").gsub(/--/,"—").smart_format.gsub(/</,"<").gsub(/>/,">")enddefendash_date(elem)elem.traversedo|n|n.text?andn.replace(n.text.gsub(/\s+--?\s+/,"–").gsub(/--/,"–"))endend# Set hash value using keys path# mod from https://stackoverflow.com/a/42425884defset_nested_value(hash,keys,new_val)key=keys[0]ifkeys.length==1hash[key]=hash[key].is_a?(Array)?(hash[key]<<new_val):hash[key].nil??new_val:[hash[key],new_val]elseifhash[key].is_a?(Array)hash[key][-1]={}if!hash[key].empty?&&hash[key][-1].nil?hash[key]<<{}ifhash[key].empty?||!hash[key][-1].is_a?(Hash)set_nested_value(hash[key][-1],keys[1..-1],new_val)elsifhash[key].nil?||hash[key].empty?hash[key]={}set_nested_value(hash[key],keys[1..-1],new_val)elsifhash[key].is_a?(Hash)&&!hash[key][keys[1]]set_nested_value(hash[key],keys[1..-1],new_val)elsif!hash[key][keys[1]]hash[key]=[hash[key],{}]set_nested_value(hash[key][-1],keys[1..-1],new_val)elseset_nested_value(hash[key],keys[1..-1],new_val)endendhashenddefsvgmap_rewrite(xmldoc,localdir="")xmldoc.xpath("//svgmap").eachdo|s|nextunlesssrc=s.at(".//image/@src")path=File.file?(src)?src:localdir+srcFile.file?(path)ornextsvg=Nokogiri::XML(File.read(path,encoding: "utf-8"))svgmap_rewrite1(s,svg,path)nextifs.at("./target/eref")s.replace(s.at("./figure"))endenddefsvgmap_rewrite1(s,svg,path)targets=s.xpath("./target").each_with_object({})do|t,m|x=t.at("./xref")andm[t["href"]]="##{x['target']}"x=t.at("./link")andm[t["href"]]=x['target']t.removeift.at("./xref | ./link")endsvg.xpath(".//xmlns:a").eachdo|a|x=targets[a["xlink:href"]]anda["xlink:href"]=xendFile.open(path,"w",encoding: "utf-8"){|f|f.write(svg.to_xml)}end# not currently useddefflatten_rawtext_lines(node,result)node.lines.eachdo|x|ifnode.respond_to?(:context)&&(node.context==:literal||node.context==:listing)result<<x.gsub(/</,"<").gsub(/>/,">")else# strip not only HTML <tag>, and Asciidoc xrefs <<xref>>result<<x.gsub(/<[^>]*>+/,"")endendresultend# not currently used# if node contains blocks, flatten them into a single line;# and extract only raw textdefflatten_rawtext(node)result=[]ifnode.respond_to?(:blocks)&&node.blocks?node.blocks.each{|b|result<<flatten_rawtext(b)}elsifnode.respond_to?(:lines)result=flatten_rawtext_lines(node,result)elsifnode.respond_to?(:text)result<<node.text.gsub(/<[^>]*>+/,"")elseresult<<node.content.gsub(/<[^>]*>+/,"")endresult.reject(&:empty?)endendendend