resources/asciidoctor/lib/chunker/extension.rb (138 lines of code) (raw):

# frozen_string_literal: true require 'asciidoctor/extensions' require_relative '../delegating_converter' require_relative '../strip_tags' require_relative 'breadcrumbs' require_relative 'convert_outline' require_relative 'extra_docinfo' require_relative 'find_related' require_relative 'footnotes' require_relative 'nav' require_relative 'url_to_v3' ## # HTML5 converter that chunks like docbook. module Chunker def self.activate(registry) doc = registry.document return unless doc.attr 'outdir' return unless (chunk_level = doc.attr 'chunk_level') doc.extend ExtraDocinfo return if doc.attr 'subdoc' doc.attributes['toclevels'] ||= doc.attributes['chunk_level'] DelegatingConverter.setup(registry.document) do |d| Converter.new d, chunk_level.to_i end end ## # A Converter implementation that chunks like docbook. class Converter < DelegatingConverter include Breadcrumbs include ConvertOutline include FindRelated include Footnotes include StripTags def initialize(delegate, chunk_level) super(delegate) @chunk_level = chunk_level end def convert_document(doc) title = doc.doctitle partition: true doc.attributes['home'] = strip_tags( title.main.strip + doc.attr('title-extra', '') ) doc.attributes['next_section'] = find_next_in doc, 0 add_nav doc add_url_to_v3 doc yield end def convert_section(section) doc = section.document return yield unless section.level <= @chunk_level html = form_section_into_page doc, section, yield # Replace the breadcrumbs placeholder with # the generated breadcrumbs if html =~ %r{<div id="breadcrumbs-go-here"></div>} html.gsub!( %r{<div id="breadcrumbs-go-here"></div>}, generate_breadcrumbs(doc, section).to_s ) end html.gsub!(%r{</h1>}, "</h1>#{section.attr('edit_me_link', '')}") write doc, "#{section.id}.html", html '' end def convert_inline_anchor(node) correct_xref node if node.type == :xref yield end def add_nav(doc) nav = Nav.new doc doc.blocks.insert 0, nav.header doc.blocks.append nav.footer end def add_url_to_v3(doc) url_to_v3 = UrlToV3.new doc doc.blocks.insert 0, url_to_v3.url end def correct_xref(node) refid = node.attributes['refid'] return unless (ref = node.document.catalog[:refs][refid]) page = page_containing ref node.target = "#{page.id}.html" node.target += "##{ref.id}" unless page == ref end def page_containing(node) page = node while page.context != :section || page.level > @chunk_level page = page.parent end page end def form_section_into_page(doc, section, html) # We don't use asciidoctor's "parent" documents here because they don't # seem to buy us much and they are an "internal" detail. subdoc = Asciidoctor::Document.new [], subdoc_opts(doc, section) add_subdoc_sections doc, subdoc, html subdoc.convert end def add_subdoc_sections(doc, subdoc, html) nav = Nav.new subdoc url_to_v3 = UrlToV3.new subdoc subdoc << url_to_v3.url subdoc << nav.header subdoc << Asciidoctor::Block.new(subdoc, :pass, source: html) subdoc << footnotes(doc, subdoc) if doc.footnotes? subdoc << nav.footer end def subdoc_opts(doc, section) { attributes: subdoc_attrs(doc, section), safe: doc.safe, backend: doc.backend, sourcemap: doc.sourcemap, base_dir: doc.base_dir, to_dir: doc.options[:to_dir], standalone: true, } end def subdoc_attrs(doc, section) attrs = doc.attributes.dup maintitle = doc.doctitle partition: true # Rendered h1 heading attrs['doctitle'] = subdoc_doctitle section # Value of `title` in the `head` attrs['title'] = subdoc_title section, maintitle # Asciidoctor defaults these attribute to empty string if they aren't # specified and setting them to `nil` clears them. Since we want to # preserve the configuration from the parent into the child, we clear # explicitly them if they aren't found in the parent. If we didn't then # they'd default to fale. attrs['stylesheet'] = nil unless attrs['stylesheet'] attrs['icons'] = nil unless attrs['icons'] attrs['subdoc'] = true # Mark the subdoc so we don't try and chunk it attrs['title-separator'] = '' attrs['canonical-url'] = section.attributes['canonical-url'] attrs['current-url'] = "#{section.id}.html" attrs.merge! find_related(section) attrs end # For the `h1` heading that appears on the rendered page, # use just the page title def subdoc_doctitle(section) strip_tags section.captioned_title.to_s end # For the `title` in the `head`, use the page title followed # by the site title ("Elastic") def subdoc_title(section, maintitle) strip_tags "#{section.captioned_title} | #{maintitle.main}" end def write(doc, file, html) dir = doc.attr 'outdir' path = File.join dir, file File.open path, 'w:UTF-8' do |f| f.write html end file end end end