resources/asciidoctor/lib/alternative_language_lookup/listing.rb (98 lines of code) (raw):

# frozen_string_literal: true require_relative 'alternative' require_relative '../log_util' module AlternativeLanguageLookup ## # Information about a listing in the original document. class Listing RESULT_SUFFIX = '-result' RESULT_SUFFIX_LENGTH = RESULT_SUFFIX.length include LogUtil attr_reader :block attr_reader :lang attr_reader :is_result attr_reader :alternatives def initialize(block) @block = block @lang = block.attr 'language' return unless @lang @is_result = @lang.end_with? RESULT_SUFFIX lookups = block.document.attr 'alternative_language_lookups' @alternatives = lookups[key_lang] @listing_index = nil # We'll look it up when we need it @colist_offset = 1 end def process return unless alternatives block.attributes['digest'] = digest found_langs = [] alternatives.each do |lookup| add_alternative_if_present found_langs, lookup end report found_langs cleanup_original_after_add found_langs unless found_langs.empty? end def add_alternative_if_present(found_langs, lookup) return unless (found = lookup.index[digest]) # TODO: we can probably cache this. There are lots of dupes. alt_lang = lookup.alternative_lang_for @is_result alternative = Alternative.new document, alt_lang, found[:path] alternative_listing = alternative.listing @block.parent return unless alternative_listing alternative_colist = alternative.colist @block.parent insert alternative_listing, alternative_colist found_langs << lookup.alternative_lang end def insert(alternative_listing, alternative_colist) find_listing unless @listing_index parent.blocks.insert @listing_index, alternative_listing @listing_index += 1 return unless alternative_colist parent.blocks.insert @listing_index + @colist_offset, alternative_colist @colist_offset += 1 end def find_listing # Find the right spot in the parent's blocks to add any alternatives: # right after this block's callouts if it has any, otherwise just after # this block. @listing_index = parent.blocks.find_index(@block) if @listing_index # While we're here check if there is a callout list. colist = parent.blocks[@listing_index + 1] @colist = colist&.context == :colist ? colist : nil else message = "Invalid document: parent doesn't include child!" error location: source_location, message: message # In grand Asciidoctor tradition we'll *try* to make some # output though @listing_index = 0 @colist = nil end end def cleanup_original_after_add(found_langs) # We're obligated to reindex the sections inside parent because we've # chaged its blocks. parent.reindex_sections # Add some roles which will translate into classes to the original # listing block and the callout. We'll use these to hide the default # language when you pick an override language. has_roles = found_langs.map { |lang| "has-#{lang}" }.join ' ' @block.attributes['role'] = "default #{has_roles}" return unless @colist @colist.attributes['role'] = "default #{has_roles} lang-#{@lang}" end def report(found_langs) report = document.attr 'alternative_language_report' report&.report self, found_langs summary = document.attr 'alternative_language_summary' summary&.on_listing self, found_langs end def parent @block.parent end def document @block.document end def source_location @block.source_location end def source @source ||= @block.source end def digest @digest ||= Digest::MurmurHash3_x64_128.hexdigest source end ## # `key_lang` normalises `lang` into the lookup key for alternatives. def key_lang if @is_result @lang[0, @lang.length - RESULT_SUFFIX_LENGTH] else @lang end end end end