# frozen_string_literal: true require('asciidoctor/extensions') unless RUBY_ENGINE == 'opal' # An extension that allow to define applicable definitions # # Usage # :tag-mylabel-color: yellow # :tag-otherlabel-color: red # # # [define, requirement, TOTO-0001, [mylabel, otherlabel]] # -- # The system shall allow to do lots of things. # -- # # or # # [define, requirement, TOTO-0001] # This shall be nice. # require('defmastership/constants') module Asciidoctor module DefMastership # Preprocessor to replace adoc statements class Preprocessor < Asciidoctor::Extensions::Preprocessor EREF_CONFIG_REGEXP = ::DefMastership::DMRegexp::EREF_CONFIG DEFINITION_REGEXP = ::DefMastership::DMRegexp::DEFINITION EREF_DEF_REGEXP = ::DefMastership::DMRegexp::EREF_DEF IREF_DEF_REGEXP = ::DefMastership::DMRegexp::IREF_DEF ATTR_CONFIG_REGEXP = ::DefMastership::DMRegexp::ATTR_CONFIG ATTR_SET_REGEXP = ::DefMastership::DMRegexp::ATTR_SET private_constant :EREF_CONFIG_REGEXP, :DEFINITION_REGEXP, :EREF_DEF_REGEXP, :IREF_DEF_REGEXP, :ATTR_CONFIG_REGEXP, :ATTR_SET_REGEXP Filter = Struct.new(:regex, :apply) FILTERS = [ Filter.new(EREF_CONFIG_REGEXP, :set_eref_url_if_any), Filter.new(DEFINITION_REGEXP, :build_definition), Filter.new(EREF_DEF_REGEXP, :build_external_ref), Filter.new(IREF_DEF_REGEXP, :build_internal_ref), Filter.new(ATTR_SET_REGEXP, :attribute_setting) ].freeze private_constant :FILTERS # class initialization def initialize(config = {}) super(config) # This is a preprocessor: we need to parse tag attributes @parsing_is_enabled = true @has_url = {} end # process the document def process(_document, reader) return reader if reader.eof? reader.unshift_lines(parse_and_replace(reader.read_lines)) reader end private def parse_and_replace(lines) parsing_is_enabled = true lines.reduce([]) do |new_lines, line| parsing_is_enabled = !parsing_is_enabled if line == '....' filter = FILTERS.find { |onefilter| line.match(onefilter.regex) } if filter && parsing_is_enabled new_lines + __send__(filter.apply, line, Regexp.last_match) else new_lines + [line] end end end def set_eref_url_if_any(line, matches) @has_url[matches[:refname]] = true if matches[:symb] == 'url' && matches[:value] != 'none' [line] end def build_definition(_line, matches) definition_lines = [] if matches[:labels] labels_str = labels_strings(matches[:labels]).join(' ') definition_lines << ".#{matches[:reference]} #{labels_str}" else definition_lines << ".#{matches[:reference]}" end definition_lines << "[\##{matches[:reference]}.define.#{matches[:type]}]" definition_lines end def labels_strings(labels) labels_strs = [] labels.split(/\s*,\s*/).reject(&:empty?).each do |label| labels_strs << "[.tag.{tag-#{label}-color}]\##{label}\#" end labels_strs end def build_link(ref, matches) if @has_url[matches[:refname]] "link:{eref-#{matches[:refname]}-url}\##{ref}\[#{ref}]" else ref end end def build_external_ref(_line, matches) extrefs = matches[:extrefs].split(/\s*,\s*/) new_line = "[.external_reference]\#{eref-#{matches[:refname]}-prefix} " extref_line = extrefs.map { |ref| build_link(ref, matches) } @has_url[matches[:refname]] ["#{new_line}#{extref_line.join(', ')}.\#"] end def build_internal_ref(line, _matches) [line.gsub(IREF_DEF_REGEXP) do "<<#{Regexp.last_match[:intref]},#{Regexp.last_match[:intref]}>>" end] end def attribute_setting(_line, matches) [ '[.attribute]', "{attr-#{matches[:attr]}-prefix} #{matches[:value]}." ] end end end end