# Copyright (c) 2020 Jerome Arbez-Gindre # frozen_string_literal: true require('asciidoctor') module DefMastership # Contains the content of a DefMastership document: mainly definitions # Reflects document structure from a definition point of view class Document attr_reader :definitions, :labels, :eref, :iref, :attributes, :variables def initialize @definitions = [] @labels = Set.new @eref = {} @iref = false @attributes = {} @in_literal = true @variables = {} @definition_parser = DefinitionParser.new(self) end def parse(lines) lines.reject(&:commented?).each do |line| (@in_literal ? FILTERS : FILTERS_IN_LITERAL).each do |filter| next unless line.match(filter.regexp) line = generate_event(filter.event, Regexp.last_match, line) break if filter.consumed_line end end end def parse_file_with_preprocessor(adoc_file) parse(Asciidoctor.load_file(adoc_file, safe: :unsafe, parse: false).reader.read_lines) end def wrong_explicit_checksum? @definitions.reduce(false) do |res, definition| res || !definition.wrong_explicit_checksum.nil? end end def explicit_version? @definitions.reduce(false) do |res, definition| res || !definition.explicit_version.nil? end end def code_block_delimiter(_match, line) @in_literal ^= true line end def add_new_definition(match, line) definition = Definition.new(match) @labels.merge(definition.labels) @definitions << definition line end def ref_to_def(ref) @definitions.find { |definition| definition.reference == ref } end def add_line(_match, line) @definitions.last << line line end def new_eref_setup(match, line) @eref[match[:refname].to_sym] ||= {} @eref[match[:refname].to_sym][match[:symb].to_sym] = match[:value] line end def new_eref_def(match, line) @definitions.last.add_eref(match[:refname].to_sym, match[:extrefs]) line end def new_iref_def(_match, line) @iref = true line.scan(DMRegexp::IREF_DEF) do |_| @definitions.last.add_iref(Regexp.last_match[:intref]) end line end def new_attribute_conf(match, line) @attributes[match[:attr].to_sym] = match[:prefix] line end def new_attribute_value(match, line) @definitions.last.set_attribute(match[:attr].to_sym, match[:value]) line end def new_variable_def(match, line) @variables[match[:varname].to_sym] = match[:value] line end def new_variable_use(_match, line) line.scan(DMRegexp::VARIABLE_USE) do |_| varname = Regexp.last_match[:varname] next if @variables[varname.to_sym].nil? line = line.gsub("{#{varname}}", @variables[varname.to_sym]) end line end private def generate_event(event, match, line) if respond_to?(event) line = public_send(event, match, line) else @definition_parser.public_send(event, match, line) end line end end end