resources/asciidoctor/lib/edit_me/extension.rb (86 lines of code) (raw):

# frozen_string_literal: true require 'asciidoctor/extensions' require 'csv' require_relative '../delegating_converter' require_relative '../log_util' ## # Automatically adds "Edit Me" links to appropriate spots in the documentation. module EditMe extend LogUtil def self.activate(registry) error message: 'sourcemap is required' unless registry.document.sourcemap return unless configure registry.document DelegatingConverter.setup(registry.document) do |doc| Converter.new doc end end def self.configure(document) edit_urls_string = document.attributes['edit_urls'] return unless edit_urls_string if edit_urls_string.is_a? String document.attributes['edit_urls'] = parse_edit_urls edit_urls_string return unless document.attributes['edit_urls'] end true end def self.parse_edit_urls(edit_urls_string) edit_urls = [] CSV.parse edit_urls_string do |toplevel, url| handle_link edit_urls, toplevel, url end # Prefer the longest matching edit url edit_urls.sort_by { |e| [-e[:toplevel].length, e[:toplevel]] } end def self.handle_link(edit_urls, toplevel, url) unless toplevel error message: 'invalid edit_urls, no toplevel' return end unless url error message: 'invalid edit_urls, no url' return end url = url[0..-2] if url.end_with? '/' edit_urls << { toplevel: toplevel, url: url } end ## # Converter implementation that decorates titles with edit me links. class Converter < DelegatingConverter include LogUtil RESPECT_OVERRIDES = 'respect_edit_url_overrides' def convert_section(block) block.attributes['edit_me_link'] = link_for block yield end def convert_floating_title(block) block.attributes['edit_me_link'] = link_for block yield end def link_for(block) url = edit_url block return '' unless url if block.document.attr 'private_edit_urls' css_classes = 'edit_me edit_me_private' title = 'Editing on GitHub is available to Elastic' else css_classes = 'edit_me' title = 'Edit this page on GitHub' end <<~HTML.strip <a class="#{css_classes}" rel="nofollow" title="#{title}" href="#{url}">edit</a> HTML end def edit_url(block) return edit_url_by_path block unless block.document.attr RESPECT_OVERRIDES url = block.document.attr 'edit_url' return false if url == '' return url if url edit_url_by_path block end def edit_url_by_path(block) # source_location.path doesn't work for relative includes outside of # the base_dir which we use when we build books from many repos. # || '<stdin>' allows us to not blow up when translating strings that # aren't associated with any particular file. '<stdin>' is asciidoctor's # standard name for such strings. path = block.source_location&.file || '<stdin>' edit_urls = block.document.attr 'edit_urls' entry = edit_urls.find { |e| path.start_with? e[:toplevel] } return url_for_path path, entry if entry warn block: block, message: <<~WARN.strip couldn't find edit url for #{path} WARN false end def url_for_path(path, entry) url = entry[:url] if url == '<disable>' false else url + path[entry[:toplevel].length..-1] end end end end