/usr/lib/ruby/vendor_ruby/kramdown/parser/kramdown/list.rb is in ruby-kramdown 1.15.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | # -*- 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.
#++
#
require 'kramdown/parser/kramdown/blank_line'
require 'kramdown/parser/kramdown/eob'
require 'kramdown/parser/kramdown/horizontal_rule'
require 'kramdown/parser/kramdown/extensions'
module Kramdown
module Parser
class Kramdown
LIST_ITEM_IAL = /^\s*(?:\{:(?!(?:#{ALD_ID_NAME})?:|\/)(#{ALD_ANY_CHARS}+)\})\s*/
LIST_ITEM_IAL_CHECK = /^#{LIST_ITEM_IAL}?\s*\n/
PARSE_FIRST_LIST_LINE_REGEXP_CACHE = Hash.new do |h, indentation|
indent_re = /^ {#{indentation}}/
content_re = /^(?:(?:\t| {4}){#{indentation / 4}} {#{indentation % 4}}|(?:\t| {4}){#{indentation / 4 + 1}}).*\S.*\n/
lazy_re = /(?!^ {0,#{[indentation, 3].min}}(?:#{IAL_BLOCK}|#{LAZY_END_HTML_STOP}|#{LAZY_END_HTML_START})).*\S.*\n/
h[indentation] = [content_re, lazy_re, indent_re]
end
# Used for parsing the first line of a list item or a definition, i.e. the line with list item
# marker or the definition marker.
def parse_first_list_line(indentation, content)
if content =~ self.class::LIST_ITEM_IAL_CHECK
indentation = 4
else
while content =~ /^ *\t/
temp = content.scan(/^ */).first.length + indentation
content.sub!(/^( *)(\t+)/) {$1 << " "*(4 - (temp % 4) + ($2.length - 1)*4)}
end
indentation += content[/^ */].length
end
content.sub!(/^\s*/, '')
[content, indentation, *PARSE_FIRST_LIST_LINE_REGEXP_CACHE[indentation]]
end
LIST_START_UL = /^(#{OPT_SPACE}[+*-])([\t| ].*?\n)/
LIST_START_OL = /^(#{OPT_SPACE}\d+\.)([\t| ].*?\n)/
LIST_START = /#{LIST_START_UL}|#{LIST_START_OL}/
# Parse the ordered or unordered list at the current location.
def parse_list
start_line_number = @src.current_line_number
type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
list = new_block_el(type, nil, nil, :location => start_line_number)
item = nil
content_re, lazy_re, indent_re = nil
eob_found = false
nested_list_found = false
last_is_blank = false
while !@src.eos?
start_line_number = @src.current_line_number
if last_is_blank && @src.check(HR_START)
break
elsif @src.scan(EOB_MARKER)
eob_found = true
break
elsif @src.scan(list_start_re)
item = Element.new(:li, nil, nil, :location => start_line_number)
item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
list.children << item
item.value.sub!(self.class::LIST_ITEM_IAL) do |match|
parse_attribute_list($1, item.options[:ial] ||= {})
''
end
list_start_re = (type == :ul ? /^( {0,#{[3, indentation - 1].min}}[+*-])([\t| ].*?\n)/ :
/^( {0,#{[3, indentation - 1].min}}\d+\.)([\t| ].*?\n)/)
nested_list_found = (item.value =~ LIST_START)
last_is_blank = false
item.value = [item.value]
elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
result.sub!(/^(\t+)/) { " " * 4 * $1.length }
indentation_found = result.sub!(indent_re, '')
if !nested_list_found && indentation_found && result =~ LIST_START
item.value << ''
nested_list_found = true
elsif nested_list_found && !indentation_found && result =~ LIST_START
result = " " * (indentation + 4) << result
end
item.value.last << result
last_is_blank = false
elsif result = @src.scan(BLANK_LINE)
nested_list_found = true
last_is_blank = true
item.value.last << result
else
break
end
end
@tree.children << list
last = nil
list.children.each do |it|
temp = Element.new(:temp, nil, nil, :location => it.options[:location])
env = save_env
location = it.options[:location]
it.value.each do |val|
@src = ::Kramdown::Utils::StringScanner.new(val, location)
parse_blocks(temp)
location = @src.current_line_number
end
restore_env(env)
it.children = temp.children
it.value = nil
next if it.children.size == 0
# Handle the case where an EOB marker is inserted by a block IAL for the first paragraph
it.children.delete_at(1) if it.children.first.type == :p &&
it.children.length >= 2 && it.children[1].type == :eob && it.children.first.options[:ial]
if it.children.first.type == :p &&
(it.children.length < 2 || it.children[1].type != :blank ||
(it == list.children.last && it.children.length == 2 && !eob_found)) &&
(list.children.last != it || list.children.size == 1 ||
list.children[0..-2].any? {|cit| !cit.children.first || cit.children.first.type != :p || cit.children.first.options[:transparent]})
it.children.first.children.first.value << "\n" if it.children.size > 1 && it.children[1].type != :blank
it.children.first.options[:transparent] = true
end
if it.children.last.type == :blank
last = it.children.pop
else
last = nil
end
end
@tree.children << last if !last.nil? && !eob_found
true
end
define_parser(:list, LIST_START)
DEFINITION_LIST_START = /^(#{OPT_SPACE}:)([\t| ].*?\n)/
# Parse the ordered or unordered list at the current location.
def parse_definition_list
children = @tree.children
if !children.last || (children.length == 1 && children.last.type != :p ) ||
(children.length >= 2 && children[-1].type != :p && (children[-1].type != :blank || children[-1].value != "\n" || children[-2].type != :p))
return false
end
first_as_para = false
deflist = new_block_el(:dl)
para = @tree.children.pop
if para.type == :blank
para = @tree.children.pop
first_as_para = true
end
deflist.options[:location] = para.options[:location] # take location from preceding para which is the first definition term
para.children.first.value.split(/\n/).each do |term|
el = Element.new(:dt, nil, nil, :location => @src.current_line_number)
term.sub!(self.class::LIST_ITEM_IAL) do
parse_attribute_list($1, el.options[:ial] ||= {})
''
end
el.options[:raw_text] = term
el.children << Element.new(:raw_text, term)
deflist.children << el
end
deflist.options[:ial] = para.options[:ial]
item = nil
content_re, lazy_re, indent_re = nil
def_start_re = DEFINITION_LIST_START
last_is_blank = false
while !@src.eos?
start_line_number = @src.current_line_number
if @src.scan(def_start_re)
item = Element.new(:dd, nil, nil, :location => start_line_number)
item.options[:first_as_para] = first_as_para
item.value, indentation, content_re, lazy_re, indent_re = parse_first_list_line(@src[1].length, @src[2])
deflist.children << item
item.value.sub!(self.class::LIST_ITEM_IAL) do |match|
parse_attribute_list($1, item.options[:ial] ||= {})
''
end
def_start_re = /^( {0,#{[3, indentation - 1].min}}:)([\t| ].*?\n)/
first_as_para = false
last_is_blank = false
elsif @src.check(EOB_MARKER)
break
elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
result.sub!(/^(\t+)/) { " "*($1 ? 4*$1.length : 0) }
result.sub!(indent_re, '')
item.value << result
first_as_para = false
last_is_blank = false
elsif result = @src.scan(BLANK_LINE)
first_as_para = true
item.value << result
last_is_blank = true
else
break
end
end
last = nil
deflist.children.each do |it|
next if it.type == :dt
parse_blocks(it, it.value)
it.value = nil
next if it.children.size == 0
if it.children.last.type == :blank
last = it.children.pop
else
last = nil
end
if it.children.first && it.children.first.type == :p && !it.options.delete(:first_as_para)
it.children.first.children.first.value << "\n" if it.children.size > 1
it.children.first.options[:transparent] = true
end
end
if @tree.children.length >= 1 && @tree.children.last.type == :dl
@tree.children[-1].children.concat(deflist.children)
elsif @tree.children.length >= 2 && @tree.children[-1].type == :blank && @tree.children[-2].type == :dl
@tree.children.pop
@tree.children[-1].children.concat(deflist.children)
else
@tree.children << deflist
end
@tree.children << last if !last.nil?
true
end
define_parser(:definition_list, DEFINITION_LIST_START)
end
end
end
|