Class: Metanorma::Sectionsplit
- Inherits:
-
Object
- Object
- Metanorma::Sectionsplit
- Defined in:
- lib/metanorma/sectionsplit.rb,
lib/metanorma/sectionsplit_links.rb
Constant Summary collapse
- SPLITSECTIONS =
[["//preface/*", "preface"], ["//sections/*", "sections"], ["//annex", nil], ["//bibliography/*[not(@hidden = 'true')]", "bibliography"], ["//indexsect", nil], ["//colophon", nil]].freeze
Instance Attribute Summary collapse
-
#filecache ⇒ Object
Returns the value of attribute filecache.
-
#key ⇒ Object
Returns the value of attribute key.
Instance Method Summary collapse
- #block?(node) ⇒ Boolean
- #build_collection ⇒ Object
- #coll_cover ⇒ Object
- #collection_manifest(filename, files, origxml, _presxml, dir) ⇒ Object
- #collection_setup(filename, dir) ⇒ Object
- #collectionyaml(files, xml) ⇒ Object
- #conflate_floatingtitles(nodes) ⇒ Object
- #copy_repo_items_biblio(ins, section, xml) ⇒ Object
- #create_sectionfile(xml, out, file, chunks, parentnode) ⇒ Object
- #emptydoc(xml) ⇒ Object
- #eref_to_internal_eref(section, xml, key) ⇒ Object
- #eref_to_internal_eref1(elem, key, url) ⇒ Object
- #eref_to_internal_eref_prep(section, xml) ⇒ Object
- #eref_to_internal_eref_select(section, _xml, bibitems) ⇒ Object
- #indirect_bib?(bibitem) ⇒ Boolean
-
#initialize(opts) ⇒ Sectionsplit
constructor
A new instance of Sectionsplit.
- #insert_indirect_biblio(ins, refs, key, xml) ⇒ Object
- #insert_indirect_biblio_prep(xml) ⇒ Object
- #internal_bib?(bibitem) ⇒ Boolean
- #make_anchor(anchor) ⇒ Object
-
#new_hidden_ref(xmldoc) ⇒ Object
from standoc.
- #new_indirect_bibitem(ident, prefix) ⇒ Object
- #ns(xpath) ⇒ Object
- #section_split_cover(col, ident, one_doc_coll) ⇒ Object
- #sectionfile(fulldoc, xml, file, chunks, parentnode) ⇒ Object
- #sectionfile_insert(ins, chunks, parentnode) ⇒ Object
-
#sectionsplit ⇒ Object
Input XML is Semantic def sectionsplit(filename, basename, dir, compile_options, fileslookup = nil, ident = nil).
- #sectionsplit_prep(file, filename, dir) ⇒ Object
- #sectionsplit_preprocess_semxml(file, filename) ⇒ Object
- #sectionsplit_update_xrefs(xml) ⇒ Object
- #sectionsplit_write_semxml(filename, xml) ⇒ Object
- #svg_preprocess(xml, doc_suffix) ⇒ Object
- #svg_xrefs(svg, svgmap, suffix) ⇒ Object
- #svgmap_wrap(svg) ⇒ Object
- #titlerender(section) ⇒ Object
- #xref_prefix_key(xref, key, indirect) ⇒ Object
- #xref_preprocess(xml, _fileslookup, _identifier) ⇒ Object
- #xref_process(section, xml, key) ⇒ Object
- #xref_to_internal_eref(section, xml, key) ⇒ Object
- #xref_to_internal_eref_anchor(xref, key, bibitems, document_suffix) ⇒ Object
- #xref_to_internal_eref_prep(section, xml) ⇒ Object
Constructor Details
#initialize(opts) ⇒ Sectionsplit
Returns a new instance of Sectionsplit.
9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/metanorma/sectionsplit.rb', line 9 def initialize(opts) @input_filename = opts[:input] @base = opts[:base] @output_filename = opts[:output] @xml = opts[:xml] @dir = opts[:dir] @compile_opts = opts[:compile_opts] || {} @fileslookup = opts[:fileslookup] @ident = opts[:ident] @isodoc = opts[:isodoc] end |
Instance Attribute Details
#filecache ⇒ Object
Returns the value of attribute filecache.
7 8 9 |
# File 'lib/metanorma/sectionsplit.rb', line 7 def filecache @filecache end |
#key ⇒ Object
Returns the value of attribute key.
7 8 9 |
# File 'lib/metanorma/sectionsplit.rb', line 7 def key @key end |
Instance Method Details
#block?(node) ⇒ Boolean
80 81 82 83 84 |
# File 'lib/metanorma/sectionsplit.rb', line 80 def block?(node) %w(p table formula admonition ol ul dl figure quote sourcecode example pre note pagebrreak hr bookmark requirement recommendation permission svgmap inputform toc passthrough review imagemap).include?(node.name) end |
#build_collection ⇒ Object
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/metanorma/sectionsplit.rb', line 25 def build_collection collection_setup(@base, @dir) files = sectionsplit # (@input_filename, @base, @dir, @compile_opts) input_xml = Nokogiri::XML(File.read(@input_filename, encoding: "UTF-8"), &:huge) collection_manifest(@base, files, input_xml, @xml, @dir).render( { format: %i(html), output_folder: "#{@output_filename}_collection", coverpage: File.join(@dir, "cover.html") }.merge(@compile_opts), ) end |
#coll_cover ⇒ Object
51 52 53 54 55 56 57 58 59 |
# File 'lib/metanorma/sectionsplit.rb', line 51 def coll_cover <<~COVER <html><head><meta charset="UTF-8"/></head><body> <h1>{{ doctitle }}</h1> <h2>{{ docnumber }}</h2> <nav>{{ navigation }}</nav> </body></html> COVER end |
#collection_manifest(filename, files, origxml, _presxml, dir) ⇒ Object
36 37 38 39 40 41 |
# File 'lib/metanorma/sectionsplit.rb', line 36 def collection_manifest(filename, files, origxml, _presxml, dir) File.open(File.join(dir, "#{filename}.html.yaml"), "w:UTF-8") do |f| f.write(collectionyaml(files, origxml)) end Metanorma::Collection.parse File.join(dir, "#{filename}.html.yaml") end |
#collection_setup(filename, dir) ⇒ Object
43 44 45 46 47 48 49 |
# File 'lib/metanorma/sectionsplit.rb', line 43 def collection_setup(filename, dir) FileUtils.mkdir_p "#{filename}_collection" if filename FileUtils.mkdir_p dir File.open(File.join(dir, "cover.html"), "w:UTF-8") do |f| f.write(coll_cover) end end |
#collectionyaml(files, xml) ⇒ Object
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/metanorma/sectionsplit.rb', line 178 def collectionyaml(files, xml) ret = { directives: ["presentation-xml", "bare-after-first"], bibdata: { title: { type: "title-main", language: @lang, content: xml.at(ns("//bibdata/title")).text }, type: "collection", docid: { type: xml.at(ns("//bibdata/docidentifier/@type")).text, id: xml.at(ns("//bibdata/docidentifier")).text, }, }, manifest: { level: "collection", title: "Collection", docref: files.sort_by { |f| f[:order] }.each.map do |f| { fileref: f[:url], identifier: f[:title] } end }, } Util::recursive_string_keys(ret).to_yaml end |
#conflate_floatingtitles(nodes) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/metanorma/sectionsplit.rb', line 86 def conflate_floatingtitles(nodes) holdover = false nodes.each_with_object([]) do |x, m| if holdover then m.last << x else m << [x] end holdover = block?(x) end end |
#copy_repo_items_biblio(ins, section, xml) ⇒ Object
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/metanorma/sectionsplit_links.rb', line 150 def copy_repo_items_biblio(ins, section, xml) bibitems = Util::gather_bibitems(section) xml.xpath(ns("//references/bibitem[docidentifier/@type = 'repository']")) .each_with_object([]) do |b, m| bibitems[b["id"]] or next # section.at("//*[@bibitemid = '#{b['id']}']") or next ins << b.dup m << b["id"] end end |
#create_sectionfile(xml, out, file, chunks, parentnode) ⇒ Object
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/metanorma/sectionsplit.rb', line 151 def create_sectionfile(xml, out, file, chunks, parentnode) ins = out.at(ns("//metanorma-extension")) || out.at(ns("//bibdata")) sectionfile_insert(ins, chunks, parentnode) xref_process(out, xml, @key) outname = "#{file}.xml" File.open(File.join(@splitdir, outname), "w:UTF-8") do |f| f.write(out) end outname end |
#emptydoc(xml) ⇒ Object
135 136 137 138 139 140 141 142 143 |
# File 'lib/metanorma/sectionsplit.rb', line 135 def emptydoc(xml) out = xml.dup out.xpath( ns("//preface | //sections | //annex | //bibliography/clause | " \ "//bibliography/references[not(@hidden = 'true')] | //indexsect | " \ "//colophon"), ).each(&:remove) out end |
#eref_to_internal_eref(section, xml, key) ⇒ Object
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/metanorma/sectionsplit_links.rb', line 93 def eref_to_internal_eref(section, xml, key) bibitems, bibitemids = eref_to_internal_eref_prep(section, xml) eref_to_internal_eref_select(section, xml, bibitems) .each_with_object([]) do |x, m| url = bibitems[x]&.at(ns("./uri[@type = 'citation']")) bibitemids[x]&.each do |e| id = eref_to_internal_eref1(e, key, url) and m << id end end end |
#eref_to_internal_eref1(elem, key, url) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/metanorma/sectionsplit_links.rb', line 111 def eref_to_internal_eref1(elem, key, url) if url elem.name = "link" elem["target"] = url nil else elem["bibitemid"] = "#{key}_#{elem['bibitemid']}" elem << make_anchor(elem["bibitemid"]) elem["type"] = key elem["bibitemid"] end end |
#eref_to_internal_eref_prep(section, xml) ⇒ Object
104 105 106 107 108 109 |
# File 'lib/metanorma/sectionsplit_links.rb', line 104 def eref_to_internal_eref_prep(section, xml) bibitems = Util::gather_bibitems(xml) .delete_if { |_, v| internal_bib?(v) } bibitemids = Util::gather_bibitemids(section) [bibitems, bibitemids] end |
#eref_to_internal_eref_select(section, _xml, bibitems) ⇒ Object
124 125 126 127 128 129 |
# File 'lib/metanorma/sectionsplit_links.rb', line 124 def eref_to_internal_eref_select(section, _xml, bibitems) refs = Util::gather_bibitemids(section).keys refs.uniq.reject do |x| b = bibitems[x] and ( indirect_bib?(b) || internal_bib?(b) ) end end |
#indirect_bib?(bibitem) ⇒ Boolean
136 137 138 139 140 141 |
# File 'lib/metanorma/sectionsplit_links.rb', line 136 def indirect_bib?(bibitem) a = bibitem.at(ns("./docidentifier[@type = 'repository']")) or return false %r{^current-metanorma-collection/}.match?(a.text) and return false a.text.include?("/") end |
#insert_indirect_biblio(ins, refs, key, xml) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/metanorma/sectionsplit_links.rb', line 161 def insert_indirect_biblio(ins, refs, key, xml) refs.empty? and return internal_bibitems, external_bibitems = insert_indirect_biblio_prep(xml) refs.compact.reject do |x| #external_bibitems[x.sub(/^#{key}_/, "")] end.each do |x| ins << if b = internal_bibitems[x.sub(/^#{key}_/, "")] b.dup.tap { |m| m["id"] = x } else new_indirect_bibitem(x, key) end end end |
#insert_indirect_biblio_prep(xml) ⇒ Object
174 175 176 177 178 179 |
# File 'lib/metanorma/sectionsplit_links.rb', line 174 def insert_indirect_biblio_prep(xml) bibitems = Util::gather_bibitems(xml) internal_bibitems = bibitems.select { |_, v| internal_bib?(v) } external_bibitems = bibitems.reject { |_, v| internal_bib?(v) } [internal_bibitems, external_bibitems] end |
#internal_bib?(bibitem) ⇒ Boolean
131 132 133 134 |
# File 'lib/metanorma/sectionsplit_links.rb', line 131 def internal_bib?(bibitem) bibitem["type"] == "internal" || bibitem.at(ns("./docidentifier[@type = 'repository']")) end |
#make_anchor(anchor) ⇒ Object
49 50 51 52 |
# File 'lib/metanorma/sectionsplit_links.rb', line 49 def make_anchor(anchor) "<localityStack><locality type='anchor'><referenceFrom>" \ "#{anchor}</referenceFrom></locality></localityStack>" end |
#new_hidden_ref(xmldoc) ⇒ Object
from standoc
144 145 146 147 148 |
# File 'lib/metanorma/sectionsplit_links.rb', line 144 def new_hidden_ref(xmldoc) ins = xmldoc.at("bibliography") or xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography") ins.add_child("<references hidden='true' normative='false'/>").first end |
#new_indirect_bibitem(ident, prefix) ⇒ Object
181 182 183 184 185 186 187 |
# File 'lib/metanorma/sectionsplit_links.rb', line 181 def new_indirect_bibitem(ident, prefix) <<~BIBENTRY <bibitem id="#{ident}" type="internal"> <docidentifier type="repository">#{ident.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier> </bibitem> BIBENTRY end |
#ns(xpath) ⇒ Object
21 22 23 |
# File 'lib/metanorma/sectionsplit.rb', line 21 def ns(xpath) @isodoc.ns(xpath) end |
#section_split_cover(col, ident, one_doc_coll) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/metanorma/sectionsplit.rb', line 202 def section_split_cover(col, ident, one_doc_coll) dir = File.dirname(col.file) collection_setup(nil, dir) CollectionRenderer.new(col, dir, output_folder: "#{ident}_collection", format: %i(html), coverpage: File.join(dir, "cover.html")).coverpage #filename = one_doc_coll ? "#{ident}_index.html" : "index.html" filename = "#{ident}_index.html" FileUtils.mv "#{ident}_collection/index.html", File.join(dir, filename) FileUtils.rm_rf "#{ident}_collection" filename end |
#sectionfile(fulldoc, xml, file, chunks, parentnode) ⇒ Object
145 146 147 148 149 |
# File 'lib/metanorma/sectionsplit.rb', line 145 def sectionfile(fulldoc, xml, file, chunks, parentnode) fname = create_sectionfile(fulldoc, xml.dup, file, chunks, parentnode) { order: chunks.last["displayorder"].to_i, url: fname, title: titlerender(chunks.last) } end |
#sectionfile_insert(ins, chunks, parentnode) ⇒ Object
162 163 164 165 166 167 168 |
# File 'lib/metanorma/sectionsplit.rb', line 162 def sectionfile_insert(ins, chunks, parentnode) if parentnode ins.next = "<#{parentnode}/>" chunks.each { |c| ins.next.add_child(c.dup) } else chunks.each { |c| ins.next = c.dup } end end |
#sectionsplit ⇒ Object
Input XML is Semantic def sectionsplit(filename, basename, dir, compile_options, fileslookup = nil, ident = nil)
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/metanorma/sectionsplit.rb', line 69 def sectionsplit xml = sectionsplit_prep(File.read(@input_filename), @base, @dir) @key = xref_preprocess(xml, @fileslookup, @ident) SPLITSECTIONS.each_with_object([]) do |n, ret| conflate_floatingtitles(xml.xpath(ns(n[0]))).each do |s| ret << sectionfile(xml, emptydoc(xml), "#{@base}.#{ret.size}", s, n[1]) end end end |
#sectionsplit_prep(file, filename, dir) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/metanorma/sectionsplit.rb', line 96 def sectionsplit_prep(file, filename, dir) @splitdir = dir xml1filename, type = sectionsplit_preprocess_semxml(file, filename) Compile.new.compile( xml1filename, { format: :asciidoc, extension_keys: [:presentation], type: type } .merge(@compile_opts), ) Nokogiri::XML(File.read(xml1filename.sub(/\.xml$/, ".presentation.xml"), encoding: "utf-8"), &:huge) end |
#sectionsplit_preprocess_semxml(file, filename) ⇒ Object
108 109 110 111 112 113 114 115 116 |
# File 'lib/metanorma/sectionsplit.rb', line 108 def sectionsplit_preprocess_semxml(file, filename) xml = Nokogiri::XML(file, &:huge) type = xml.root.name.sub("-standard", "").to_sym sectionsplit_update_xrefs(xml) xml1 = sectionsplit_write_semxml(filename, xml) @filecache ||= [] @filecache << xml1 [xml1.path, type] end |
#sectionsplit_update_xrefs(xml) ⇒ Object
118 119 120 121 122 123 124 125 |
# File 'lib/metanorma/sectionsplit.rb', line 118 def sectionsplit_update_xrefs(xml) if c = @fileslookup&.parent n = c.nested c.nested = true # so unresolved erefs are not deleted c.update_xrefs(xml, @ident, {}) c.nested = n end end |
#sectionsplit_write_semxml(filename, xml) ⇒ Object
127 128 129 130 131 132 133 |
# File 'lib/metanorma/sectionsplit.rb', line 127 def sectionsplit_write_semxml(filename, xml) Tempfile.open([filename, ".xml"], encoding: "utf-8") do |f| # f.write(@isodoc.to_xml(svg_preprocess(xml))) f.write(@isodoc.to_xml(xml)) f end end |
#svg_preprocess(xml, doc_suffix) ⇒ Object
24 25 26 27 28 29 30 31 |
# File 'lib/metanorma/sectionsplit_links.rb', line 24 def svg_preprocess(xml, doc_suffix) suffix = doc_suffix.nil? || doc_suffix.blank? ? "" : "_#{doc_suffix}" xml.xpath("//m:svg", "m" => "http://www.w3.org/2000/svg").each do |s| m = svgmap_wrap(s) svg_xrefs(s, m, suffix) end xml end |
#svg_xrefs(svg, svgmap, suffix) ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/metanorma/sectionsplit_links.rb', line 40 def svg_xrefs(svg, svgmap, suffix) svg.xpath(".//m:a", "m" => "http://www.w3.org/2000/svg").each do |a| /^#/.match? a["href"] or next a["href"] = a["href"].sub(/^#/, "") svgmap << "<target href='#{a['href']}'>" \ "<xref target='#{a['href']}#{suffix}'/></target>" end end |
#svgmap_wrap(svg) ⇒ Object
33 34 35 36 37 38 |
# File 'lib/metanorma/sectionsplit_links.rb', line 33 def svgmap_wrap(svg) ret = svg.at("./ancestor::xmlns:svgmap") and return ret ret = svg.at("./ancestor::xmlns:figure") ret.wrap("<svgmap/>") svg.at("./ancestor::xmlns:svgmap") end |
#titlerender(section) ⇒ Object
170 171 172 173 174 175 176 |
# File 'lib/metanorma/sectionsplit.rb', line 170 def titlerender(section) title = section.at(ns("./title")) or return "[Untitled]" t = title.dup t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") } t.xpath(ns(".//strong")).each { |x| x.replace(x.children) } t.children.to_xml end |
#xref_prefix_key(xref, key, indirect) ⇒ Object
83 84 85 86 87 88 89 90 91 |
# File 'lib/metanorma/sectionsplit_links.rb', line 83 def xref_prefix_key(xref, key, indirect) if b = indirect[xref["target"]] t = b.at(ns("./docidentifier[@type = 'repository']")) xref["type"] = t.text.sub(%r{/.*$}, "") else xref["target"] = "#{key}_#{xref['target']}" xref["type"] = key end end |
#xref_preprocess(xml, _fileslookup, _identifier) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 |
# File 'lib/metanorma/sectionsplit_links.rb', line 3 def xref_preprocess(xml, _fileslookup, _identifier) key = (0...8).map { rand(65..90).chr }.join # random string xml.root["type"] = key # to force recognition of internal refs # bookmarks etc as new id elements introduced in Presentation XML: # add doc suffix Metanorma::Utils::anchor_attributes.each do |(tag_name, attribute_name)| Util::add_suffix_to_attributes(xml, xml.root["document_suffix"], tag_name, attribute_name, @isodoc) end key end |
#xref_process(section, xml, key) ⇒ Object
15 16 17 18 19 20 21 22 |
# File 'lib/metanorma/sectionsplit_links.rb', line 15 def xref_process(section, xml, key) svg_preprocess(section, Metanorma::Utils::to_ncname(@ident)) refs = eref_to_internal_eref(section, xml, key) refs += xref_to_internal_eref(section, xml, key) ins = new_hidden_ref(section) copied_refs = copy_repo_items_biblio(ins, section, xml) insert_indirect_biblio(ins, refs - copied_refs, key, xml) end |
#xref_to_internal_eref(section, xml, key) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/metanorma/sectionsplit_links.rb', line 54 def xref_to_internal_eref(section, xml, key) bibitems, indirect = xref_to_internal_eref_prep(section, xml) section.xpath(ns("//xref")).each_with_object({}) do |x, m| xref_prefix_key(x, key, indirect) x["bibitemid"] = x["target"] m[x["bibitemid"]] = true xref_to_internal_eref_anchor(x, key, bibitems, xml.root["document_suffix"]) end.keys end |
#xref_to_internal_eref_anchor(xref, key, bibitems, document_suffix) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/metanorma/sectionsplit_links.rb', line 71 def xref_to_internal_eref_anchor(xref, key, bibitems, document_suffix) t = xref["target"] if d = bibitems[t]&.at(ns("./docidentifier[@type = 'repository']")) m = %r{^([^/]+)}.match(d.text) and t.sub!(%r(#{m[0]}_), "") end t.sub!(%r{^#{key}_}, "") xref << make_anchor(t.sub(%r(_#{document_suffix}$), "")) xref.delete("target") xref.name = "eref" end |
#xref_to_internal_eref_prep(section, xml) ⇒ Object
64 65 66 67 68 69 |
# File 'lib/metanorma/sectionsplit_links.rb', line 64 def xref_to_internal_eref_prep(section, xml) bibitems = Util::gather_bibitems(section) indirect_bibitems = Util::gather_bibitems(xml) .select { |_, v| indirect_bib?(v) } [bibitems, indirect_bibitems] end |