blob: 8c404a7de84b346aa85b61d67290da9af0280520 [file] [log] [blame]
# -*- coding: utf-8 -*-
#
#--
# Copyright (C) 2009-2016 Thomas Leitner <t_leitner@gmx.at>
#
# 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!
warning("Duplicate abbreviation ID '#{abbrev_id}' on line #{start_line_number} - overwriting") if @root.options[:abbrev_defs][abbrev_id]
@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?
if !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