# -*- coding: utf-8; frozen_string_literal: true -*- # #-- # Copyright (C) 2009-2019 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown ABBREV_DEFINITION_START = /^#{OPT_SPACE}\*\[(.+?)\]:(.*?)\n/ # Parse the link definition at the current location. def parse_abbrev_definition start_line_number = @src.current_line_number @src.pos += @src.matched_size abbrev_id, abbrev_text = @src[1], @src[2] abbrev_text.strip! if @root.options[:abbrev_defs][abbrev_id] warning("Duplicate abbreviation ID '#{abbrev_id}' on line #{start_line_number} " \ "- overwriting") end @tree.children << new_block_el(:eob, :abbrev_def) @root.options[:abbrev_defs][abbrev_id] = abbrev_text @root.options[:abbrev_attr][abbrev_id] = @tree.children.last true end define_parser(:abbrev_definition, ABBREV_DEFINITION_START) # Correct abbreviation attributes. def correct_abbreviations_attributes @root.options[:abbrev_attr].keys.each do |k| @root.options[:abbrev_attr][k] = @root.options[:abbrev_attr][k].attr end end # Replace the abbreviation text with elements. def replace_abbreviations(el, regexps = nil) return if @root.options[:abbrev_defs].empty? unless regexps sorted_abbrevs = @root.options[:abbrev_defs].keys.sort {|a, b| b.length <=> a.length } regexps = [Regexp.union(*sorted_abbrevs.map {|k| /#{Regexp.escape(k)}/ })] regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries end el.children.map! do |child| if child.type == :text if child.value =~ regexps.first result = [] strscan = Kramdown::Utils::StringScanner.new(child.value, child.options[:location]) text_lineno = strscan.current_line_number while (temp = strscan.scan_until(regexps.last)) abbr_lineno = strscan.current_line_number abbr = strscan.scan(regexps.first) # begin of line case of abbr with \W char as first one if abbr.nil? temp << strscan.scan(/\W|^/) abbr = strscan.scan(regexps.first) end result << Element.new(:text, temp, nil, location: text_lineno) result << Element.new(:abbreviation, abbr, nil, location: abbr_lineno) text_lineno = strscan.current_line_number end result << Element.new(:text, strscan.rest, nil, location: text_lineno) else child end else replace_abbreviations(child, regexps) child end end.flatten! end end end end