kramdown-1.10.0/0000755000175000017500000000000012672246617013264 5ustar uwabamiuwabamikramdown-1.10.0/setup.rb0000644000175000017500000010650412672246616014756 0ustar uwabamiuwabami# # setup.rb # # Copyright (c) 2000-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # unless Enumerable.method_defined?(:map) # Ruby 1.4.6 module Enumerable alias map collect end end unless File.respond_to?(:read) # Ruby 1.6 def File.read(fname) open(fname) {|f| return f.read } end end unless Errno.const_defined?(:ENOTEMPTY) # Windows? module Errno class ENOTEMPTY # We do not raise this exception, implementation is not needed. end end end def File.binread(fname) open(fname, 'rb') {|f| return f.read } end # for corrupted Windows' stat(2) def File.dir?(path) File.directory?((path[-1,1] == '/') ? path : path + '/') end class ConfigTable include Enumerable def initialize(rbconfig) @rbconfig = rbconfig @items = [] @table = {} # options @install_prefix = nil @config_opt = nil @verbose = true @no_harm = false end attr_accessor :install_prefix attr_accessor :config_opt attr_writer :verbose def verbose? @verbose end attr_writer :no_harm def no_harm? @no_harm end def [](key) lookup(key).resolve(self) end def []=(key, val) lookup(key).set val end def names @items.map {|i| i.name } end def each(&block) @items.each(&block) end def key?(name) @table.key?(name) end def lookup(name) @table[name] or setup_rb_error "no such config item: #{name}" end def add(item) @items.push item @table[item.name] = item end def remove(name) item = lookup(name) @items.delete_if {|i| i.name == name } @table.delete_if {|name, i| i.name == name } item end def load_script(path, inst = nil) if File.file?(path) MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path end end def savefile '.config' end def load_savefile begin File.foreach(savefile()) do |line| k, v = *line.split(/=/, 2) self[k] = v.strip end rescue Errno::ENOENT setup_rb_error $!.message + "\n#{File.basename($0)} config first" end end def save @items.each {|i| i.value } File.open(savefile(), 'w') {|f| @items.each do |i| f.printf "%s=%s\n", i.name, i.value if i.value? and i.value end } end def load_standard_entries standard_entries(@rbconfig).each do |ent| add ent end end def standard_entries(rbconfig) c = rbconfig rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) if c['rubylibdir'] # V > 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = c['rubylibdir'] librubyverarch = c['archdir'] siteruby = c['sitedir'] siterubyver = c['sitelibdir'] siterubyverarch = c['sitearchdir'] elsif newpath_p # 1.4.4 <= V <= 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = c['sitedir'] siterubyver = "$siteruby/#{version}" siterubyverarch = "$siterubyver/#{c['arch']}" else # V < 1.4.4 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" siterubyver = siteruby siterubyverarch = "$siterubyver/#{c['arch']}" end parameterize = lambda {|path| path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') } if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } makeprog = arg.sub(/'/, '').split(/=/, 2)[1] else makeprog = 'make' end [ ExecItem.new('installdirs', 'std/site/home', 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ {|val, table| case val when 'std' table['rbdir'] = '$librubyver' table['sodir'] = '$librubyverarch' when 'site' table['rbdir'] = '$siterubyver' table['sodir'] = '$siterubyverarch' when 'home' setup_rb_error '$HOME was not set' unless ENV['HOME'] table['prefix'] = ENV['HOME'] table['rbdir'] = '$libdir/ruby' table['sodir'] = '$libdir/ruby' end }, PathItem.new('prefix', 'path', c['prefix'], 'path prefix of target environment'), PathItem.new('bindir', 'path', parameterize.call(c['bindir']), 'the directory for commands'), PathItem.new('libdir', 'path', parameterize.call(c['libdir']), 'the directory for libraries'), PathItem.new('datadir', 'path', parameterize.call(c['datadir']), 'the directory for shared data'), PathItem.new('mandir', 'path', parameterize.call(c['mandir']), 'the directory for man pages'), PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), 'the directory for system configuration files'), PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), 'the directory for local state data'), PathItem.new('libruby', 'path', libruby, 'the directory for ruby libraries'), PathItem.new('librubyver', 'path', librubyver, 'the directory for standard ruby libraries'), PathItem.new('librubyverarch', 'path', librubyverarch, 'the directory for standard ruby extensions'), PathItem.new('siteruby', 'path', siteruby, 'the directory for version-independent aux ruby libraries'), PathItem.new('siterubyver', 'path', siterubyver, 'the directory for aux ruby libraries'), PathItem.new('siterubyverarch', 'path', siterubyverarch, 'the directory for aux ruby binaries'), PathItem.new('rbdir', 'path', '$siterubyver', 'the directory for ruby scripts'), PathItem.new('sodir', 'path', '$siterubyverarch', 'the directory for ruby extentions'), PathItem.new('rubypath', 'path', rubypath, 'the path to set to #! line'), ProgramItem.new('rubyprog', 'name', rubypath, 'the ruby program using for installation'), ProgramItem.new('makeprog', 'name', makeprog, 'the make program to compile ruby extentions'), SelectItem.new('shebang', 'all/ruby/never', 'ruby', 'shebang line (#!) editing mode'), BoolItem.new('without-ext', 'yes/no', 'no', 'does not compile/install ruby extentions') ] end private :standard_entries def load_multipackage_entries multipackage_entries().each do |ent| add ent end end def multipackage_entries [ PackageSelectionItem.new('with', 'name,name...', '', 'ALL', 'package names that you want to install'), PackageSelectionItem.new('without', 'name,name...', '', 'NONE', 'package names that you do not want to install') ] end private :multipackage_entries ALIASES = { 'std-ruby' => 'librubyver', 'stdruby' => 'librubyver', 'rubylibdir' => 'librubyver', 'archdir' => 'librubyverarch', 'site-ruby-common' => 'siteruby', # For backward compatibility 'site-ruby' => 'siterubyver', # For backward compatibility 'bin-dir' => 'bindir', 'bin-dir' => 'bindir', 'rb-dir' => 'rbdir', 'so-dir' => 'sodir', 'data-dir' => 'datadir', 'ruby-path' => 'rubypath', 'ruby-prog' => 'rubyprog', 'ruby' => 'rubyprog', 'make-prog' => 'makeprog', 'make' => 'makeprog' } def fixup ALIASES.each do |ali, name| @table[ali] = @table[name] end @items.freeze @table.freeze @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ end def parse_opt(opt) m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" m.to_a[1,2] end def dllext @rbconfig['DLEXT'] end def value_config?(name) lookup(name).value? end class Item def initialize(name, template, default, desc) @name = name.freeze @template = template @value = default @default = default @description = desc end attr_reader :name attr_reader :description attr_accessor :default alias help_default default def help_opt "--#{@name}=#{@template}" end def value? true end def value @value end def resolve(table) @value.gsub(%r<\$([^/]+)>) { table[$1] } end def set(val) @value = check(val) end private def check(val) setup_rb_error "config: --#{name} requires argument" unless val val end end class BoolItem < Item def config_type 'bool' end def help_opt "--#{@name}" end private def check(val) return 'yes' unless val case val when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' else setup_rb_error "config: --#{@name} accepts only yes/no for argument" end end end class PathItem < Item def config_type 'path' end private def check(path) setup_rb_error "config: --#{@name} requires argument" unless path path[0,1] == '$' ? path : File.expand_path(path) end end class ProgramItem < Item def config_type 'program' end end class SelectItem < Item def initialize(name, selection, default, desc) super @ok = selection.split('/') end def config_type 'select' end private def check(val) unless @ok.include?(val.strip) setup_rb_error "config: use --#{@name}=#{@template} (#{val})" end val.strip end end class ExecItem < Item def initialize(name, selection, desc, &block) super name, selection, nil, desc @ok = selection.split('/') @action = block end def config_type 'exec' end def value? false end def resolve(table) setup_rb_error "$#{name()} wrongly used as option value" end undef set def evaluate(val, table) v = val.strip.downcase unless @ok.include?(v) setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" end @action.call v, table end end class PackageSelectionItem < Item def initialize(name, template, default, help_default, desc) super name, template, default, desc @help_default = help_default end attr_reader :help_default def config_type 'package' end private def check(val) unless File.dir?("packages/#{val}") setup_rb_error "config: no such package: #{val}" end val end end class MetaConfigEnvironment def initialize(config, installer) @config = config @installer = installer end def config_names @config.names end def config?(name) @config.key?(name) end def bool_config?(name) @config.lookup(name).config_type == 'bool' end def path_config?(name) @config.lookup(name).config_type == 'path' end def value_config?(name) @config.lookup(name).config_type != 'exec' end def add_config(item) @config.add item end def add_bool_config(name, default, desc) @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) end def add_path_config(name, default, desc) @config.add PathItem.new(name, 'path', default, desc) end def set_config_default(name, default) @config.lookup(name).default = default end def remove_config(name) @config.remove(name) end # For only multipackage def packages raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer @installer.packages end # For only multipackage def declare_packages(list) raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer @installer.packages = list end end end # class ConfigTable # This module requires: #verbose?, #no_harm? module FileOperations def mkdir_p(dirname, prefix = nil) dirname = prefix + File.expand_path(dirname) if prefix $stderr.puts "mkdir -p #{dirname}" if verbose? return if no_harm? # Does not check '/', it's too abnormal. dirs = File.expand_path(dirname).split(%r<(?=/)>) if /\A[a-z]:\z/i =~ dirs[0] disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless File.dir?(path) end end def rm_f(path) $stderr.puts "rm -f #{path}" if verbose? return if no_harm? force_remove_file path end def rm_rf(path) $stderr.puts "rm -rf #{path}" if verbose? return if no_harm? remove_tree path end def remove_tree(path) if File.symlink?(path) remove_file path elsif File.dir?(path) remove_tree0 path else force_remove_file path end end def remove_tree0(path) Dir.foreach(path) do |ent| next if ent == '.' next if ent == '..' entpath = "#{path}/#{ent}" if File.symlink?(entpath) remove_file entpath elsif File.dir?(entpath) remove_tree0 entpath else force_remove_file entpath end end begin Dir.rmdir path rescue Errno::ENOTEMPTY # directory may not be empty end end def move_file(src, dest) force_remove_file dest begin File.rename src, dest rescue File.open(dest, 'wb') {|f| f.write File.binread(src) } File.chmod File.stat(src).mode, dest File.unlink src end end def force_remove_file(path) begin remove_file path rescue end end def remove_file(path) File.chmod 0777, path File.unlink path end def install(from, dest, mode, prefix = nil) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix ? prefix + File.expand_path(dest) : dest realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) str = File.binread(from) if diff?(str, realdest) verbose_off { rm_f realdest if File.exist?(realdest) } File.open(realdest, 'wb') {|f| f.write str } File.chmod mode, realdest File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| if prefix f.puts realdest.sub(prefix, '') else f.puts realdest end } end end def diff?(new_content, path) return true unless File.exist?(path) new_content != File.binread(path) end def command(*args) $stderr.puts args.join(' ') if verbose? system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed" end def ruby(*args) command config('rubyprog'), *args end def make(task = nil) command(*[config('makeprog'), task].compact) end def extdir?(dir) File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") end def files_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.file?("#{dir}/#{ent}") } } end DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) def directories_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT } end end # This module requires: #srcdir_root, #objdir_root, #relpath module HookScriptAPI def get_config(key) @config[key] end alias config get_config # obsolete: use metaconfig to change configuration def set_config(key, val) @config[key] = val end # # srcdir/objdir (works only in the package directory) # def curr_srcdir "#{srcdir_root()}/#{relpath()}" end def curr_objdir "#{objdir_root()}/#{relpath()}" end def srcfile(path) "#{curr_srcdir()}/#{path}" end def srcexist?(path) File.exist?(srcfile(path)) end def srcdirectory?(path) File.dir?(srcfile(path)) end def srcfile?(path) File.file?(srcfile(path)) end def srcentries(path = '.') Dir.open("#{curr_srcdir()}/#{path}") {|d| return d.to_a - %w(. ..) } end def srcfiles(path = '.') srcentries(path).select {|fname| File.file?(File.join(curr_srcdir(), path, fname)) } end def srcdirectories(path = '.') srcentries(path).select {|fname| File.dir?(File.join(curr_srcdir(), path, fname)) } end end class ToplevelInstaller Version = '3.4.1' Copyright = 'Copyright (c) 2000-2005 Minero Aoki' TASKS = [ [ 'all', 'do config, setup, then install' ], [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles ruby extentions and others' ], [ 'install', 'installs files' ], [ 'test', 'run all tests in test/' ], [ 'clean', "does `make clean' for each extention" ], [ 'distclean',"does `make distclean' for each extention" ] ] def ToplevelInstaller.invoke config = ConfigTable.new(load_rbconfig()) config.load_standard_entries config.load_multipackage_entries if multipackage? config.fixup klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) klass.new(File.dirname($0), config).invoke end def ToplevelInstaller.multipackage? File.dir?(File.dirname($0) + '/packages') end def ToplevelInstaller.load_rbconfig if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } ARGV.delete(arg) load File.expand_path(arg.split(/=/, 2)[1]) $".push 'rbconfig.rb' else require 'rbconfig' end ::RbConfig::CONFIG end def initialize(ardir_root, config) @ardir = File.expand_path(ardir_root) @config = config # cache @valid_task_re = nil end def config(key) @config[key] end def inspect "#<#{self.class} #{__id__()}>" end def invoke run_metaconfigs case task = parsearg_global() when nil, 'all' parsearg_config init_installers exec_config exec_setup exec_install else case task when 'config', 'test' ; when 'clean', 'distclean' @config.load_savefile if File.exist?(@config.savefile) else @config.load_savefile end __send__ "parsearg_#{task}" init_installers __send__ "exec_#{task}" end end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig" end def init_installers @installer = Installer.new(@config, @ardir, File.expand_path('.')) end # # Hook Script API bases # def srcdir_root @ardir end def objdir_root '.' end def relpath '.' end # # Option Parsing # def parsearg_global while arg = ARGV.shift case arg when /\A\w+\z/ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) return arg when '-q', '--quiet' @config.verbose = false when '--verbose' @config.verbose = true when '--help' print_usage $stdout exit 0 when '--version' puts "#{File.basename($0)} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else setup_rb_error "unknown global option '#{arg}'" end end nil end def valid_task?(t) valid_task_re() =~ t end def valid_task_re @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ end def parsearg_no_options unless ARGV.empty? task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" end end alias parsearg_show parsearg_no_options alias parsearg_setup parsearg_no_options alias parsearg_test parsearg_no_options alias parsearg_clean parsearg_no_options alias parsearg_distclean parsearg_no_options def parsearg_config evalopt = [] set = [] @config.config_opt = [] while i = ARGV.shift if /\A--?\z/ =~ i @config.config_opt = ARGV.dup break end name, value = *@config.parse_opt(i) if @config.value_config?(name) @config[name] = value else evalopt.push [name, value] end set.push name end evalopt.each do |name, value| @config.lookup(name).evaluate value, @config end # Check if configuration is valid set.each do |n| @config[n] if @config.value_config?(n) end end def parsearg_install @config.no_harm = false @config.install_prefix = '' while a = ARGV.shift case a when '--no-harm' @config.no_harm = true when /\A--prefix=/ path = a.split(/=/, 2)[1] path = File.expand_path(path) unless path[0,1] == '/' @config.install_prefix = path else setup_rb_error "install: unknown option #{a}" end end end def print_usage(out) out.puts 'Typical Installation Procedure:' out.puts " $ ruby #{File.basename $0} config" out.puts " $ ruby #{File.basename $0} setup" out.puts " # ruby #{File.basename $0} install (may require root privilege)" out.puts out.puts 'Detailed Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-24s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, ' --help', 'print this message' out.printf fmt, ' --version', 'print version and quit' out.printf fmt, ' --copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf fmt, name, desc end fmt = " %-24s %s [%s]\n" out.puts out.puts 'Options for CONFIG or ALL:' @config.each do |item| out.printf fmt, item.help_opt, item.description, item.help_default end out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" out.puts out.puts 'Options for INSTALL:' out.printf fmt, '--no-harm', 'only display what to do if given', 'off' out.printf fmt, '--prefix=path', 'install path prefix', '' out.puts end # # Task Handlers # def exec_config @installer.exec_config @config.save # must be final end def exec_setup @installer.exec_setup end def exec_install @installer.exec_install end def exec_test @installer.exec_test end def exec_show @config.each do |i| printf "%-20s %s\n", i.name, i.value if i.value? end end def exec_clean @installer.exec_clean end def exec_distclean @installer.exec_distclean end end # class ToplevelInstaller class ToplevelInstallerMulti < ToplevelInstaller include FileOperations def initialize(ardir_root, config) super @packages = directories_of("#{@ardir}/packages") raise 'no package exists' if @packages.empty? @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig", self @packages.each do |name| @config.load_script "#{@ardir}/packages/#{name}/metaconfig" end end attr_reader :packages def packages=(list) raise 'package list is empty' if list.empty? list.each do |name| raise "directory packages/#{name} does not exist"\ unless File.dir?("#{@ardir}/packages/#{name}") end @packages = list end def init_installers @installers = {} @packages.each do |pack| @installers[pack] = Installer.new(@config, "#{@ardir}/packages/#{pack}", "packages/#{pack}") end with = extract_selection(config('with')) without = extract_selection(config('without')) @selected = @installers.keys.select {|name| (with.empty? or with.include?(name)) \ and not without.include?(name) } end def extract_selection(list) a = list.split(/,/) a.each do |name| setup_rb_error "no such package: #{name}" unless @installers.key?(name) end a end def print_usage(f) super f.puts 'Inluded packages:' f.puts ' ' + @packages.sort.join(' ') f.puts end # # Task Handlers # def exec_config run_hook 'pre-config' each_selected_installers {|inst| inst.exec_config } run_hook 'post-config' @config.save # must be final end def exec_setup run_hook 'pre-setup' each_selected_installers {|inst| inst.exec_setup } run_hook 'post-setup' end def exec_install run_hook 'pre-install' each_selected_installers {|inst| inst.exec_install } run_hook 'post-install' end def exec_test run_hook 'pre-test' each_selected_installers {|inst| inst.exec_test } run_hook 'post-test' end def exec_clean rm_f @config.savefile run_hook 'pre-clean' each_selected_installers {|inst| inst.exec_clean } run_hook 'post-clean' end def exec_distclean rm_f @config.savefile run_hook 'pre-distclean' each_selected_installers {|inst| inst.exec_distclean } run_hook 'post-distclean' end # # lib # def each_selected_installers Dir.mkdir 'packages' unless File.dir?('packages') @selected.each do |pack| $stderr.puts "Processing the package `#{pack}' ..." if verbose? Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") Dir.chdir "packages/#{pack}" yield @installers[pack] Dir.chdir '../..' end end def run_hook(id) @root_installer.run_hook id end # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end end # class ToplevelInstallerMulti class Installer FILETYPES = %w( bin lib ext data conf man ) include FileOperations include HookScriptAPI def initialize(config, srcroot, objroot) @config = config @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{self.class} #{File.basename(@srcdir)}>" end def noop(rel) end # # Hook Script API base methods # def srcdir_root @srcdir end def objdir_root @objdir end def relpath @currdir end # # Config Access # # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end def verbose_off begin save, @config.verbose = @config.verbose?, false yield ensure @config.verbose = save end end # # TASK config # def exec_config exec_task_traverse 'config' end alias config_dir_bin noop alias config_dir_lib noop def config_dir_ext(rel) extconf if extdir?(curr_srcdir()) end alias config_dir_data noop alias config_dir_conf noop alias config_dir_man noop def extconf ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt end # # TASK setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin(rel) files_of(curr_srcdir()).each do |fname| update_shebang_line "#{curr_srcdir()}/#{fname}" end end alias setup_dir_lib noop def setup_dir_ext(rel) make if extdir?(curr_srcdir()) end alias setup_dir_data noop alias setup_dir_conf noop alias setup_dir_man noop def update_shebang_line(path) return if no_harm? return if config('shebang') == 'never' old = Shebang.load(path) if old $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 new = new_shebang(old) return if new.to_s == old.to_s else return unless config('shebang') == 'all' new = Shebang.new(config('rubypath')) end $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? open_atomic_writer(path) {|output| File.open(path, 'rb') {|f| f.gets if old # discard output.puts new.to_s output.print f.read } } end def new_shebang(old) if /\Aruby/ =~ File.basename(old.cmd) Shebang.new(config('rubypath'), old.args) elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' Shebang.new(config('rubypath'), old.args[1..-1]) else return old unless config('shebang') == 'all' Shebang.new(config('rubypath')) end end def open_atomic_writer(path, &block) tmpfile = File.basename(path) + '.tmp' begin File.open(tmpfile, 'wb', &block) File.rename tmpfile, File.basename(path) ensure File.unlink tmpfile if File.exist?(tmpfile) end end class Shebang def Shebang.load(path) line = nil File.open(path) {|f| line = f.gets } return nil unless /\A#!/ =~ line parse(line) end def Shebang.parse(line) cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') new(cmd, args) end def initialize(cmd, args = []) @cmd = cmd @args = args end attr_reader :cmd attr_reader :args def to_s "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") end end # # TASK install # def exec_install rm_f 'InstalledFiles' exec_task_traverse 'install' end def install_dir_bin(rel) install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 end def install_dir_lib(rel) install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 end def install_dir_ext(rel) return unless extdir?(curr_srcdir()) install_files rubyextentions('.'), "#{config('sodir')}/#{File.dirname(rel)}", 0555 end def install_dir_data(rel) install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 end def install_dir_conf(rel) # FIXME: should not remove current config files # (rename previous file to .old/.org) install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 end def install_dir_man(rel) install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 end def install_files(list, dest, mode) mkdir_p dest, @config.install_prefix list.each do |fname| install fname, dest, mode, @config.install_prefix end end def libfiles glob_reject(%w(*.y *.output), targetfiles()) end def rubyextentions(dir) ents = glob_select("*.#{@config.dllext}", targetfiles()) if ents.empty? setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" end ents end def targetfiles mapdir(existfiles() - hookfiles()) end def mapdir(ents) ents.map {|ent| if File.exist?(ent) then ent # objdir else "#{curr_srcdir()}/#{ent}" # srcdir end } end # picked up many entries from cvs-1.11.1/src/ignore.c JUNK_FILES = %w( core RCSLOG tags TAGS .make.state .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$ *.org *.in .* ) def existfiles glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) end def hookfiles %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| %w( config setup install clean ).map {|t| sprintf(fmt, t) } }.flatten end def glob_select(pat, ents) re = globs2re([pat]) ents.select {|ent| re =~ ent } end def glob_reject(pats, ents) re = globs2re(pats) ents.reject {|ent| re =~ ent } end GLOB2REGEX = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' } def globs2re(pats) /\A(?:#{ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') })\z/ end # # TASK test # TESTDIR = 'test' def exec_test unless File.directory?('test') $stderr.puts 'no test in this package' if verbose? return end $stderr.puts 'Running tests...' if verbose? begin require 'test/unit' rescue LoadError setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' end runner = Test::Unit::AutoRunner.new(true) runner.to_run << TESTDIR runner.run end # # TASK clean # def exec_clean exec_task_traverse 'clean' rm_f @config.savefile rm_f 'InstalledFiles' end alias clean_dir_bin noop alias clean_dir_lib noop alias clean_dir_data noop alias clean_dir_conf noop alias clean_dir_man noop def clean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'clean' if File.file?('Makefile') end # # TASK distclean # def exec_distclean exec_task_traverse 'distclean' rm_f @config.savefile rm_f 'InstalledFiles' end alias distclean_dir_bin noop alias distclean_dir_lib noop def distclean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'distclean' if File.file?('Makefile') end alias distclean_dir_data noop alias distclean_dir_conf noop alias distclean_dir_man noop # # Traversing # def exec_task_traverse(task) run_hook "pre-#{task}" FILETYPES.each do |type| if type == 'ext' and config('without-ext') == 'yes' $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, "#{task}_dir_#{type}" end run_hook "post-#{task}" end def traverse(task, rel, mid) dive_into(rel) { run_hook "pre-#{task}" __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') directories_of(curr_srcdir()).each do |d| traverse task, "#{rel}/#{d}", mid end run_hook "post-#{task}" } end def dive_into(rel) return unless File.dir?("#{@srcdir}/#{rel}") dir = File.basename(rel) Dir.mkdir dir unless File.dir?(dir) prevdir = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir prevdir $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end def run_hook(id) path = [ "#{curr_srcdir()}/#{id}", "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } return unless path begin instance_eval File.read(path), path, 1 rescue raise if $DEBUG setup_rb_error "hook #{path} failed:\n" + $!.message end end end # class Installer class SetupError < StandardError; end def setup_rb_error(msg) raise SetupError, msg end if $0 == __FILE__ begin ToplevelInstaller.invoke rescue SetupError raise if $DEBUG $stderr.puts $!.message $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." exit 1 end end kramdown-1.10.0/benchmark/0000755000175000017500000000000012672246616015215 5ustar uwabamiuwabamikramdown-1.10.0/benchmark/generate_data.rb0000644000175000017500000000772212672246616020335 0ustar uwabamiuwabamirequire 'benchmark' require 'optparse' require 'fileutils' require 'kramdown' options = {:others => false, :average => 1} OptionParser.new do |opts| opts.on("-a AVG", "--average AVG", Integer, "Average times over the specified number of runs") {|v| options[:average] = v } opts.on("-o", "--[no-]others", "Generate data for other parsers") {|v| options[:others] = v} opts.on("-g", "--[no-]graph", "Generate graph") {|v| options[:graph] = v} opts.on("-k VERSION", "--kramdown VERSION", String, "Add benchmark data for kramdown version VERSION") {|v| options[:kramdown] = v} end.parse! THISRUBY = (self.class.const_defined?(:RUBY_DESCRIPTION) ? RUBY_DESCRIPTION.scan(/^.*?(?=\s*\()/).first.sub(/\s/, '-') : "ruby-#{RUBY_VERSION}") + '-' + RUBY_PATCHLEVEL.to_s Dir.chdir(File.dirname(__FILE__)) BMDATA = File.read('mdbasics.text') MULTIPLIER = (0..5).map {|i| 2**i} if options[:others] require 'maruku' require 'maruku/version' begin require 'rdiscount' rescue LoadError end #require 'bluefeather' module MaRuKu::Errors def tell_user(s) end end bmdata = {} labels = [] MULTIPLIER.each do |i| $stderr.puts "Generating benchmark data for other parsers, multiplier #{i}" mddata = BMDATA*i labels = [] bmdata[i] = Benchmark::bmbm do |x| labels << "Maruku #{MaRuKu::Version}" x.report { Maruku.new(mddata, :on_error => :ignore).to_html } if self.class.const_defined?(:BlueFeather) labels << "BlueFeather #{BlueFeather::VERSION}" x.report { BlueFeather.parse(mddata) } end if self.class.const_defined?(:RDiscount) labels << "RDiscount #{RDiscount::VERSION}" x.report { RDiscount.new(mddata).to_html } end end end File.open("static-#{THISRUBY}.dat", 'w+') do |f| f.puts "# " + labels.join(" || ") format_str = "%5d" + " %10.5f"*bmdata[MULTIPLIER.first].size bmdata.sort.each do |m,v| f.puts format_str % [m, *v.map {|tms| tms.real}] end end end if options[:kramdown] kramdown = "kramdown-#{THISRUBY}.dat" data = if File.exist?(kramdown) lines = File.readlines(kramdown).map {|l| l.chomp} lines.first << " || " lines else ["# ", *MULTIPLIER.map {|m| "%3d" % m}] end data.first << "#{options[:kramdown]}".rjust(10) times = [] options[:average].times do MULTIPLIER.each_with_index do |m, i| $stderr.puts "Generating benchmark data for kramdown version #{options[:kramdown]}, multiplier #{m}" mddata = BMDATA*m begin (times[i] ||= []) << Benchmark::bmbm {|x| x.report { Kramdown::Document.new(mddata).to_html } }.first.real rescue $stderr.puts $!.message (times[i] ||= []) << 0 end end end times.each_with_index {|t,i| data[i+1] << "%14.5f" % (t.inject(0) {|sum,v| sum+v}/3.0)} File.open(kramdown, 'w+') do |f| data.each {|l| f.puts l} end end if options[:graph] Dir['kramdown-*.dat'].each do |kramdown_name| theruby = kramdown_name.sub(/^kramdown-/, '').sub(/\.dat$/, '') graph_name = "graph-#{theruby}.png" static_name = "static-#{theruby}.dat" kramdown_names = File.readlines(kramdown_name).first.chomp[1..-1].split(/\s*\|\|\s*/) static_names = (File.exist?(static_name) ? File.readlines(static_name).first.chomp[1..-1].split(/\s*\|\|\s*/) : []) File.open("gnuplot.dat", "w+") do |f| f.puts </dev/null if [ -z $MASTER_AS -o $KD_VERSION != master ]; then VNUM=${KD_VERSION} else VNUM=$MASTER_AS fi ruby -I${TMPDIR}/kramdown/lib ../generate_data.rb -k ${VNUM} -a ${AVERAGE} >/dev/null done if [ $OTHERS = "true" ]; then ruby -rubygems -I${TMPDIR}/kramdown/lib ../generate_data.rb -o >/dev/null fi done cd ${TMPDIR} rvm default ruby generate_data.rb -g kramdown-1.10.0/benchmark/timing.sh0000755000175000017500000000041112672246616017037 0ustar uwabamiuwabami#!/bin/bash source ~/.bashrc for VERSION in `rvm list strings | sort`; do rvm $VERSION echo $(ruby -v) ruby -Ilib bin/kramdown < benchmark/mdsyntax.text 2>/dev/null >/dev/null time ruby -Ilib bin/kramdown < benchmark/mdsyntax.text 2>/dev/null >/dev/null done kramdown-1.10.0/benchmark/testing.sh0000755000175000017500000000032012672246616017224 0ustar uwabamiuwabami#!/bin/bash source ~/.profile COMMAND="$@" if [[ -z "$COMMAND" ]]; then COMMAND="rake test"; fi for VERSION in `rvm list strings | sort`; do rvm $VERSION echo $(ruby -v) RUBYOPT=-rubygems $COMMAND done kramdown-1.10.0/benchmark/mdsyntax.text0000644000175000017500000006544412672246616020007 0ustar uwabamiuwabamiMarkdown: Syntax ================ * [Overview](#overview) * [Philosophy](#philosophy) * [Inline HTML](#html) * [Automatic Escaping for Special Characters](#autoescape) * [Block Elements](#block) * [Paragraphs and Line Breaks](#p) * [Headers](#header) * [Blockquotes](#blockquote) * [Lists](#list) * [Code Blocks](#precode) * [Horizontal Rules](#hr) * [Span Elements](#span) * [Links](#link) * [Emphasis](#em) * [Code](#code) * [Images](#img) * [Miscellaneous](#misc) * [Backslash Escapes](#backslash) * [Automatic Links](#autolink) **Note:** This document is itself written using Markdown; you can [see the source for it by adding '.text' to the URL][src]. [src]: /projects/markdown/syntax.text * * *

Overview

Philosophy

Markdown is intended to be as easy-to-read and easy-to-write as is feasible. Readability, however, is emphasized above all else. A Markdown-formatted document should be publishable as-is, as plain text, without looking like it's been marked up with tags or formatting instructions. While Markdown's syntax has been influenced by several existing text-to-HTML filters -- including [Setext] [1], [atx] [2], [Textile] [3], [reStructuredText] [4], [Grutatext] [5], and [EtText] [6] -- the single biggest source of inspiration for Markdown's syntax is the format of plain text email. [1]: http://docutils.sourceforge.net/mirror/setext.html [2]: http://www.aaronsw.com/2002/atx/ [3]: http://textism.com/tools/textile/ [4]: http://docutils.sourceforge.net/rst.html [5]: http://www.triptico.com/software/grutatxt.html [6]: http://ettext.taint.org/doc/ To this end, Markdown's syntax is comprised entirely of punctuation characters, which punctuation characters have been carefully chosen so as to look like what they mean. E.g., asterisks around a word actually look like \*emphasis\*. Markdown lists look like, well, lists. Even blockquotes look like quoted passages of text, assuming you've ever used email.

Inline HTML

Markdown's syntax is intended for one purpose: to be used as a format for *writing* for the web. Markdown is not a replacement for HTML, or even close to it. Its syntax is very small, corresponding only to a very small subset of HTML tags. The idea is *not* to create a syntax that makes it easier to insert HTML tags. In my opinion, HTML tags are already easy to insert. The idea for Markdown is to make it easy to read, write, and edit prose. HTML is a *publishing* format; Markdown is a *writing* format. Thus, Markdown's formatting syntax only addresses issues that can be conveyed in plain text. For any markup that is not covered by Markdown's syntax, you simply use HTML itself. There's no need to preface it or delimit it to indicate that you're switching from Markdown to HTML; you just use the tags. The only restrictions are that block-level HTML elements -- e.g. `
`, ``, `
`, `

`, etc. -- must be separated from surrounding content by blank lines, and the start and end tags of the block should not be indented with tabs or spaces. Markdown is smart enough not to add extra (unwanted) `

` tags around HTML block-level tags. For example, to add an HTML table to a Markdown article: This is a regular paragraph.

Foo
This is another regular paragraph. Note that Markdown formatting syntax is not processed within block-level HTML tags. E.g., you can't use Markdown-style `*emphasis*` inside an HTML block. Span-level HTML tags -- e.g. ``, ``, or `` -- can be used anywhere in a Markdown paragraph, list item, or header. If you want, you can even use HTML tags instead of Markdown formatting; e.g. if you'd prefer to use HTML `` or `` tags instead of Markdown's link or image syntax, go right ahead. Unlike block-level HTML tags, Markdown syntax *is* processed within span-level tags.

Automatic Escaping for Special Characters

In HTML, there are two characters that demand special treatment: `<` and `&`. Left angle brackets are used to start tags; ampersands are used to denote HTML entities. If you want to use them as literal characters, you must escape them as entities, e.g. `<`, and `&`. Ampersands in particular are bedeviling for web writers. If you want to write about 'AT&T', you need to write '`AT&T`'. You even need to escape ampersands within URLs. Thus, if you want to link to: http://images.google.com/images?num=30&q=larry+bird you need to encode the URL as: http://images.google.com/images?num=30&q=larry+bird in your anchor tag `href` attribute. Needless to say, this is easy to forget, and is probably the single most common source of HTML validation errors in otherwise well-marked-up web sites. Markdown allows you to use these characters naturally, taking care of all the necessary escaping for you. If you use an ampersand as part of an HTML entity, it remains unchanged; otherwise it will be translated into `&`. So, if you want to include a copyright symbol in your article, you can write: © and Markdown will leave it alone. But if you write: AT&T Markdown will translate it to: AT&T Similarly, because Markdown supports [inline HTML](#html), if you use angle brackets as delimiters for HTML tags, Markdown will treat them as such. But if you write: 4 < 5 Markdown will translate it to: 4 < 5 However, inside Markdown code spans and blocks, angle brackets and ampersands are *always* encoded automatically. This makes it easy to use Markdown to write about HTML code. (As opposed to raw HTML, which is a terrible format for writing about HTML syntax, because every single `<` and `&` in your example code needs to be escaped.) * * *

Block Elements

Paragraphs and Line Breaks

A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. (A blank line is any line that looks like a blank line -- a line containing nothing but spaces or tabs is considered blank.) Normal paragraphs should not be intended with spaces or tabs. The implication of the "one or more consecutive lines of text" rule is that Markdown supports "hard-wrapped" text paragraphs. This differs significantly from most other text-to-HTML formatters (including Movable Type's "Convert Line Breaks" option) which translate every line break character in a paragraph into a `
` tag. When you *do* want to insert a `
` break tag using Markdown, you end a line with two or more spaces, then type return. Yes, this takes a tad more effort to create a `
`, but a simplistic "every line break is a `
`" rule wouldn't work for Markdown. Markdown's email-style [blockquoting][bq] and multi-paragraph [list items][l] work best -- and look better -- when you format them with hard breaks. [bq]: #blockquote [l]: #list Markdown supports two styles of headers, [Setext] [1] and [atx] [2]. Setext-style headers are "underlined" using equal signs (for first-level headers) and dashes (for second-level headers). For example: This is an H1 ============= This is an H2 ------------- Any number of underlining `=`'s or `-`'s will work. Atx-style headers use 1-6 hash characters at the start of the line, corresponding to header levels 1-6. For example: # This is an H1 ## This is an H2 ###### This is an H6 Optionally, you may "close" atx-style headers. This is purely cosmetic -- you can use this if you think it looks better. The closing hashes don't even need to match the number of hashes used to open the header. (The number of opening hashes determines the header level.) : # This is an H1 # ## This is an H2 ## ### This is an H3 ######

Blockquotes

Markdown uses email-style `>` characters for blockquoting. If you're familiar with quoting passages of text in an email message, then you know how to create a blockquote in Markdown. It looks best if you hard wrap the text and put a `>` before every line: > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse > id sem consectetuer libero luctus adipiscing. Markdown allows you to be lazy and only put the `>` before the first line of a hard-wrapped paragraph: > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by adding additional levels of `>`: > This is the first level of quoting. > > > This is nested blockquote. > > Back to the first level. Blockquotes can contain other Markdown elements, including headers, lists, and code blocks: > ## This is a header. > > 1. This is the first list item. > 2. This is the second list item. > > Here's some example code: > > return shell_exec("echo $input | $markdown_script"); Any decent text editor should make email-style quoting easy. For example, with BBEdit, you can make a selection and choose Increase Quote Level from the Text menu.

Lists

Markdown supports ordered (numbered) and unordered (bulleted) lists. Unordered lists use asterisks, pluses, and hyphens -- interchangably -- as list markers: * Red * Green * Blue is equivalent to: + Red + Green + Blue and: - Red - Green - Blue Ordered lists use numbers followed by periods: 1. Bird 2. McHale 3. Parish It's important to note that the actual numbers you use to mark the list have no effect on the HTML output Markdown produces. The HTML Markdown produces from the above list is:
  1. Bird
  2. McHale
  3. Parish
If you instead wrote the list in Markdown like this: 1. Bird 1. McHale 1. Parish or even: 3. Bird 1. McHale 8. Parish you'd get the exact same HTML output. The point is, if you want to, you can use ordinal numbers in your ordered Markdown lists, so that the numbers in your source match the numbers in your published HTML. But if you want to be lazy, you don't have to. If you do use lazy list numbering, however, you should still start the list with the number 1. At some point in the future, Markdown may support starting ordered lists at an arbitrary number. List markers typically start at the left margin, but may be indented by up to three spaces. List markers must be followed by one or more spaces or a tab. To make lists look nice, you can wrap items with hanging indents: * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. But if you want to be lazy, you don't have to: * Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. * Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. If list items are separated by blank lines, Markdown will wrap the items in `

` tags in the HTML output. For example, this input: * Bird * Magic will turn into:

  • Bird
  • Magic
But this: * Bird * Magic will turn into:
  • Bird

  • Magic

List items may consist of multiple paragraphs. Each subsequent paragraph in a list item must be intended by either 4 spaces or one tab: 1. This is a list item with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. Donec sit amet nisl. Aliquam semper ipsum sit amet velit. 2. Suspendisse id sem consectetuer libero luctus adipiscing. It looks nice if you indent every line of the subsequent paragraphs, but here again, Markdown will allow you to be lazy: * This is a list item with two paragraphs. This is the second paragraph in the list item. You're only required to indent the first line. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. * Another item in the same list. To put a blockquote within a list item, the blockquote's `>` delimiters need to be indented: * A list item with a blockquote: > This is a blockquote > inside a list item. To put a code block within a list item, the code block needs to be indented *twice* -- 8 spaces or two tabs: * A list item with a code block: It's worth noting that it's possible to trigger an ordered list by accident, by writing something like this: 1986. What a great season. In other words, a *number-period-space* sequence at the beginning of a line. To avoid this, you can backslash-escape the period: 1986\. What a great season.

Code Blocks

Pre-formatted code blocks are used for writing about programming or markup source code. Rather than forming normal paragraphs, the lines of a code block are interpreted literally. Markdown wraps a code block in both `
` and `` tags.

To produce a code block in Markdown, simply indent every line of the
block by at least 4 spaces or 1 tab. For example, given this input:

    This is a normal paragraph:

        This is a code block.

Markdown will generate:

    

This is a normal paragraph:

This is a code block.
    
One level of indentation -- 4 spaces or 1 tab -- is removed from each line of the code block. For example, this: Here is an example of AppleScript: tell application "Foo" beep end tell will turn into:

Here is an example of AppleScript:

tell application "Foo"
        beep
    end tell
    
A code block continues until it reaches a line that is not indented (or the end of the article). Within a code block, ampersands (`&`) and angle brackets (`<` and `>`) are automatically converted into HTML entities. This makes it very easy to include example HTML source code using Markdown -- just paste it and indent it, and Markdown will handle the hassle of encoding the ampersands and angle brackets. For example, this: will turn into:
<div class="footer">
        &copy; 2004 Foo Corporation
    </div>
    
Regular Markdown syntax is not processed within code blocks. E.g., asterisks are just literal asterisks within a code block. This means it's also easy to use Markdown to write about Markdown's own syntax.

Horizontal Rules

You can produce a horizontal rule tag (`
`) by placing three or more hyphens, asterisks, or underscores on a line by themselves. If you wish, you may use spaces between the hyphens or asterisks. Each of the following lines will produce a horizontal rule: * * * *** ***** - - - --------------------------------------- _ _ _ * * *

Span Elements

Markdown supports two style of links: *inline* and *reference*. In both styles, the link text is delimited by [square brackets]. To create an inline link, use a set of regular parentheses immediately after the link text's closing square bracket. Inside the parentheses, put the URL where you want the link to point, along with an *optional* title for the link, surrounded in quotes. For example: This is [an example](http://example.com/ "Title") inline link. [This link](http://example.net/) has no title attribute. Will produce:

This is an example inline link.

This link has no title attribute.

If you're referring to a local resource on the same server, you can use relative paths: See my [About](/about/) page for details. Reference-style links use a second set of square brackets, inside which you place a label of your choosing to identify the link: This is [an example][id] reference-style link. You can optionally use a space to separate the sets of brackets: This is [an example] [id] reference-style link. Then, anywhere in the document, you define your link label like this, on a line by itself: [id]: http://example.com/ "Optional Title Here" That is: * Square brackets containing the link identifier (optionally indented from the left margin using up to three spaces); * followed by a colon; * followed by one or more spaces (or tabs); * followed by the URL for the link; * optionally followed by a title attribute for the link, enclosed in double or single quotes. The link URL may, optionally, be surrounded by angle brackets: [id]: "Optional Title Here" You can put the title attribute on the next line and use extra spaces or tabs for padding, which tends to look better with longer URLs: [id]: http://example.com/longish/path/to/resource/here "Optional Title Here" Link definitions are only used for creating links during Markdown processing, and are stripped from your document in the HTML output. Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links: [link text][a] [link text][A] are equivalent. The *implicit link name* shortcut allows you to omit the name of the link, in which case the link text itself is used as the name. Just use an empty set of square brackets -- e.g., to link the word "Google" to the google.com web site, you could simply write: [Google][] And then define the link: [Google]: http://google.com/ Because link names may contain spaces, this shortcut even works for multiple words in the link text: Visit [Daring Fireball][] for more information. And then define the link: [Daring Fireball]: http://daringfireball.net/ Link definitions can be placed anywhere in your Markdown document. I tend to put them immediately after each paragraph in which they're used, but if you want, you can put them all at the end of your document, sort of like footnotes. Here's an example of reference links in action: I get 10 times more traffic from [Google] [1] than from [Yahoo] [2] or [MSN] [3]. [1]: http://google.com/ "Google" [2]: http://search.yahoo.com/ "Yahoo Search" [3]: http://search.msn.com/ "MSN Search" Using the implicit link name shortcut, you could instead write: I get 10 times more traffic from [Google][] than from [Yahoo][] or [MSN][]. [google]: http://google.com/ "Google" [yahoo]: http://search.yahoo.com/ "Yahoo Search" [msn]: http://search.msn.com/ "MSN Search" Both of the above examples will produce the following HTML output:

I get 10 times more traffic from Google than from Yahoo or MSN.

For comparison, here is the same paragraph written using Markdown's inline link style: I get 10 times more traffic from [Google](http://google.com/ "Google") than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or [MSN](http://search.msn.com/ "MSN Search"). The point of reference-style links is not that they're easier to write. The point is that with reference-style links, your document source is vastly more readable. Compare the above examples: using reference-style links, the paragraph itself is only 81 characters long; with inline-style links, it's 176 characters; and as raw HTML, it's 234 characters. In the raw HTML, there's more markup than there is text. With Markdown's reference-style links, a source document much more closely resembles the final output, as rendered in a browser. By allowing you to move the markup-related metadata out of the paragraph, you can add links without interrupting the narrative flow of your prose.

Emphasis

Markdown treats asterisks (`*`) and underscores (`_`) as indicators of emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML `` tag; double `*`'s or `_`'s will be wrapped with an HTML `` tag. E.g., this input: *single asterisks* _single underscores_ **double asterisks** __double underscores__ will produce: single asterisks single underscores double asterisks double underscores You can use whichever style you prefer; the lone restriction is that the same character must be used to open and close an emphasis span. Emphasis can be used in the middle of a word: un*fucking*believable But if you surround an `*` or `_` with spaces, it'll be treated as a literal asterisk or underscore. To produce a literal asterisk or underscore at a position where it would otherwise be used as an emphasis delimiter, you can backslash escape it: \*this text is surrounded by literal asterisks\*

Code

To indicate a span of code, wrap it with backtick quotes (`` ` ``). Unlike a pre-formatted code block, a code span indicates code within a normal paragraph. For example: Use the `printf()` function. will produce:

Use the printf() function.

To include a literal backtick character within a code span, you can use multiple backticks as the opening and closing delimiters: ``There is a literal backtick (`) here.`` which will produce this:

There is a literal backtick (`) here.

The backtick delimiters surrounding a code span may include spaces -- one after the opening, one before the closing. This allows you to place literal backtick characters at the beginning or end of a code span: A single backtick in a code span: `` ` `` A backtick-delimited string in a code span: `` `foo` `` will produce:

A single backtick in a code span: `

A backtick-delimited string in a code span: `foo`

With a code span, ampersands and angle brackets are encoded as HTML entities automatically, which makes it easy to include example HTML tags. Markdown will turn this: Please don't use any `` tags. into:

Please don't use any <blink> tags.

You can write this: `—` is the decimal-encoded equivalent of `—`. to produce:

&#8212; is the decimal-encoded equivalent of &mdash;.

Images

Admittedly, it's fairly difficult to devise a "natural" syntax for placing images into a plain text document format. Markdown uses an image syntax that is intended to resemble the syntax for links, allowing for two styles: *inline* and *reference*. Inline image syntax looks like this: ![Alt text](/path/to/img.jpg) ![Alt text](/path/to/img.jpg "Optional title") That is: * An exclamation mark: `!`; * followed by a set of square brackets, containing the `alt` attribute text for the image; * followed by a set of parentheses, containing the URL or path to the image, and an optional `title` attribute enclosed in double or single quotes. Reference-style image syntax looks like this: ![Alt text][id] Where "id" is the name of a defined image reference. Image references are defined using syntax identical to link references: [id]: url/to/image "Optional title attribute" As of this writing, Markdown has no syntax for specifying the dimensions of an image; if this is important to you, you can simply use regular HTML `` tags. * * *

Miscellaneous

Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this: Markdown will turn this into: http://example.com/ Automatic links for email addresses work similarly, except that Markdown will also perform a bit of randomized decimal and hex entity-encoding to help obscure your address from address-harvesting spambots. For example, Markdown will turn this: into something like this: address@exa mple.com which will render in a browser as a clickable link to "address@example.com". (This sort of entity-encoding trick will indeed fool many, if not most, address-harvesting bots, but it definitely won't fool all of them. It's better than nothing, but an address published in this way will probably eventually start receiving spam.)

Backslash Escapes

Markdown allows you to use backslash escapes to generate literal characters which would otherwise have special meaning in Markdown's formatting syntax. For example, if you wanted to surround a word with literal asterisks (instead of an HTML `` tag), you can backslashes before the asterisks, like this: \*literal asterisks\* Markdown provides backslash escapes for the following characters: \ backslash ` backtick * asterisk _ underscore {} curly braces [] square brackets () parentheses # hash mark + plus sign - minus sign (hyphen) . dot ! exclamation mark kramdown-1.10.0/benchmark/mdbasics.text0000644000175000017500000001760012672246616017714 0ustar uwabamiuwabamiMarkdown: Basics ================ Getting the Gist of Markdown's Formatting Syntax ------------------------------------------------ This page offers a brief overview of what it's like to use Markdown. The [syntax page] [s] provides complete, detailed documentation for every feature, but Markdown should be very easy to pick up simply by looking at a few examples of it in action. The examples on this page are written in a before/after style, showing example syntax and the HTML output produced by Markdown. It's also helpful to simply try Markdown out; the [Dingus] [d] is a web application that allows you type your own Markdown-formatted text and translate it to XHTML. **Note:** This document is itself written using Markdown; you can [see the source for it by adding '.text' to the URL] [src]. [s]: /projects/markdown/syntax "Markdown Syntax" [d]: /projects/markdown/dingus "Markdown Dingus" [src]: /projects/markdown/basics.text ## Paragraphs, Headers, Blockquotes ## A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. (A blank line is any line that looks like a blank line -- a line containing nothing spaces or tabs is considered blank.) Normal paragraphs should not be intended with spaces or tabs. Markdown offers two styles of headers: *Setext* and *atx*. Setext-style headers for `

` and `

` are created by "underlining" with equal signs (`=`) and hyphens (`-`), respectively. To create an atx-style header, you put 1-6 hash marks (`#`) at the beginning of the line -- the number of hashes equals the resulting HTML header level. Blockquotes are indicated using email-style '`>`' angle brackets. Markdown: A First Level Header ==================== A Second Level Header --------------------- Now is the time for all good men to come to the aid of their country. This is just a regular paragraph. The quick brown fox jumped over the lazy dog's back. ### Header 3 > This is a blockquote. > > This is the second paragraph in the blockquote. > > ## This is an H2 in a blockquote Output:

A First Level Header

A Second Level Header

Now is the time for all good men to come to the aid of their country. This is just a regular paragraph.

The quick brown fox jumped over the lazy dog's back.

Header 3

This is a blockquote.

This is the second paragraph in the blockquote.

This is an H2 in a blockquote

### Phrase Emphasis ### Markdown uses asterisks and underscores to indicate spans of emphasis. Markdown: Some of these words *are emphasized*. Some of these words _are emphasized also_. Use two asterisks for **strong emphasis**. Or, if you prefer, __use two underscores instead__. Output:

Some of these words are emphasized. Some of these words are emphasized also.

Use two asterisks for strong emphasis. Or, if you prefer, use two underscores instead.

## Lists ## Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`, `+`, and `-`) as list markers. These three markers are interchangable; this: * Candy. * Gum. * Booze. this: + Candy. + Gum. + Booze. and this: - Candy. - Gum. - Booze. all produce the same output:
  • Candy.
  • Gum.
  • Booze.
Ordered (numbered) lists use regular numbers, followed by periods, as list markers: 1. Red 2. Green 3. Blue Output:
  1. Red
  2. Green
  3. Blue
If you put blank lines between items, you'll get `

` tags for the list item text. You can create multi-paragraph list items by indenting the paragraphs by 4 spaces or 1 tab: * A list item. With multiple paragraphs. * Another item in the list. Output:

  • A list item.

    With multiple paragraphs.

  • Another item in the list.

### Links ### Markdown supports two styles for creating links: *inline* and *reference*. With both styles, you use square brackets to delimit the text you want to turn into a link. Inline-style links use parentheses immediately after the link text. For example: This is an [example link](http://example.com/). Output:

This is an example link.

Optionally, you may include a title attribute in the parentheses: This is an [example link](http://example.com/ "With a Title"). Output:

This is an example link.

Reference-style links allow you to refer to your links by names, which you define elsewhere in your document: I get 10 times more traffic from [Google][1] than from [Yahoo][2] or [MSN][3]. [1]: http://google.com/ "Google" [2]: http://search.yahoo.com/ "Yahoo Search" [3]: http://search.msn.com/ "MSN Search" Output:

I get 10 times more traffic from Google than from Yahoo or MSN.

The title attribute is optional. Link names may contain letters, numbers and spaces, but are *not* case sensitive: I start my morning with a cup of coffee and [The New York Times][NY Times]. [ny times]: http://www.nytimes.com/ Output:

I start my morning with a cup of coffee and The New York Times.

### Images ### Image syntax is very much like link syntax. Inline (titles are optional): ![alt text](/path/to/img.jpg "Title") Reference-style: ![alt text][id] [id]: /path/to/img.jpg "Title" Both of the above examples produce the same output: alt text ### Code ### In a regular paragraph, you can create code span by wrapping text in backtick quotes. Any ampersands (`&`) and angle brackets (`<` or `>`) will automatically be translated into HTML entities. This makes it easy to use Markdown to write about HTML example code: I strongly recommend against using any `` tags. I wish SmartyPants used named entities like `—` instead of decimal-encoded entites like `—`. Output:

I strongly recommend against using any <blink> tags.

I wish SmartyPants used named entities like &mdash; instead of decimal-encoded entites like &#8212;.

To specify an entire block of pre-formatted code, indent every line of the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`, and `>` characters will be escaped automatically. Markdown: If you want your page to validate under XHTML 1.0 Strict, you've got to put paragraph tags in your blockquotes:

For example.

Output:

If you want your page to validate under XHTML 1.0 Strict, you've got to put paragraph tags in your blockquotes:

<blockquote>
        <p>For example.</p>
    </blockquote>
    
kramdown-1.10.0/benchmark/benchmark.rb0000644000175000017500000000260212672246616017474 0ustar uwabamiuwabamirequire 'benchmark' require 'stringio' require 'kramdown' require 'bluecloth' require 'maruku' require 'maruku/version' require 'rdiscount' require 'bluefeather' require 'redcarpet' module MaRuKu::Errors def tell_user(s) end end RUNS=20 FILES=['mdsyntax.text', 'mdbasics.text'] puts "Running tests on #{Time.now.strftime("%Y-%m-%d")} under #{RUBY_DESCRIPTION}" FILES.each do |file| data = File.read(File.join(File.dirname(__FILE__), file)) puts puts "Test using file #{file} and #{RUNS} runs" results = Benchmark.bmbm do |b| b.report("kramdown #{Kramdown::VERSION}") { RUNS.times { Kramdown::Document.new(data).to_html } } b.report("Maruku #{MaRuKu::Version}") { RUNS.times { Maruku.new(data, :on_error => :ignore).to_html } } b.report("BlueFeather #{BlueFeather::VERSION}") { RUNS.times { BlueFeather.parse(data) } } b.report("BlueCloth #{BlueCloth::VERSION}") { RUNS.times { BlueCloth.new(data).to_html } } b.report("RDiscount #{RDiscount::VERSION}") { RUNS.times { RDiscount.new(data).to_html } } b.report("redcarpet #{Redcarpet::VERSION}") { RUNS.times { Redcarpet::Markdown.new(Redcarpet::Render::HTML).render(data) } } end puts puts "Real time of X divided by real time of kramdown" kd = results.shift.real %w[Maruku BlueFeather BlueCloth RDiscount redcarpet].each do |name| puts name.ljust(19) << (results.shift.real/kd).round(4).to_s end end kramdown-1.10.0/test/0000755000175000017500000000000012672246616014242 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases_gfm/0000755000175000017500000000000012672246616017071 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases_gfm/atx_header.html0000644000175000017500000000004312672246616022060 0ustar uwabamiuwabami

header

#no header

kramdown-1.10.0/test/testcases_gfm/hard_line_breaks_off.text0000644000175000017500000000011112672246616024076 0ustar uwabamiuwabamiThis is just a normal paragraph. Containing a manual line break above. kramdown-1.10.0/test/testcases_gfm/strikethrough.text0000644000175000017500000000067312672246616022707 0ustar uwabamiuwabami~~This is a test~~ ~~~This is another test~~~ ~~This is yet another test~~~ ~~ This is a test of it NOT working ~~ ~~ This is a **multiline** test ~~ This is an ~~_inline_ **strikethrough**~~ test This is an \~~escaped~~ strikethrough. This is a ~~strikethrough with a ~ in the middle~~ I ~~don't even~~~ have an extra tilde. This should ~~not be struck. This ~~is a complex *strike* through *test ~~with nesting~~ involved* here~~. kramdown-1.10.0/test/testcases_gfm/hard_line_breaks_off.html0000644000175000017500000000012412672246616024062 0ustar uwabamiuwabami

This is just a normal paragraph.
Containing a manual line break above.

kramdown-1.10.0/test/testcases_gfm/hard_line_breaks.text0000644000175000017500000000002012672246616023243 0ustar uwabamiuwabamione _two_ three kramdown-1.10.0/test/testcases_gfm/backticks_syntax.text0000644000175000017500000000023312672246616023341 0ustar uwabamiuwabami``` Three backticks ``` ```` Four backticks ```` ``` Unbalanced bottom heavy `````` ````ruby language no space ```` ```` ruby language with space ```` kramdown-1.10.0/test/testcases_gfm/hard_line_breaks.html0000644000175000017500000000005212672246616023230 0ustar uwabamiuwabami

one
two
three

kramdown-1.10.0/test/testcases_gfm/two_para_hard_line_breaks.text0000644000175000017500000000012012672246616025140 0ustar uwabamiuwabamiThis is just a normal paragraph. Containing a line break. Another paragraph. kramdown-1.10.0/test/testcases_gfm/backticks_disable_highlighting.html0000644000175000017500000000014012672246616026120 0ustar uwabamiuwabami
Kramdown::Document.new(text, :input => 'GFM')
kramdown-1.10.0/test/testcases_gfm/backticks_disable_highlighting.options0000644000175000017500000000002712672246616026653 0ustar uwabamiuwabami:enable_coderay: false kramdown-1.10.0/test/testcases_gfm/backticks_syntax.html0000644000175000017500000000100012672246616023312 0ustar uwabamiuwabami
Three backticks
Four backticks
Unbalanced bottom heavy
1language no space
1language with space
kramdown-1.10.0/test/testcases_gfm/strikethrough.html.190000644000175000017500000000120612672246616023110 0ustar uwabamiuwabami

This is a test

~This is another test~

This is yet another test~

~~ This is a test of it NOT working ~~

~~
This
is
a
multiline
test
~~

This is an inline strikethrough test

This is an ~~escaped~~ strikethrough.

This is a strikethrough with a ~ in the middle

I don’t even~ have an extra tilde.

This should ~~not be struck.

This is a complex strike through *test ~~with nesting involved* here~~.

kramdown-1.10.0/test/testcases_gfm/hard_line_breaks_off.options0000644000175000017500000000002212672246616024606 0ustar uwabamiuwabami:hard_wrap: false kramdown-1.10.0/test/testcases_gfm/strikethrough.html0000644000175000017500000000121212672246616022655 0ustar uwabamiuwabami

This is a test

~This is another test~

This is yet another test~

~~ This is a test of it NOT working ~~

~~
This
is
a
multiline
test
~~

This is an inline strikethrough test

This is an ~~escaped~~ strikethrough.

This is a strikethrough with a ~ in the middle

I don’t even~ have an extra tilde.

This should ~~not be struck.

This is a complex strike through *test ~~with nesting involved* here~~.

kramdown-1.10.0/test/testcases_gfm/two_para_hard_line_breaks.html0000644000175000017500000000014412672246616025126 0ustar uwabamiuwabami

This is just a normal paragraph.
Containing a line break.

Another paragraph.

kramdown-1.10.0/test/testcases_gfm/backticks_disable_highlighting.text0000644000175000017500000000007212672246616026144 0ustar uwabamiuwabami```ruby Kramdown::Document.new(text, :input => 'GFM') ``` kramdown-1.10.0/test/testcases_gfm/atx_header.text0000644000175000017500000000002512672246616022100 0ustar uwabamiuwabami# header #no header kramdown-1.10.0/test/test_location.rb0000644000175000017500000001532112672246616017440 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'minitest/autorun' require 'kramdown' Encoding.default_external = 'utf-8' if RUBY_VERSION >= '1.9' describe 'location' do # checks that +element+'s :location option corresponds to the location stored # in the element.attr['class'] def check_element_for_location(element) if (match = /^line-(\d+)/.match(element.attr['class'] || '')) expected_line = match[1].to_i element.options[:location].must_equal(expected_line) end element.children.each do |child| check_element_for_location(child) end end # Test cases consist of a kramdown string that uses IALs to specify the expected # line numbers for a given element. test_cases = { 'autolink' => %(testing autolinks\n\n{:.line-3}), 'blockquote' => %( > block quote1 > > * {:.line-3} list item in block quote > * {:.line-4} list item in block quote > {:.line-3} {:.line-1} > block quote2 {:.line-8} ), 'codeblock' => %(\na para\n\n~~~~\ntest code 1\n~~~~\n{:.line-3}\n\n test code 2\n{:.line-8}\n), 'codespan' => %(a para\n\nanother para ``{:.line-3} with code\n), 'emphasis' => %( para *span*{:.line-1} {:.line-1} ## header *span*{:.line-4} {:.line-4} Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum *short span on single line*{:.line-11} dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non *long span over multiple lines - proident, sunt in culpa qui officia deserunt mollit anim id est laborum.*{:.line-13} Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo `code span`{:.line-18} Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo {:.line-7} ), 'header' => %( # header1 {:.line-1} ## header2 {:.line-4} ## header3 {:.line-7} header4 ======= {:.line-10} ^ header5 ------- {:.line-16} ), 'horizontal_rule' => %(\na para\n\n----\n{:.line-3}\n), 'html_entity' => "a para\n\nanother para with &{:.line-3} html entity.\n", 'link' => %( a para This is [a link](http://rubyforge.org){:.line-3} to a page. Here comes a ![smiley](../images/smiley.png){:.line-5} ), 'list' => %( * {:.line-1} list item * {:.line-2} list item * {:.line-3} list item {:.line-1} {:.line-7} 1. {:.line-7} list item 2. {:.line-8} list item 3. {:.line-9} list item {:.line-12} definition term 1 : {:.line-13} definition definition 1 definition term 2 : {:.line-15} definition definition 2 ), 'math_block' => %(\na para\n\n$$5+5$$\n{:.line-3}\n), 'math_inline' => %(\na para\n\nanother para with inline math $$5+5$${:.line-3}\n), 'paragraph' => %( para1 {:.line-1} para2 {:.line-4} Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse {:.line-7} {:.line-14} para with leading IAL ), 'table' => %( a para |first|second|third| |-----|------|-----| |a |b |c | {:.line-3} ), 'typographic_symbol' => %( a para another para ---{:.line-3} another para ...{:.line-5} ), 'gh issue 129' => %( `|` {:.line-1} ), 'gh issue 131' => %( * {:.line-1} test line 2 * {:.line-3} second * {:.line-4} third * {:.line-5} * {:.line-5} one * {:.line-6} two ), 'gh issue 158' => %( ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ðŸ˜ {:.line-1} - {:.line-4} T {:.line-4} # T {:.line-7} ), 'gh issue 243 - HTML raw elements' => %(
  • Test
), } test_cases.each do |name, test_string| it "Handles #{ name }" do doc = Kramdown::Document.new(test_string.gsub(/^ /, '').strip) check_element_for_location(doc.root) end end it 'adds location info to duplicate abbreviation definition warnings' do test_string = %(This snippet contains a duplicate abbreviation definition *[duplicate]: The first definition *[duplicate]: The second definition ) doc = Kramdown::Document.new(test_string.strip) doc.warnings.must_equal ["Duplicate abbreviation ID 'duplicate' on line 4 - overwriting"] end it 'handles abbreviations' do str = "This *is* ABC and\n**and** ABC second\nanother ABC\nas ABC as\nABC at the end.\n\n*[ABC]: ABC" doc = Kramdown::Document.new(str) doc.root.children.first.children.select {|e| e.type == :abbreviation}.each_with_index do |e, i| assert_equal(i + 1, e.options[:location]) end end it 'handles line breaks' do str = "First \nsecond\\\\\nthird \n" doc = Kramdown::Document.new(str) doc.root.children.first.children.select {|e| e.type == :br}.each_with_index do |e, i| assert_equal(i + 1, e.options[:location]) end end it 'handles smart quotes' do str = "This is 'first'\nand 'second' and\n'third'" doc = Kramdown::Document.new(str) doc.root.children.first.children.select {|e| e.type == :smart_quote}.each_with_index do |e, i| assert_equal(((i + 1) /2.0).ceil, e.options[:location]) end end it 'handles hard wrapped paragraphs with the GFM parser' do str = "A*b*C\nA*b*C\nA*b*C" doc = Kramdown::Document.new(str, :input => 'GFM', :hard_wrap => true) para = doc.root.children.first 1.upto(3) do |line| 0.upto(line == 3 ? 2 : 3) do |element| assert_equal(line, para.children[4*(line - 1) + element].options[:location]) end end end end kramdown-1.10.0/test/run_tests.rb0000644000175000017500000000252612672246616016622 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # $:.unshift File.dirname(__FILE__) + '/../lib' require 'kramdown' require 'test/unit/assertions' require 'yaml' include Test::Unit::Assertions arg = ARGV[0] || File.join(File.dirname(__FILE__), 'testcases') arg = if File.directory?(arg) File.join(arg, '**/*.text') else arg + '.text' end width = ((size = %x{stty size 2>/dev/null}).length > 0 ? size.split.last.to_i : 72) rescue 72 width -= 8 fwidth = 0 Dir[arg].each {|f| fwidth = [fwidth, f.length + 10].max }.each do |file| print(('Testing ' + file + ' ').ljust([fwidth, width].min)) $stdout.flush html_file = file.sub('.text', '.html') opts_file = file.sub('.text', '.options') opts_file = File.join(File.dirname(file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} doc = Kramdown::Document.new(File.read(file), options) begin assert_equal(File.read(html_file), doc.to_html) puts 'PASSED' rescue Exception => e puts ' FAILED' puts $!.message if $VERBOSE puts $!.backtrace if $DEBUG end puts "Warnings:\n" + doc.warnings.join("\n") if !doc.warnings.empty? && $VERBOSE end kramdown-1.10.0/test/test_string_scanner_kramdown.rb0000644000175000017500000000145112672246616022550 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'minitest/autorun' require 'kramdown/utils/string_scanner' describe Kramdown::Utils::StringScanner do [ ["...........X............", [/X/], 1], ["1\n2\n3\n4\n5\n6X", [/X/], 6], ["1\n2\n3\n4\n5\n6X\n7\n8X", [/X/,/X/], 8], [(".\n" * 1000) + 'X', [/X/], 1001] ].each_with_index do |test_data, i| test_string, scan_regexes, expect = test_data it "computes the correct current_line_number for example ##{i+1}" do str_sc = Kramdown::Utils::StringScanner.new(test_string) scan_regexes.each { |scan_re| str_sc.scan_until(scan_re) } str_sc.current_line_number.must_equal expect end end end kramdown-1.10.0/test/testcases/0000755000175000017500000000000012672246616016240 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/encoding.text0000644000175000017500000000120212672246616020727 0ustar uwabamiuwabamiDas ist gewöhnlich *ein* [Über-Problem](http://example.org) mit manchen Sälen und anderen Dinge. Siehe ![Über mich](http://example.org)! > Vielleicht *höre*{:.red} ich nicht richtig? {:.test} * Sollten wir uns das überl*egen*? *Verhöhne* mich nicht! * Ho ho höher! Sind \*wir\* da? Titel sind urschön ================== ## Manche mögens *ärmer* {#hot} öha was nun? Töne : Laute Geräusche : vielleicht noch was ä*hnliches* | hoch | höher | am höchsten | |----------------------------| | über | drüber | müde |

Das ist schön gemacht

kramdown-1.10.0/test/testcases/block/0000755000175000017500000000000012672246616017332 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/02_eob/0000755000175000017500000000000012672246616020400 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/02_eob/beginning.html0000644000175000017500000000000112672246616023215 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/02_eob/middle.text0000644000175000017500000000000612672246616022540 0ustar uwabamiuwabami ^ kramdown-1.10.0/test/testcases/block/02_eob/middle.html0000644000175000017500000000000112672246616022513 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/02_eob/end.html0000644000175000017500000000000112672246616022023 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/02_eob/end.text0000644000175000017500000000000412672246616022046 0ustar uwabamiuwabami ^ kramdown-1.10.0/test/testcases/block/02_eob/beginning.text0000644000175000017500000000000412672246616023240 0ustar uwabamiuwabami^ kramdown-1.10.0/test/testcases/block/03_paragraph/0000755000175000017500000000000012672246616021601 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/03_paragraph/two_para.text0000644000175000017500000000012612672246616024322 0ustar uwabamiuwabamiThis is just a normal paragraph. That goes on to the second line. Another paragraph. kramdown-1.10.0/test/testcases/block/03_paragraph/indented.html0000644000175000017500000000035212672246616024261 0ustar uwabamiuwabami

This is a para.

This is a para.

This is a para.

This is a para.

This is a code block.

And this is another.

A para with mixed indents. and with much indent

kramdown-1.10.0/test/testcases/block/03_paragraph/indented.html.gfm0000644000175000017500000000040212672246616025025 0ustar uwabamiuwabami

This is a para.

This is a para.

This is a para.

This is a para.

This is a code block.

And this is another.

A para
with
mixed
indents.
and with much indent

kramdown-1.10.0/test/testcases/block/03_paragraph/one_para.text0000644000175000017500000000004112672246616024266 0ustar uwabamiuwabamiThis is just a normal paragraph. kramdown-1.10.0/test/testcases/block/03_paragraph/indented.text0000644000175000017500000000027212672246616024302 0ustar uwabamiuwabamiThis is a para. This is a para. This is a para. This is a para. This is a code block. And this is another. A para with mixed indents. and with much indent kramdown-1.10.0/test/testcases/block/03_paragraph/no_newline_at_end.html0000644000175000017500000000012112672246616026130 0ustar uwabamiuwabami

One paragraph over multiple lines.

Second one without newline.

kramdown-1.10.0/test/testcases/block/03_paragraph/no_newline_at_end.text0000644000175000017500000000010412672246616026151 0ustar uwabamiuwabami One paragraph over multiple lines. Second one without newline.kramdown-1.10.0/test/testcases/block/03_paragraph/one_para.html0000644000175000017500000000005012672246616024246 0ustar uwabamiuwabami

This is just a normal paragraph.

kramdown-1.10.0/test/testcases/block/03_paragraph/two_para.html0000644000175000017500000000014412672246616024302 0ustar uwabamiuwabami

This is just a normal paragraph. That goes on to the second line.

Another paragraph.

kramdown-1.10.0/test/testcases/block/11_ial/0000755000175000017500000000000012672246616020400 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/11_ial/simple.html0000644000175000017500000000107312672246616022560 0ustar uwabamiuwabami

Some paragraph.

Some paragraph.

quote

  • list
code block
other code block

A header

Some paragraph here

Some paragraph here

Paragraph

Paragraph

Another header

kramdown-1.10.0/test/testcases/block/11_ial/nested.html0000644000175000017500000000022412672246616022546 0ustar uwabamiuwabami
test

test

para

kramdown-1.10.0/test/testcases/block/11_ial/auto_id_and_ial.options0000644000175000017500000000002012672246616025100 0ustar uwabamiuwabami:auto_ids: true kramdown-1.10.0/test/testcases/block/11_ial/simple.text0000644000175000017500000000074712672246616022607 0ustar uwabamiuwabamiSome paragraph. {:.class .-class id key="val"} Some paragraph. {:.cls1#id.cls2} > quote {: #id} {: .class} * list {: key="val"} code block {: #other} other code block ## A header {:#myid} {:.cls} Some paragraph here {:.cls1} {:.cls2} Some paragraph here Paragraph {:.cls} Paragraph Another header ============== {: .class #other} {:id: #id key="valo"} {:id: #other .myclass other} {:other: key1="val\"" - ig.nored as_is#this key2='val\'' .other-class} {:.invalid} kramdown-1.10.0/test/testcases/block/11_ial/auto_id_and_ial.text0000644000175000017500000000003212672246616024374 0ustar uwabamiuwabami## A header {:#myid .cls} kramdown-1.10.0/test/testcases/block/11_ial/auto_id_and_ial.html0000644000175000017500000000005012672246616024354 0ustar uwabamiuwabami

A header

kramdown-1.10.0/test/testcases/block/11_ial/nested.text0000644000175000017500000000014712672246616022572 0ustar uwabamiuwabami{:.cls}
test
{:#id} {:.cls}
test
{:#id} {:.cls} > para {:#id} kramdown-1.10.0/test/testcases/block/04_header/0000755000175000017500000000000012672246616021065 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/04_header/atx_header.html0000644000175000017500000000114512672246616024060 0ustar uwabamiuwabami

This is a header

This is a header

This is a header

This is a header

This is a header
This is a header

Header

Header

Header

blockquote

header

paragraph

blockquote ### not a header

header #

header

#

#

Header

Header

Header

Header

Header {#9ab}

Header{#noid}

Header ##{#noid}

Last

kramdown-1.10.0/test/testcases/block/04_header/atx_header_no_newline_at_end.text0000644000175000017500000000001012672246616027615 0ustar uwabamiuwabami# headerkramdown-1.10.0/test/testcases/block/04_header/setext_header.html0000644000175000017500000000056212672246616024602 0ustar uwabamiuwabami

test

test2

test

para

   header =

=

This is a para. With two lines. And not a header. =================

Blockquote. Not a Header -

header

header

header

header{#noid}

header

kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_stripping.options0000644000175000017500000000003112672246616027252 0ustar uwabamiuwabami:auto_id_stripping: true kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_prefix.text0000644000175000017500000000002212672246616026021 0ustar uwabamiuwabami# Header 1 # 123 kramdown-1.10.0/test/testcases/block/04_header/header_type_offset.html0000644000175000017500000000020312672246616025605 0ustar uwabamiuwabami

Lorem ipsum

Lorem ipsum

Lorem ipsum

Lorem ipsum

Lorem ipsum

Lorem ipsum

kramdown-1.10.0/test/testcases/block/04_header/setext_header.text0000644000175000017500000000043012672246616024614 0ustar uwabamiuwabamitest - test2 ========= test - para header = = This is a para. With two lines. And not a header. ================= > Blockquote. Not a Header - header {#id} ------------ header {#Id} ====== header {#A-Za-z0-9_:} ------ header{#noid} ----- header ------ kramdown-1.10.0/test/testcases/block/04_header/setext_header_no_newline_at_end.text0000644000175000017500000000001512672246616030342 0ustar uwabamiuwabamiheader ======kramdown-1.10.0/test/testcases/block/04_header/header_type_offset.text0000644000175000017500000000016512672246616025634 0ustar uwabamiuwabami# Lorem ipsum ## Lorem ipsum ### Lorem ipsum ###### Lorem ipsum Lorem ipsum =========== Lorem ipsum ----------- kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_stripping.text0000644000175000017500000000005112672246616026545 0ustar uwabamiuwabami# This is a header kramdown-1.10.0/test/testcases/block/04_header/with_auto_ids.text0000644000175000017500000000031012672246616024627 0ustar uwabamiuwabami# This is a header ## 12. Another one-1-here ### Do ^& it now Hallo ===== Not now ------- # Hallo # 23232 # 33333 ## hallO # Header without ID {: id=""} # Transliterated: Äây-là-ví-dụ kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_stripping.html0000644000175000017500000000010612672246616026526 0ustar uwabamiuwabami

This is a header

kramdown-1.10.0/test/testcases/block/04_header/header_type_offset.latex0000644000175000017500000000025112672246616025761 0ustar uwabamiuwabami\subsection*{Lorem ipsum} \subsubsection*{Lorem ipsum} \paragraph*{Lorem ipsum} \subparagraph*{Lorem ipsum} \subsection*{Lorem ipsum} \subsubsection*{Lorem ipsum} kramdown-1.10.0/test/testcases/block/04_header/atx_header_no_newline_at_end.html0000644000175000017500000000002012672246616027576 0ustar uwabamiuwabami

header

kramdown-1.10.0/test/testcases/block/04_header/header_type_offset.kramdown0000644000175000017500000000015012672246616026464 0ustar uwabamiuwabami## Lorem ipsum ### Lorem ipsum #### Lorem ipsum ###### Lorem ipsum ## Lorem ipsum ### Lorem ipsum kramdown-1.10.0/test/testcases/block/04_header/setext_header_no_newline_at_end.html0000644000175000017500000000002012672246616030316 0ustar uwabamiuwabami

header

kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_prefix.options0000644000175000017500000000005012672246616026531 0ustar uwabamiuwabami:auto_ids: true :auto_id_prefix: hallo_ kramdown-1.10.0/test/testcases/block/04_header/header_type_offset.options0000644000175000017500000000004212672246616026335 0ustar uwabamiuwabami:header_offset: 1 :auto_ids: falsekramdown-1.10.0/test/testcases/block/04_header/with_auto_ids.html0000644000175000017500000000065612672246616024624 0ustar uwabamiuwabami

This is a header

12. Another one-1-here

Do ^& it now

Hallo

Not now

Hallo

23232

33333

hallO

Header without ID

Transliterated: Äây-là-ví-dụ

kramdown-1.10.0/test/testcases/block/04_header/with_auto_id_prefix.html0000644000175000017500000000010712672246616026005 0ustar uwabamiuwabami

Header 1

123

kramdown-1.10.0/test/testcases/block/04_header/with_auto_ids.options0000644000175000017500000000006112672246616025341 0ustar uwabamiuwabami:auto_ids: true :transliterated_header_ids: true kramdown-1.10.0/test/testcases/block/04_header/atx_header.text0000644000175000017500000000066712672246616024110 0ustar uwabamiuwabami# This is a header ## This is a header ### This is a header #### This is a header ##### This is a header ###### This is a header # Header ^ # Header ##Header ##### > blockquote ###### header paragraph > blockquote ### not a header # header \# # header # # ### Header {#id} ### Header ## {#Id} ### Header ## {#id} ### Header {#A-Za-z0-9_:t} ### Header {#9ab} ### Header{#noid} ### Header ##{#noid} ### Last kramdown-1.10.0/test/testcases/block/01_blank_line/0000755000175000017500000000000012672246616021730 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/01_blank_line/spaces.text0000644000175000017500000000002012672246616024104 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/01_blank_line/tabs.text0000644000175000017500000000001612672246616023564 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/01_blank_line/tabs.html0000644000175000017500000000000112672246616023536 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/01_blank_line/spaces.html0000644000175000017500000000000112672246616024063 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/16_toc/0000755000175000017500000000000012672246616020425 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/16_toc/toc_with_footnotes.html0000644000175000017500000000061712672246616025237 0ustar uwabamiuwabami

Header1 level 1

  1. Some footnote content here

kramdown-1.10.0/test/testcases/block/16_toc/toc_levels.options0000644000175000017500000000004212672246616024175 0ustar uwabamiuwabami:toc_levels: 2..3 :auto_ids: true kramdown-1.10.0/test/testcases/block/16_toc/toc_exclude.text0000644000175000017500000000033112672246616023626 0ustar uwabamiuwabami# Contents {:.no_toc} * Here comes the table of content {:toc} # Header level 1 ## Header level 2 ### Header level 3 #### Header level 4 # Other header level 1 ## Other header level 2 ### Other header level 3 kramdown-1.10.0/test/testcases/block/16_toc/toc_exclude.options0000644000175000017500000000002012672246616024330 0ustar uwabamiuwabami:auto_ids: true kramdown-1.10.0/test/testcases/block/16_toc/toc_levels.text0000644000175000017500000000030712672246616023472 0ustar uwabamiuwabami* Here comes the table of content {:toc} # Header level 1 ## Header \\\` level 2 ### Header level 3 #### Header level 4 # Other header level 1 ## Other header level 2 ### Other header level 3 kramdown-1.10.0/test/testcases/block/16_toc/toc_exclude.html0000644000175000017500000000241612672246616023614 0ustar uwabamiuwabami

Contents

Header level 1

Header level 2

Header level 3

Header level 4

Other header level 1

Other header level 2

Other header level 3

kramdown-1.10.0/test/testcases/block/16_toc/no_toc.text0000644000175000017500000000030212672246616022607 0ustar uwabamiuwabami* Here comes the table of content {:toc} # Header level 1 ## Header level 2 ### Header level 3 #### Header level 4 # Other header level 1 ## Other header level 2 ### Other header level 3 kramdown-1.10.0/test/testcases/block/16_toc/no_toc.html0000644000175000017500000000030112672246616022566 0ustar uwabamiuwabami

Header level 1

Header level 2

Header level 3

Header level 4

Other header level 1

Other header level 2

Other header level 3

kramdown-1.10.0/test/testcases/block/16_toc/toc_with_footnotes.options0000644000175000017500000000002012672246616025752 0ustar uwabamiuwabami:auto_ids: true kramdown-1.10.0/test/testcases/block/16_toc/toc_levels.html0000644000175000017500000000147712672246616023463 0ustar uwabamiuwabami

Header level 1

Header \` level 2

Header level 3

Header level 4

Other header level 1

Other header level 2

Other header level 3

kramdown-1.10.0/test/testcases/block/16_toc/toc_with_footnotes.text0000644000175000017500000000014112672246616025247 0ustar uwabamiuwabami* Here comes the table of content {:toc} # Header[^1] level 1 [^1]: Some footnote content here kramdown-1.10.0/test/testcases/block/07_horizontal_rule/0000755000175000017500000000000012672246616023060 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/07_horizontal_rule/sepspaces.text0000644000175000017500000000004512672246616025753 0ustar uwabamiuwabami- - - * * * _ _ _ _ _ kramdown-1.10.0/test/testcases/block/07_horizontal_rule/septabs.text0000644000175000017500000000003312672246616025423 0ustar uwabamiuwabami- - - * * * _ _ _ _ _ kramdown-1.10.0/test/testcases/block/07_horizontal_rule/normal.text0000644000175000017500000000014012672246616025251 0ustar uwabamiuwabami*** * * * - - - d- - --- ___ *** para ----------- text * * * - - - * * * {:.test} kramdown-1.10.0/test/testcases/block/07_horizontal_rule/septabs.html0000644000175000017500000000002512672246616025404 0ustar uwabamiuwabami


kramdown-1.10.0/test/testcases/block/07_horizontal_rule/error.html0000644000175000017500000000025112672246616025075 0ustar uwabamiuwabami

_ * _

— * * *

_ - *

———————————————- test

kramdown-1.10.0/test/testcases/block/07_horizontal_rule/error.text0000644000175000017500000000011512672246616025114 0ustar uwabamiuwabami_ * _ --- * * * _ - * ---------------------------------------------- test kramdown-1.10.0/test/testcases/block/07_horizontal_rule/sepspaces.html0000644000175000017500000000002512672246616025731 0ustar uwabamiuwabami


kramdown-1.10.0/test/testcases/block/07_horizontal_rule/error.html.190000644000175000017500000000015112672246616025324 0ustar uwabamiuwabami

_ * _

— * * *

_ - *

———————————————- test

kramdown-1.10.0/test/testcases/block/07_horizontal_rule/normal.html0000644000175000017500000000022012672246616025230 0ustar uwabamiuwabami


d- -




para

text


- - -

kramdown-1.10.0/test/testcases/block/09_html/0000755000175000017500000000000012672246616020606 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/09_html/invalid_html_2.text0000644000175000017500000000002112672246616024400 0ustar uwabamiuwabamipara
para kramdown-1.10.0/test/testcases/block/09_html/html_and_codeblocks.html0000644000175000017500000000023712672246616025454 0ustar uwabamiuwabami

para

codeblock

test

<p>codeblock</p>

test

kramdown-1.10.0/test/testcases/block/09_html/simple.html0000644000175000017500000000113512672246616022765 0ustar uwabamiuwabami

test

para2

tes

test weiter

para4

foo

bar 

para5

id

test

hallo

hallo

para6

Another para.

doit

Test

Test

Test

kramdown-1.10.0/test/testcases/block/09_html/html_and_codeblocks.options0000644000175000017500000000003012672246616026172 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/parse_as_span.htmlinput0000644000175000017500000000024512672246616025373 0ustar uwabamiuwabami

This text should be parsed as span

This produces `

` an unwanted result.</p>

This text too

some text

kramdown-1.10.0/test/testcases/block/09_html/html_after_block.html0000644000175000017500000000017112672246616024772 0ustar uwabamiuwabami

Para

division

Quote

division
kramdown-1.10.0/test/testcases/block/09_html/invalid_html_1.html0000644000175000017500000000005612672246616024367 0ustar uwabamiuwabami

para

</div>

para

kramdown-1.10.0/test/testcases/block/09_html/parse_as_span.html0000644000175000017500000000024512672246616024313 0ustar uwabamiuwabami

This text should be parsed as span

This produces `

` an unwanted result.</p>

This text too

some text

kramdown-1.10.0/test/testcases/block/09_html/textarea.text0000644000175000017500000000012012672246616023322 0ustar uwabamiuwabamiThis is a kramdown-1.10.0/test/testcases/block/09_html/textarea.html0000644000175000017500000000012712672246616023311 0ustar uwabamiuwabami

This is a

kramdown-1.10.0/test/testcases/block/09_html/html5_attributes.html0000644000175000017500000000047612672246616025002 0ustar uwabamiuwabami

paragraph

paragraph

paragraph

paragraph

paragraph

paragraph

paragraph

kramdown-1.10.0/test/testcases/block/09_html/html_after_block.text0000644000175000017500000000012012672246616025004 0ustar uwabamiuwabamiPara
division
> Quote
division
kramdown-1.10.0/test/testcases/block/09_html/parse_as_raw.html0000644000175000017500000000104612672246616024143 0ustar uwabamiuwabami

baz { |qux| quux }

This is some para.

parsed This too

http://example.com

kramdown-1.10.0/test/testcases/block/09_html/markdown_attr.html0000644000175000017500000000044512672246616024353 0ustar uwabamiuwabami

para

para

para

*para*

para

para

para

*para*

emphasize

para

kramdown-1.10.0/test/testcases/block/09_html/html_and_headers.html0000644000175000017500000000004512672246616024754 0ustar uwabamiuwabami

header

======
kramdown-1.10.0/test/testcases/block/09_html/comment.html0000644000175000017500000000023512672246616023136 0ustar uwabamiuwabami

para1

para2

para

This is

kramdown-1.10.0/test/testcases/block/09_html/not_parsed.html0000644000175000017500000000040112672246616023625 0ustar uwabamiuwabami
This is some text
This is some text

Foo

This is some text

http://example.com

<http://example.com>
kramdown-1.10.0/test/testcases/block/09_html/parse_as_raw.text0000644000175000017500000000076012672246616024165 0ustar uwabamiuwabami

baz { |qux| quux }

This is some para.

*parsed* This too

kramdown-1.10.0/test/testcases/block/09_html/parse_as_raw.htmlinput0000644000175000017500000000104512672246616025222 0ustar uwabamiuwabami

baz { |qux| quux }

This is some para.

parsed This too

http://example.com

kramdown-1.10.0/test/testcases/block/09_html/invalid_html_2.html0000644000175000017500000000004112672246616024362 0ustar uwabamiuwabami

para


para

kramdown-1.10.0/test/testcases/block/09_html/simple.html.190000644000175000017500000000113112672246616023211 0ustar uwabamiuwabami

test

para2

tes

test weiter

para4

foo

bar 

para5

id

test

hallo

hallo

para6

Another para.

doit

Test

Test

Test

kramdown-1.10.0/test/testcases/block/09_html/simple.options0000644000175000017500000000003012672246616023505 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/parse_block_html.text0000644000175000017500000000021112672246616025016 0ustar uwabamiuwabami
test
test
test
code block with
No matching end tag kramdown-1.10.0/test/testcases/block/09_html/html_and_codeblocks.text0000644000175000017500000000012412672246616025467 0ustar uwabamiuwabamipara codeblock
test

codeblock

test
kramdown-1.10.0/test/testcases/block/09_html/simple.text0000644000175000017500000000074412672246616023012 0ustar uwabamiuwabami
test

para2

tes

test weiter

para4
foo
bar 
para5
id
test
hallo
hallo
para6
Another para.
doit Test

Test

Test

kramdown-1.10.0/test/testcases/block/09_html/parse_block_html.options0000644000175000017500000000003012672246616025524 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/parse_as_raw.options0000644000175000017500000000003012672246616024662 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/processing_instruction.text0000644000175000017500000000013112672246616026324 0ustar uwabamiuwabami para para other kramdown-1.10.0/test/testcases/block/09_html/parse_block_html.html0000644000175000017500000000035512672246616025007 0ustar uwabamiuwabami

test

test
test
code block with </div>

No matching end tag

kramdown-1.10.0/test/testcases/block/09_html/html_and_headers.text0000644000175000017500000000004312672246616024772 0ustar uwabamiuwabamiheader ======
======
kramdown-1.10.0/test/testcases/block/09_html/markdown_attr.text0000644000175000017500000000053412672246616024372 0ustar uwabamiuwabami
*para*
*para*
*para*
*para*

*para*

*para*

*para*

*para*

*emphasize*
para
kramdown-1.10.0/test/testcases/block/09_html/processing_instruction.html0000644000175000017500000000015612672246616026313 0ustar uwabamiuwabami

para

para

other

kramdown-1.10.0/test/testcases/block/09_html/html5_attributes.text0000644000175000017500000000045312672246616025015 0ustar uwabamiuwabami

paragraph

paragraph

paragraph

paragraph

paragraph

paragraph

paragraph

kramdown-1.10.0/test/testcases/block/09_html/content_model/0000755000175000017500000000000012672246616023440 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/09_html/content_model/deflists.text0000644000175000017500000000005312672246616026161 0ustar uwabamiuwabami
*text*
para
kramdown-1.10.0/test/testcases/block/09_html/content_model/tables.text0000644000175000017500000000030012672246616025611 0ustar uwabamiuwabami
*Usage* Output
Some *data* # Some more
kramdown-1.10.0/test/testcases/block/09_html/content_model/deflists.html0000644000175000017500000000010312672246616026135 0ustar uwabamiuwabami
text

para

kramdown-1.10.0/test/testcases/block/09_html/content_model/tables.html0000644000175000017500000000027712672246616025606 0ustar uwabamiuwabami
Usage Output
Some data

Some more

kramdown-1.10.0/test/testcases/block/09_html/content_model/deflists.options0000644000175000017500000000003012672246616026663 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/content_model/tables.options0000644000175000017500000000003012672246616026320 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/09_html/not_parsed.text0000644000175000017500000000033112672246616023647 0ustar uwabamiuwabami
This is some text
This is some text

Foo

This is some text

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/0000755000175000017500000000000012672246616023622 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/09_html/html_to_native/table_normal.text0000644000175000017500000000022512672246616027166 0ustar uwabamiuwabami
Usage Other
Some *data*

Some more

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/entity.html0000644000175000017500000000007112672246616026022 0ustar uwabamiuwabami

This is *raw* HTML text containing < entities!

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/typography.html.190000644000175000017500000000006012672246616027142 0ustar uwabamiuwabami

This is … something “to rememberâ€!

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/paragraph.text0000644000175000017500000000011112672246616026466 0ustar uwabamiuwabami

Some text here and end

Some other text here

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/typography.text0000644000175000017500000000007512672246616026740 0ustar uwabamiuwabami

This is … something “to remember”!

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/code.html0000644000175000017500000000040512672246616025421 0ustar uwabamiuwabami

This is a code span with <entities> that should be preserved. This is a simple code span.

Some <

Some very important < thing
Some code<<
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/header.text0000644000175000017500000000020412672246616025754 0ustar uwabamiuwabami

Some headerhere!

hallo

hallo

hallo

hallo
hallo
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/code.text0000644000175000017500000000041312672246616025440 0ustar uwabamiuwabamiThis is a code span with <entities> that should be preserved. This is a simple code span.

Some <

Some very important < thing
Some code<<
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/comment.html0000644000175000017500000000006312672246616026151 0ustar uwabamiuwabami
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/options0000644000175000017500000000002612672246616025236 0ustar uwabamiuwabami:html_to_native: true kramdown-1.10.0/test/testcases/block/09_html/html_to_native/emphasis.text0000644000175000017500000000022112672246616026334 0ustar uwabamiuwabamiThis is sizedhallo. This is strongitalic, yes!. This is not converted, as is this. kramdown-1.10.0/test/testcases/block/09_html/html_to_native/paragraph.html0000644000175000017500000000011012672246616026445 0ustar uwabamiuwabami

Some text here and end

Some other text here

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/typography.html0000644000175000017500000000007412672246616026717 0ustar uwabamiuwabami

This is … something “to remember”!

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/table_simple.html0000644000175000017500000000156312672246616027155 0ustar uwabamiuwabami
Usage Output
Some *data* Some more
Usage Output
Some *data* Some more
foot locker
Usage Output
Some *data* Some more
Usage Output
Some *data* Some more
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_ul.text0000644000175000017500000000043312672246616026203 0ustar uwabamiuwabami
  • This is a simple list item
  • Followed by another

  • Followed by

    a para list item

  • and a normal one
  • and

    a para

  • multi line list item
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_ol.text0000644000175000017500000000035712672246616026202 0ustar uwabamiuwabami
  1. This is a simple list item
  2. Followed by another

  3. Followed by

    a para list item

  4. and a normal one
  5. and

    a para

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_dl.html0000644000175000017500000000015312672246616026141 0ustar uwabamiuwabami
kram
down
kram
down
kram
down
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_ul.html0000644000175000017500000000043112672246616026161 0ustar uwabamiuwabami
  • This is a simple list item
  • Followed by another

  • Followed by

    a para list item

  • and a normal one
  • and

    a para

  • multi line list item
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_ol.html0000644000175000017500000000035512672246616026160 0ustar uwabamiuwabami
  1. This is a simple list item
  2. Followed by another

  3. Followed by

    a para list item

  4. and a normal one
  5. and

    a para

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/table_simple.text0000644000175000017500000000135112672246616027170 0ustar uwabamiuwabami
Usage Output
Some *data* Some more
Usage Output
Some *data* Some more
foot locker
Usage Output
Some *data* Some more
Usage Output
Some *data* Some more
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/entity.text0000644000175000017500000000007112672246616026042 0ustar uwabamiuwabami

This is *raw* HTML text containing < entities!

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/emphasis.html0000644000175000017500000000026212672246616026321 0ustar uwabamiuwabami

This is sizedhallo.

This is strongitalic, yes!.

This is not converted, as is this.

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/header.html0000644000175000017500000000031312672246616025735 0ustar uwabamiuwabami

Some headerhere!

hallo

hallo

hallo

hallo
hallo
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/list_dl.text0000644000175000017500000000015312672246616026161 0ustar uwabamiuwabami
kram
down
kram
down
kram
down
kramdown-1.10.0/test/testcases/block/09_html/html_to_native/table_normal.html0000644000175000017500000000022512672246616027146 0ustar uwabamiuwabami
Usage Other
Some *data*

Some more

kramdown-1.10.0/test/testcases/block/09_html/html_to_native/header.options0000644000175000017500000000004612672246616026467 0ustar uwabamiuwabami:auto_ids: true :html_to_native: true kramdown-1.10.0/test/testcases/block/09_html/html_to_native/comment.text0000644000175000017500000000006412672246616026172 0ustar uwabamiuwabami
kramdown-1.10.0/test/testcases/block/09_html/invalid_html_1.text0000644000175000017500000000002312672246616024401 0ustar uwabamiuwabamipara
para kramdown-1.10.0/test/testcases/block/09_html/parse_as_span.text0000644000175000017500000000020312672246616024325 0ustar uwabamiuwabami

This *text should* be parsed as span

This produces `

` an unwanted result.

This *text* too

some text kramdown-1.10.0/test/testcases/block/09_html/comment.text0000644000175000017500000000015012672246616023152 0ustar uwabamiuwabami para1 para2 para > This is > kramdown-1.10.0/test/testcases/block/09_html/parse_as_span.options0000644000175000017500000000003012672246616025032 0ustar uwabamiuwabami:parse_block_html: true kramdown-1.10.0/test/testcases/block/14_table/0000755000175000017500000000000012672246616020725 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/14_table/simple.html0000644000175000017500000000461612672246616023113 0ustar uwabamiuwabami
cell1 cell2
cell3 cell4
cell5 cell6 |
cell7 cell8

Missing cells at end

cell1 cell2 cell3
cell1    
  cell2 cell3

Escaped pipe characters

cell1 | cell1 cell2
cell1 cell2 |
cell1 | con cell2

Table with code elements

This is a span | with a pipe.      
Some span </em> here a span | with a pipe.

Special cases regarding codespan syntax

a b
a
table with ial
table with ial

not starting with a bar

simple table
head1 head2
cell1 cell2
head1 head2
  cell2
a b
c d
e f
kramdown-1.10.0/test/testcases/block/14_table/no_table.html0000644000175000017500000000005612672246616023377 0ustar uwabamiuwabami

No table

| Some | thing | here

kramdown-1.10.0/test/testcases/block/14_table/header.text0000644000175000017500000000070012672246616023060 0ustar uwabamiuwabamiSimple header | cell1 | cell2 |----- | cell3 | cell4 Full header | cell1 | cell2 |-------|-------| | cell3 | cell4 With alignment and superfluous alignment defs | default | left | center | right | default |-| :- |:-: | -: | - | :-: | :- | cell1 | cell2 | cell3 | cell4 | cell5 With leading sep line |:-:|-:| | cell1 | cell2 |-------|-------| | cell3 | cell4 Multiple bodies | cell1 | cell2 + :-: | | cell3 | cell4 |----||| | cell5 | cell6 kramdown-1.10.0/test/testcases/block/14_table/errors.html0000644000175000017500000000016312672246616023127 0ustar uwabamiuwabami

No table body

|-|-|-

|no|table|here|

|no|table|here| paragraph

|-|-| |-|-|

kramdown-1.10.0/test/testcases/block/14_table/simple.html.190000644000175000017500000000456212672246616023343 0ustar uwabamiuwabami
cell1 cell2
cell3 cell4
cell5 cell6 |
cell7 cell8

Missing cells at end

cell1 cell2 cell3
cell1    
  cell2 cell3

Escaped pipe characters

cell1 | cell1 cell2
cell1 cell2 |
cell1 | con cell2

Table with code elements

This is a span | with a pipe.      
Some span </em> here a span | with a pipe.

Special cases regarding codespan syntax

a b
a
table with ial
table with ial

not starting with a bar

simple table
head1 head2
cell1 cell2
head1 head2
  cell2
a b
c d
e f
kramdown-1.10.0/test/testcases/block/14_table/table_with_footnote.text0000644000175000017500000000012212672246616025665 0ustar uwabamiuwabami| this is [^1] | a table | with a | footnote [^1]: Something > special here kramdown-1.10.0/test/testcases/block/14_table/simple.text0000644000175000017500000000123012672246616023120 0ustar uwabamiuwabami| cell1 | cell2 | |cell3 | cell4| |cell5|cell6 \| | cell7|cell8 Missing cells at end | cell1 | cell2 | cell3 | | cell1 || || cell2 | cell3 Escaped pipe characters | cell1 \| cell1 | cell2 | | cell1 | cell2 \| | cell1 `|` con | cell2 Table with code elements | This is a span | with a pipe. | Some span | here | a span | with a | pipe. Special cases regarding codespan syntax |a|`b` |`a` {:.cls} | table | with | ial | table | with | ial {:.cls} not starting with a bar simple | table head1 | head2 ------|------ cell1 | cell2 head1 | head2 -------|------ | cell2 | a | b | c | d | e | f | kramdown-1.10.0/test/testcases/block/14_table/escaping.text0000644000175000017500000000040712672246616023425 0ustar uwabamiuwabami`cell 1 | cell 2` cell 1 \| cell 2 cell 1 | cell 2 \| continued cell 1 | cell `2` cell 1 | `code | span` cell 1 `code | span` cell 1 \| `code | span` cell 1 | cell `2 | cell 3 cell 1` | cell 2 | cell 3 cell 1 \| cell `2 | cell 3 cell 1` | cell 2 | cell 3 kramdown-1.10.0/test/testcases/block/14_table/footer.text0000644000175000017500000000037612672246616023137 0ustar uwabamiuwabamiSimple footer | cell1 | cell2 |= | cell3 | cell4 Full footer | cell1 | cell2 |=======|=======| | cell3 | cell4 Footer with separator lines | cell1 | cell2 |=======|=======| | cell3 | cell4 |--- | cell5 | cell6 |--- Empty footer | cell1 | cell2 |= kramdown-1.10.0/test/testcases/block/14_table/table_with_footnote.latex0000644000175000017500000000023512672246616026023 0ustar uwabamiuwabami\begin{longtable}{|l|l|} \hline this is \footnote{Something \begin{quote} special here \end{quote}} & a table\\ with a & footnote\\ \hline \end{longtable} kramdown-1.10.0/test/testcases/block/14_table/footer.html0000644000175000017500000000144512672246616023115 0ustar uwabamiuwabami

Simple footer

cell1 cell2
cell3 cell4

Full footer

cell1 cell2
cell3 cell4

Footer with separator lines

cell1 cell2
cell3 cell4
cell5 cell6

Empty footer

cell1 cell2
kramdown-1.10.0/test/testcases/block/14_table/escaping.html0000644000175000017500000000140512672246616023404 0ustar uwabamiuwabami

cell 1 | cell 2

cell 1 | cell 2

cell 1 cell 2 | continued
cell 1 cell 2
cell 1 code | span

cell 1 code | span

cell 1 | code | span

cell 1 cell `2 cell 3
cell 1` cell 2 cell 3

cell 1 | cell 2 | cell 3 cell 1 | cell 2 | cell 3

kramdown-1.10.0/test/testcases/block/14_table/no_table.text0000644000175000017500000000004312672246616023413 0ustar uwabamiuwabamiNo table \| Some \| thing \| here kramdown-1.10.0/test/testcases/block/14_table/table_with_footnote.html0000644000175000017500000000072212672246616025653 0ustar uwabamiuwabami
this is 1 a table
with a footnote
  1. Something

    special here

kramdown-1.10.0/test/testcases/block/14_table/header.html0000644000175000017500000000274412672246616023052 0ustar uwabamiuwabami

Simple header

cell1 cell2
cell3 cell4

Full header

cell1 cell2
cell3 cell4

With alignment and superfluous alignment defs

default left center right default
cell1 cell2 cell3 cell4 cell5

With leading sep line

cell1 cell2
cell3 cell4

Multiple bodies

cell1 cell2
cell3 cell4
cell5 cell6
kramdown-1.10.0/test/testcases/block/14_table/errors.text0000644000175000017500000000013212672246616023143 0ustar uwabamiuwabamiNo table body |-|-|- [5]: test |no|table|here| |no|table|here| paragraph |-|-| |-|-| kramdown-1.10.0/test/testcases/block/08_list/0000755000175000017500000000000012672246616020614 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/08_list/item_ial.html0000644000175000017500000000024412672246616023265 0ustar uwabamiuwabami
  • IAL at first continued
  • another {:.cls}
  • IAL at last code
  • X test
  • X OK
kramdown-1.10.0/test/testcases/block/08_list/lazy.html0000644000175000017500000000071012672246616022457 0ustar uwabamiuwabami
  • This is a simple list item
  • Followed by another list item

  • Followed by

    a para list item continued here

  • and a normal one
  • and

    a para continued here

para

  • multi line list item

para

  • list item line1 one line two lines
  • list item line2 one line two lines
kramdown-1.10.0/test/testcases/block/08_list/special_cases.text0000644000175000017500000000046312672246616024323 0ustar uwabamiuwabami* not a para here > blockquote * and not here >blockquote * this is a para * > blockquote * this too ^ A paragraph 1. followed not by ol - followed not by ul A compact list: * compact * list * items A normal list: * not * compact * but here List item without content: * * a kramdown-1.10.0/test/testcases/block/08_list/other_first_element.html0000644000175000017500000000106312672246616025543 0ustar uwabamiuwabami
  • This is a code block.
    
  • This is a blockquote.

  • A header

  • This is a code block.
    
  • This is a blockquote. continued by some para.

  • A header

    a para

    • nested list
    • other nested item
  • item 2
kramdown-1.10.0/test/testcases/block/08_list/nested.html0000644000175000017500000000027212672246616022765 0ustar uwabamiuwabami
  • some item
    • nested
  • last item
  • some text

    • nested
kramdown-1.10.0/test/testcases/block/08_list/list_and_others.text0000644000175000017500000000022412672246616024701 0ustar uwabamiuwabami* list item > blockquote para * * * para - no list + item > block ## header * test codeblock test * test codeblock test kramdown-1.10.0/test/testcases/block/08_list/item_ial.text0000644000175000017500000000027612672246616023312 0ustar uwabamiuwabami* {:.cls} IAL at first continued * another {:.cls} * {:.cls} IAL at last code * {::nomarkdown type="html"}X{:/nomarkdown} test * {::nomarkdown type="html"}X{:/nomarkdown} OK kramdown-1.10.0/test/testcases/block/08_list/simple_ol.html0000644000175000017500000000037412672246616023471 0ustar uwabamiuwabami
  1. This is a simple list item
  2. Followed by another

  3. Followed by

    a para list item

  4. and a normal one
  5. and

    a para

para

kramdown-1.10.0/test/testcases/block/08_list/simple_ol.text0000644000175000017500000000021212672246616023500 0ustar uwabamiuwabami1. This is a simple list item 3. Followed by another 10. Followed by a para list item 1. and a normal one 2. and a para para kramdown-1.10.0/test/testcases/block/08_list/mixed.html0000644000175000017500000000244312672246616022613 0ustar uwabamiuwabami

With tabs/spaces, no paras:

  • item1
  • item2
  • item3

With tabs/spaces, paras:

  • item1

  • item2

  • item3

With tabs/spaces, no paras:

  1. item1
  2. item2
  3. item3

With tabs/spaces, paras:

  1. item1

  2. item2

  3. item3

Nested, without paras:

  • item1
    • item2
      • item3

Nested, with paras:

  • item1

    • item2
      • item3 (level 3)

Ordered, without paras:

  1. item1
  2. item2
    • do
    • it
    • now
  3. item3

Ordered, with paras:

  1. item1

  2. item2

    • do
    • it
    • now
  3. item3

Mixed tabs and spaces:

  • some text
    • nested
kramdown-1.10.0/test/testcases/block/08_list/other_first_element.text0000644000175000017500000000041112672246616025557 0ustar uwabamiuwabami* This is a code block. * > This is a blockquote. * ## A header ^ * This is a code block. * > This is a blockquote. continued by some para. * A header ========= a para ^ * * nested list * other nested item * item 2 kramdown-1.10.0/test/testcases/block/08_list/single_item.html0000644000175000017500000000003512672246616023777 0ustar uwabamiuwabami
  • single
kramdown-1.10.0/test/testcases/block/08_list/lazy.text0000644000175000017500000000043512672246616022503 0ustar uwabamiuwabami* This is a simple list item * Followed by another list item * Followed by a para list item continued here * and a normal one * and a para continued here para * multi line list item para * list item line1 one line two lines * list item line2 one line two lines kramdown-1.10.0/test/testcases/block/08_list/mixed.text0000644000175000017500000000106712672246616022634 0ustar uwabamiuwabamiWith tabs/spaces, no paras: * item1 + item2 - item3 With tabs/spaces, paras: - item1 * item2 + item3 With tabs/spaces, no paras: 1. item1 20. item2 3. item3 With tabs/spaces, paras: 1. item1 2. item2 3. item3 Nested, without paras: * item1 * item2 * item3 Nested, with paras: + item1 * item2 * item3 (level 3) Ordered, without paras: 1. item1 2. item2 * do * it * now 3. item3 Ordered, with paras: 1. item1 2. item2 * do * it * now 3. item3 Mixed tabs and spaces: * some text * nested kramdown-1.10.0/test/testcases/block/08_list/escaping.text0000644000175000017500000000037412672246616023317 0ustar uwabamiuwabamiI have read the book 1984. It was great - other say that, too! I have read the book 1984\. It was great \- other say that, too! I have read the book 1984. It was great. I have read the book 1984. - it was great! 1984\. Was great! \- This too! kramdown-1.10.0/test/testcases/block/08_list/simple_ul.html0000644000175000017500000000104212672246616023470 0ustar uwabamiuwabami
  • This is a simple list item
  • Followed by another

  • Followed by

    a para list item

  • and a normal one
  • and

    a para

para

  • multi line list item

para

  • list item line1 one line two lines
  • list item line2 one line two lines

para

  • list item line3 one line two lines
  • list item line4 one line two lines

para

kramdown-1.10.0/test/testcases/block/08_list/list_and_hr.text0000644000175000017500000000006012672246616024004 0ustar uwabamiuwabami* Starting a list * * * * Starting a new list kramdown-1.10.0/test/testcases/block/08_list/list_and_others.html0000644000175000017500000000063312672246616024665 0ustar uwabamiuwabami
  • list item

blockquote

para * * * para - no list

  • item

    block

    header

  • test

    codeblock
    

    test

  • test

    codeblock
    

    test

kramdown-1.10.0/test/testcases/block/08_list/single_item.text0000644000175000017500000000001112672246616024011 0ustar uwabamiuwabami* single kramdown-1.10.0/test/testcases/block/08_list/special_cases.html0000644000175000017500000000132312672246616024277 0ustar uwabamiuwabami
  • not a para here

    blockquote

  • and not here

    blockquote

  • this is a para

  • blockquote

  • this too

A paragraph 1. followed not by ol - followed not by ul

A compact list:

  • compact
  • list
  • items

A normal list:

  • not

  • compact

  • but here

List item without content:

  • a
kramdown-1.10.0/test/testcases/block/08_list/escaping.html0000644000175000017500000000044212672246616023273 0ustar uwabamiuwabami

I have read the book 1984. It was great - other say that, too!

I have read the book 1984. It was great - other say that, too!

I have read the book 1984. It was great.

I have read the book 1984. - it was great!

1984. Was great!

- This too!

kramdown-1.10.0/test/testcases/block/08_list/simple_ul.text0000644000175000017500000000055012672246616023513 0ustar uwabamiuwabami* This is a simple list item * Followed by another * Followed by a para list item * and a normal one * and a para para * multi line list item para * list item line1 one line two lines * list item line2 one line two lines para * list item line3 one line two lines * list item line4 one line two lines para kramdown-1.10.0/test/testcases/block/08_list/nested.text0000644000175000017500000000007612672246616023007 0ustar uwabamiuwabami* some item * nested * last item ^ * some text * nested kramdown-1.10.0/test/testcases/block/08_list/list_and_hr.html0000644000175000017500000000013112672246616023763 0ustar uwabamiuwabami
  • Starting a list

  • Starting a new list
kramdown-1.10.0/test/testcases/block/10_ald/0000755000175000017500000000000012672246616020372 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/10_ald/simple.html0000644000175000017500000000002712672246616022550 0ustar uwabamiuwabami

Some paragraph

kramdown-1.10.0/test/testcases/block/10_ald/simple.text0000644000175000017500000000025612672246616022574 0ustar uwabamiuwabamiSome paragraph {:id: ref1} {:id: .class1} {:id: #id} {:id: key="value"} {:id: .class2 .class3 ref2 #id-with key="value" key='value' key='dfsd\}' } {:test: k ey=value} kramdown-1.10.0/test/testcases/block/06_codeblock/0000755000175000017500000000000012672246616021564 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted.latex0000644000175000017500000000014412672246616026545 0ustar uwabamiuwabami\begin{minted}[]{ruby} x = Class.new \end{minted} \begin{minted}[]{html} href \end{minted} kramdown-1.10.0/test/testcases/block/06_codeblock/with_eob_marker.html0000644000175000017500000000013412672246616025611 0ustar uwabamiuwabami
code block

continued here
new block here
kramdown-1.10.0/test/testcases/block/06_codeblock/tilde_syntax.text0000644000175000017500000000015312672246616025200 0ustar uwabamiuwabami~~~~~~~~ Here comes some code. ~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~ code with tildes ~~~~~~~~ ~~~~~~~~~~~~~~~~~~ kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting.text0000644000175000017500000000006712672246616025142 0ustar uwabamiuwabami x = Class.new ^ href {: .language-html} kramdown-1.10.0/test/testcases/block/06_codeblock/issue_gh45.html0000644000175000017500000000671112672246616024436 0ustar uwabamiuwabami

B

                       BBBBBBBB. 



           BBBB BB BBBBBBBB BBBBB. BBBBBBB BB BBBBB BB BBB BBBB BBBBB BBB BBB BBBB BBB BBBBBBB BBB BBBBBBB. B BBB'B BBBBB BBBB BBB BBBB BBBBBBB BBBB BBBB BBBB BBBBBBBB.


                BBB BBBBB BBBBB BBB BBBB BBBB BBBB, BBB BBBBB BB BBBBB BBB BB BBBBBB BBBB BBB BBBBB BBBB BB. BBBBB BBB BBBBB BBBBB BBB BBBB BB BBBB BBBB BBBBB.


                         BBBB BBBBB, BBBBB, BBBBBBBB?

                   BB BBB BB BBBB BBB BBBB BBB BBBBBB /BBB BB BBBBBBBBB BBBB BBBBBBB BBBBBB BB BBB. 


                   BBBB BBBBBBBB BBB BBBB BB BBBBB BBB BBBBBB BBBB BBBBB BBBBBB BBBBBBBBB BBBB BB BBBBB......................................................................





















              BBBBB B'B BBB BBBBB. BBBB BBBBB BBBBB. ( B BBBBB BBBBBBBBBB BBBBB BBBB'B BBBBB BBBBB. BBB BBBB BBBBB BBBB BBBB. BBBBBBB BBB BB BBBBBBB BBB BBB B BBBB BBBBBBBBBBBB. BBBBB BBBBB.)




























             BBBB'B BB

.

        B BBB BBB BBB ? B. B BBB BBBBBB BBBB BBB BBBB. BBBBBBB BB BBBBBBB B BBBB BBBB BBB BBBBBB. 













         BBBB BB 'BBBB' BBBB BBBBB.


                           BBBBBBBB B BBBB BBBBBB BB BBBBBBBB BBB BBBBBBB BBBBBBB BBBBBBB. 


     B BBBB BB BBBB. BBBBB BBBBBBBB. BBB BB BB. BB BB BBBB BB BBBBBBBBBB. BB BBBBBBBB BB BBBBBBBBB. 


                     BBBBBBBB BB BBBB. BBBBBBB BBB BBBBB BBBBB BBBBB. B'BB BBBBBBB BB BBBBB BBBBB BBBBBBB BBB BBBBB. BBBB. 

  B BBBBBB BBBB BB BBBB BBB. (BB BBB BBBBB BBBBB...............B)



           BBBB!



         BBBB BB BBB BBBBBBB BBBBBB.            B

B

     BBBBB BB/BBB BBBBB!  BBBB BBBB BBBBBBBBBBB 'BBB'B BBBBBB.' 














          BBBB BBBBBBB BBBB BB BBB BBBBBBBB BB BBBB BBBBBB BBB BBBBBBBBB BBBB. BBBBBBBB BBBBBBB BBBB BBBB BBBB BB BBBB BB BBBB BB BBBB B BBB BB BBBBB BBBBBB.  B BBBB BBBBBBB BB BBBB BBBBB B BBB BBBBBBB BB BBBBB BBBB. BBB BBBBBBB BBBB. B BBB BBBB BBBB B BBBB BBBBBB BBB B BBBBBB BBBBBB. BBB BB BBBBBB BBBBBB BBBBBBBBBB BB...BBBBB BBBB BBBB BB BBBBB. (BBBBBBB BBB BBBBBB BBB'B BBBB BBB BBBBB BBB BB BBBBB BBBBBBBBBBB  BBBBB B BBBB BBBB BBBBB. 









BBBBB BB BB BBBB B'B BBBB BBBBB BBBBB BBB BB BBBBBB/BBB (BBBBB) BBBBBB BB. 
                          BBBBBBBB. B BBB BBBB BB BB BBB/BBBBBB BBBBBB BBB BBBB BBBBBBBB BB BB B BBBBBB BBBBBB BBBBB. (BBB/B BBB BBBB BBBB...BBB BBB BBB BBBB BB BB B BBBB BB BBB BB? BBBBBBB B BBB B BBBB BBBBBBBB BBB B BBB BBB BBBBB BBBB BBB BBBB BB B BBBBBBBB BB BBBBB BB BB BBB BBBBB BBB BB BBBBB BBBBBBB B BBB BBBBBBB. BBBBBB (BBBBB) BBBB BBBBB BBBBBBB BBBBB BBBB BBBB BBB. 100 BBBBBB BB BBBBB. BBBB BBB BBB BBBBBB BBB BB. BBB BBBB BB BBB BBBBB! BBB BB BBBBBB BBBBB B BBB'B BBBBBBBBB BBBB BBB BBB. (BBBBBB BBBBBBB BB BBBB BBBBB (BBBBBB BBBBB BBBBB BBBBB.))


    BBB B BBBBBBBBBBB BBBB BBB BB BBB. BBBBB BBB BBBBB B BBBB BBBBBB BBBBB BBB. BB BBBBBB BBB BBBB B BBB BB BBBBBBBB BBBBBB BBBB BBB B BBBBBB BBBB BBBBBB BBBBBBB BBBB BBBB BBB BBBBBBBB.











           BBBBB!!!!!!!


         B BBB BBBB BBBBBB BBBB BBBB BBBB B BBB BBBBB BBB BBBBB B BBBB BBBBBBB BB BB BBBB BBBBBBBBB. B BBBB BBBBBB BBBBBBB BBBB BBBB BBB BBBB.

                                               BB BB, BB BBBBBB BBBB, (BBBBBB BB BBB BBBB . BBBBB BB BBBB BBBB BB BB BBBB BBBB B BBBB BB BB (BB BBBB BB BBB BBBBBBB BB BBBBBBB. )) BB'BB BBB BBB'B BB BB BBBB BB B BBBB B BBBBB (BB BBBBBB BB BBB B'BB BBBBBBBB BB BBBB BBBB.)


  B BBBBB B'BB BBB BB BBBB BBB BBB.
kramdown-1.10.0/test/testcases/block/06_codeblock/normal.text0000644000175000017500000000013712672246616023763 0ustar uwabamiuwabami starting code paragraph other code with samples paragraph ending code kramdown-1.10.0/test/testcases/block/06_codeblock/disable-highlighting.options0000644000175000017500000000002712672246616027246 0ustar uwabamiuwabami:enable_coderay: false kramdown-1.10.0/test/testcases/block/06_codeblock/no_newline_at_end_1.text0000644000175000017500000000002012672246616026351 0ustar uwabamiuwabami test test kramdown-1.10.0/test/testcases/block/06_codeblock/lazy.html0000644000175000017500000000010512672246616023425 0ustar uwabamiuwabami
This is some code

This is some  other code
kramdown-1.10.0/test/testcases/block/06_codeblock/with_blank_line.html0000644000175000017500000000023512672246616025603 0ustar uwabamiuwabami

paragraph

code block

continued here

ended

next blank line has 4 spaces

paragraph

kramdown-1.10.0/test/testcases/block/06_codeblock/disable-highlighting.text0000644000175000017500000000006412672246616026540 0ustar uwabamiuwabami x = Class.new ^ href {: lang="html"} kramdown-1.10.0/test/testcases/block/06_codeblock/error.html0000644000175000017500000000005612672246616023604 0ustar uwabamiuwabami

Some para

~~~~~~ not codeblock

kramdown-1.10.0/test/testcases/block/06_codeblock/error.text0000644000175000017500000000004012672246616023615 0ustar uwabamiuwabamiSome para ~~~~~~ not codeblock kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted-with-opts.text0000644000175000017500000000027312672246616030353 0ustar uwabamiuwabami x = Class.new {: .language-ruby} this is a reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, long link {: .language-html} kramdown-1.10.0/test/testcases/block/06_codeblock/with_blank_line.text0000644000175000017500000000015312672246616025622 0ustar uwabamiuwabamiparagraph code block continued here ended next blank line has 4 spaces paragraph kramdown-1.10.0/test/testcases/block/06_codeblock/whitespace.html0000644000175000017500000000070212672246616024605 0ustar uwabamiuwabami
This	issome
whitespace
kramdown-1.10.0/test/testcases/block/06_codeblock/no_newline_at_end_1.html0000644000175000017500000000004512672246616026340 0ustar uwabamiuwabami
test   test
kramdown-1.10.0/test/testcases/block/06_codeblock/issue_gh45.test0000644000175000017500000000726312672246616024454 0ustar uwabamiuwabami B BBBBBBBB. BBBB BB BBBBBBBB BBBBB. BBBBBBB BB BBBBB BB BBB BBBB BBBBB BBB BBB BBBB BBB BBBBBBB BBB BBBBBBB. B BBB'B BBBBB BBBB BBB BBBB BBBBBBB BBBB BBBB BBBB BBBBBBBB. BBB BBBBB BBBBB BBB BBBB BBBB BBBB, BBB BBBBB BB BBBBB BBB BB BBBBBB BBBB BBB BBBBB BBBB BB. BBBBB BBB BBBBB BBBBB BBB BBBB BB BBBB BBBB BBBBB. BBBB BBBBB, BBBBB, BBBBBBBB? BB BBB BB BBBB BBB BBBB BBB BBBBBB /BBB BB BBBBBBBBB BBBB BBBBBBB BBBBBB BB BBB. BBBB BBBBBBBB BBB BBBB BB BBBBB BBB BBBBBB BBBB BBBBB BBBBBB BBBBBBBBB BBBB BB BBBBB...................................................................... BBBBB B'B BBB BBBBB. BBBB BBBBB BBBBB. ( B BBBBB BBBBBBBBBB BBBBB BBBB'B BBBBB BBBBB. BBB BBBB BBBBB BBBB BBBB. BBBBBBB BBB BB BBBBBBB BBB BBB B BBBB BBBBBBBBBBBB. BBBBB BBBBB.) BBBB'B BB . B BBB BBB BBB ? B. B BBB BBBBBB BBBB BBB BBBB. BBBBBBB BB BBBBBBB B BBBB BBBB BBB BBBBBB. BBBB BB 'BBBB' BBBB BBBBB. BBBBBBBB B BBBB BBBBBB BB BBBBBBBB BBB BBBBBBB BBBBBBB BBBBBBB. B BBBB BB BBBB. BBBBB BBBBBBBB. BBB BB BB. BB BB BBBB BB BBBBBBBBBB. BB BBBBBBBB BB BBBBBBBBB. BBBBBBBB BB BBBB. BBBBBBB BBB BBBBB BBBBB BBBBB. B'BB BBBBBBB BB BBBBB BBBBB BBBBBBB BBB BBBBB. BBBB. B BBBBBB BBBB BB BBBB BBB. (BB BBB BBBBB BBBBB...............B) BBBB! BBBB BB BBB BBBBBBB BBBBBB. B B BBBBB BB/BBB BBBBB! BBBB BBBB BBBBBBBBBBB 'BBB'B BBBBBB.' BBBB BBBBBBB BBBB BB BBB BBBBBBBB BB BBBB BBBBBB BBB BBBBBBBBB BBBB. BBBBBBBB BBBBBBB BBBB BBBB BBBB BB BBBB BB BBBB BB BBBB B BBB BB BBBBB BBBBBB. B BBBB BBBBBBB BB BBBB BBBBB B BBB BBBBBBB BB BBBBB BBBB. BBB BBBBBBB BBBB. B BBB BBBB BBBB B BBBB BBBBBB BBB B BBBBBB BBBBBB. BBB BB BBBBBB BBBBBB BBBBBBBBBB BB...BBBBB BBBB BBBB BB BBBBB. (BBBBBBB BBB BBBBBB BBB'B BBBB BBB BBBBB BBB BB BBBBB BBBBBBBBBBB BBBBB B BBBB BBBB BBBBB. BBBBB BB BB BBBB B'B BBBB BBBBB BBBBB BBB BB BBBBBB/BBB (BBBBB) BBBBBB BB. BBBBBBBB. B BBB BBBB BB BB BBB/BBBBBB BBBBBB BBB BBBB BBBBBBBB BB BB B BBBBBB BBBBBB BBBBB. (BBB/B BBB BBBB BBBB...BBB BBB BBB BBBB BB BB B BBBB BB BBB BB? BBBBBBB B BBB B BBBB BBBBBBBB BBB B BBB BBB BBBBB BBBB BBB BBBB BB B BBBBBBBB BB BBBBB BB BB BBB BBBBB BBB BB BBBBB BBBBBBB B BBB BBBBBBB. BBBBBB (BBBBB) BBBB BBBBB BBBBBBB BBBBB BBBB BBBB BBB. 100 BBBBBB BB BBBBB. BBBB BBB BBB BBBBBB BBB BB. BBB BBBB BB BBB BBBBB! BBB BB BBBBBB BBBBB B BBB'B BBBBBBBBB BBBB BBB BBB. (BBBBBB BBBBBBB BB BBBB BBBBB (BBBBBB BBBBB BBBBB BBBBB.)) BBB B BBBBBBBBBBB BBBB BBB BB BBB. BBBBB BBB BBBBB B BBBB BBBBBB BBBBB BBB. BB BBBBBB BBB BBBB B BBB BB BBBBBBBB BBBBBB BBBB BBB B BBBBBB BBBB BBBBBB BBBBBBB BBBB BBBB BBB BBBBBBBB. BBBBB!!!!!!! B BBB BBBB BBBBBB BBBB BBBB BBBB B BBB BBBBB BBB BBBBB B BBBB BBBBBBB BB BB BBBB BBBBBBBBB. B BBBB BBBBBB BBBBBBB BBBB BBBB BBB BBBB. BB BB, BB BBBBBB BBBB, (BBBBBB BB BBB BBBB . BBBBB BB BBBB BBBB BB BB BBBB BBBB B BBBB BB BB (BB BBBB BB BBB BBBBBBB BB BBBBBBB. )) BB'BB BBB BBB'B BB BB BBBB BB B BBBB B BBBBB (BB BBBBBB BB BBB B'BB BBBBBBBB BB BBBB BBBB.) B BBBBB B'BB BBB BB BBBB BBB BBB. kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted-with-opts.options0000644000175000017500000000013012672246616031052 0ustar uwabamiuwabami:syntax_highlighter: minted :syntax_highlighter_opts: wrap: true line_numbers: true kramdown-1.10.0/test/testcases/block/06_codeblock/disable-highlighting.html0000644000175000017500000000014412672246616026517 0ustar uwabamiuwabami
x = Class.new
<a>href</a>
kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-opts.options0000644000175000017500000000015212672246616026627 0ustar uwabamiuwabami:syntax_highlighter_opts: block: css: class default_lang: ruby wrap: span line_numbers: null kramdown-1.10.0/test/testcases/block/06_codeblock/lazy.text0000644000175000017500000000006412672246616023451 0ustar uwabamiuwabami This is some code This is some other code kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.html0000644000175000017500000000025312672246616031436 0ustar uwabamiuwabami
text
text
text
kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block.html0000644000175000017500000000061512672246616027574 0ustar uwabamiuwabami
def what?
  42
end
def what?
  42
end
def what?
  42
end
def what?
  42
end
def what?
  42
end
kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting.html0000644000175000017500000000040212672246616025113 0ustar uwabamiuwabami
x = Class.new
<a>href</a>
kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block.options0000644000175000017500000000003012672246616030312 0ustar uwabamiuwabami:enable_coderay: false kramdown-1.10.0/test/testcases/block/06_codeblock/tilde_syntax.html0000644000175000017500000000015312672246616025160 0ustar uwabamiuwabami
Here comes some code.
~~~~~~~
code with tildes
~~~~~~~~
kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-opts.html0000644000175000017500000000040212672246616026076 0ustar uwabamiuwabami
x = Class.new
<a>href</a>
kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text0000644000175000017500000000007512672246616032646 0ustar uwabamiuwabami~~~ act-iii s1'dim'a'500'm'500'q'500'' index'j'j+1'j-1'' ~~~ kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted.text0000644000175000017500000000006712672246616026420 0ustar uwabamiuwabami x = Class.new ^ href {: .language-html} kramdown-1.10.0/test/testcases/block/06_codeblock/with_ial.html0000644000175000017500000000015012672246616024246 0ustar uwabamiuwabami
code block

continued here
new block here
kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted-with-opts.latex0000644000175000017500000000037312672246616030505 0ustar uwabamiuwabami\begin{minted}[breaklines,linenos]{ruby} x = Class.new \end{minted} \begin{minted}[breaklines,linenos]{html} this is a reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, reaally, long link \end{minted} kramdown-1.10.0/test/testcases/block/06_codeblock/whitespace.text0000644000175000017500000000007512672246616024630 0ustar uwabamiuwabami This is some whitespace {:.show-whitespaces} kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting.options0000644000175000017500000000013612672246616025646 0ustar uwabamiuwabami:coderay_default_lang: ruby :coderay_wrap: span :coderay_line_numbers: ~ :coderay_css: class kramdown-1.10.0/test/testcases/block/06_codeblock/no_newline_at_end.html0000644000175000017500000000004012672246616026113 0ustar uwabamiuwabami
test  
kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text0000644000175000017500000000010512672246616031452 0ustar uwabamiuwabami~~~ asn.1 text ~~~ ~~~ asn#w1 text ~~~ ~~~ руÑÑкий text ~~~ kramdown-1.10.0/test/testcases/block/06_codeblock/with_eob_marker.text0000644000175000017500000000007012672246616025630 0ustar uwabamiuwabami code block continued here ^ new block here kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.options0000644000175000017500000000003012672246616033344 0ustar uwabamiuwabami:enable_coderay: false kramdown-1.10.0/test/testcases/block/06_codeblock/no_newline_at_end.text0000644000175000017500000000001212672246616026132 0ustar uwabamiuwabami test kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.options0000644000175000017500000000003012672246616032156 0ustar uwabamiuwabami:enable_coderay: false kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block.text0000644000175000017500000000035612672246616027616 0ustar uwabamiuwabami~~~ ruby def what? 42 end ~~~ ~~~ ruby def what? 42 end ~~~ {:.class1} ~~~ def what? 42 end ~~~ {: .language-ruby} ~~~ ruby def what? 42 end ~~~ {: .language-python} ~~~ ruby def what? 42 end ~~~ {: class="language-python"} kramdown-1.10.0/test/testcases/block/06_codeblock/normal.html0000644000175000017500000000025012672246616023737 0ustar uwabamiuwabami
starting code

paragraph

other code  
with samples 

paragraph

  ending code
kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-minted.options0000644000175000017500000000011312672246616027117 0ustar uwabamiuwabami:syntax_highlighter: minted :syntax_highlighter_opts: default_lang: ruby kramdown-1.10.0/test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.html0000644000175000017500000000013712672246616032625 0ustar uwabamiuwabami
s1'dim'a'500'm'500'q'500''
index'j'j+1'j-1''
kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/0000755000175000017500000000000012672246616022705 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/06_codeblock/rouge/simple.html0000644000175000017500000000110412672246616025060 0ustar uwabamiuwabami
x = Class.new
<a>href</a>
$foo = new Bar;
kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/disabled.html0000644000175000017500000000004712672246616025343 0ustar uwabamiuwabami
x = Class.new
kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/simple.options0000644000175000017500000000011212672246616025605 0ustar uwabamiuwabami:syntax_highlighter: rouge :syntax_highlighter_opts: default_lang: ruby kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/simple.text0000644000175000017500000000014412672246616025103 0ustar uwabamiuwabami x = Class.new ^ href {: .language-html} ~~~ php?start_inline=1 $foo = new Bar; ~~~ kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/disabled.text0000644000175000017500000000002212672246616025354 0ustar uwabamiuwabami x = Class.new kramdown-1.10.0/test/testcases/block/06_codeblock/rouge/disabled.options0000644000175000017500000000012012672246616026062 0ustar uwabamiuwabami:syntax_highlighter: rouge :syntax_highlighter_opts: block: disable: true kramdown-1.10.0/test/testcases/block/06_codeblock/highlighting-opts.text0000644000175000017500000000006712672246616026125 0ustar uwabamiuwabami x = Class.new ^ href {: .language-html} kramdown-1.10.0/test/testcases/block/06_codeblock/with_ial.text0000644000175000017500000000007612672246616024275 0ustar uwabamiuwabami code block continued here {:.cls} new block here kramdown-1.10.0/test/testcases/block/12_extension/0000755000175000017500000000000012672246616021650 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/12_extension/nomarkdown.text0000644000175000017500000000046612672246616024743 0ustar uwabamiuwabamiThis is a simple paragraph. {::nomarkdown} This *is* not processed {:/nomarkdown} And another paragraph {::nomarkdown this='is' .ignore /} {::nomarkdown type='html'} bold {:/} {::nomarkdown type="latex"} \begin{itemize} \item[Yes] YESSSS! \end{itemize} {:/} {::nomarkdown} Another paragraph kramdown-1.10.0/test/testcases/block/12_extension/nomarkdown.latex0000644000175000017500000000024412672246616025066 0ustar uwabamiuwabamiThis is a simple paragraph. This *is* not processed And another paragraph \begin{itemize} \item[Yes] YESSSS! \end{itemize} \{::nomarkdown\} Another paragraph kramdown-1.10.0/test/testcases/block/12_extension/ignored.html0000644000175000017500000000014312672246616024163 0ustar uwabamiuwabami

paragraph

{::something} anotherthing {:/something}

{::something/} paragraph

kramdown-1.10.0/test/testcases/block/12_extension/options.html0000644000175000017500000000061412672246616024232 0ustar uwabamiuwabami

No header id

without header id

some *para*

some para

Some text10.

  1. Some text.

kramdown-1.10.0/test/testcases/block/12_extension/ignored.text0000644000175000017500000000011612672246616024203 0ustar uwabamiuwabamiparagraph {::something} anotherthing {:/something} {::something/} paragraph kramdown-1.10.0/test/testcases/block/12_extension/comment.html0000644000175000017500000000024512672246616024201 0ustar uwabamiuwabami

This is a simple paragraph.

And another paragraph

{::comment} Another paragraph

kramdown-1.10.0/test/testcases/block/12_extension/options3.html0000644000175000017500000000034512672246616024316 0ustar uwabamiuwabami
x = Class.new
x = Class.new
kramdown-1.10.0/test/testcases/block/12_extension/nomarkdown.html0000644000175000017500000000022312672246616024712 0ustar uwabamiuwabami

This is a simple paragraph.

This *is* not processed

And another paragraph

bold

{::nomarkdown} Another paragraph

kramdown-1.10.0/test/testcases/block/12_extension/options2.text0000644000175000017500000000010512672246616024327 0ustar uwabamiuwabami{::options footnote_nr="da10" /} Some text[^ab]. [^ab]: Some text. kramdown-1.10.0/test/testcases/block/12_extension/options2.html0000644000175000017500000000036012672246616024312 0ustar uwabamiuwabami

Some text1.

  1. Some text.

kramdown-1.10.0/test/testcases/block/12_extension/nomarkdown.kramdown0000644000175000017500000000040712672246616025574 0ustar uwabamiuwabamiThis is a simple paragraph. {::nomarkdown} This *is* not processed {:/} And another paragraph {::nomarkdown type="html"} bold {:/} {::nomarkdown type="latex"} \begin{itemize} \item[Yes] YESSSS! \end{itemize} {:/} \{::nomarkdown} Another paragraph kramdown-1.10.0/test/testcases/block/12_extension/options.text0000644000175000017500000000042312672246616024250 0ustar uwabamiuwabami# No header id {::options unusedvar="val" /} # without header id
some *para*
{::options parse_block_html="true" parse_span_html="true" /}
some *para*
{::options footnote_nr="10" /} Some text[^ab]. [^ab]: Some text. kramdown-1.10.0/test/testcases/block/12_extension/options3.text0000644000175000017500000000026012672246616024332 0ustar uwabamiuwabami x = Class.new {: .language-ruby} {::options coderay_wrap="span" coderay_line_numbers="" coderay_css="class" coderay_tab_width="4" /} x = Class.new {: .language-ruby} kramdown-1.10.0/test/testcases/block/12_extension/comment.text0000644000175000017500000000030012672246616024211 0ustar uwabamiuwabamiThis is a simple paragraph. {::comment} This is a comment {:/}which is {:/comment} ignored. {:/comment} And another paragraph {::comment this='is' .ignore /} {::comment} Another paragraph kramdown-1.10.0/test/testcases/block/05_blockquote/0000755000175000017500000000000012672246616022006 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/05_blockquote/lazy.html0000644000175000017500000000073112672246616023654 0ustar uwabamiuwabami

This is a long long line.

Nested quote inside still inside

This is a subquote. over multipline lines. continuing here

This is a quote no code

This is a quote

This is a quote

kramdown-1.10.0/test/testcases/block/05_blockquote/nested.html0000644000175000017500000000015212672246616024154 0ustar uwabamiuwabami

foo

bar baz

foo

kramdown-1.10.0/test/testcases/block/05_blockquote/indented.html0000644000175000017500000000052612672246616024471 0ustar uwabamiuwabami

A normal blockquote.

A normal blockquote.

A normal blockquote.

A normal blockquote.

> A codeblock

Blockquote with mixed indents.

kramdown-1.10.0/test/testcases/block/05_blockquote/lazy.text0000644000175000017500000000033112672246616023670 0ustar uwabamiuwabami> This is a long long line. > > Nested quote inside > still inside > > This is a subquote. > > over multipline lines. > continuing here > This is a quote no code > This is a quote {: #id} > This is a quote ^ kramdown-1.10.0/test/testcases/block/05_blockquote/indented.text0000644000175000017500000000024212672246616024504 0ustar uwabamiuwabami> A normal blockquote. > A normal blockquote. > A normal blockquote. > A normal blockquote. > A codeblock > Blockquote > with >mixed > indents. kramdown-1.10.0/test/testcases/block/05_blockquote/with_code_blocks.html0000644000175000017500000000027412672246616026201 0ustar uwabamiuwabami

Example:

sub status {
    print "working";
}

Or:

sub status {
    return "working";
}
kramdown-1.10.0/test/testcases/block/05_blockquote/no_newline_at_end.html0000644000175000017500000000011312672246616026336 0ustar uwabamiuwabami

This is a block quote with no newline.

kramdown-1.10.0/test/testcases/block/05_blockquote/with_code_blocks.text0000644000175000017500000000020612672246616026214 0ustar uwabamiuwabami>Example: > > sub status { > print "working"; > } > > Or: > > sub status { > return "working"; > } kramdown-1.10.0/test/testcases/block/05_blockquote/no_newline_at_end.text0000644000175000017500000000005212672246616026360 0ustar uwabamiuwabami> This is a block quote > with no newline.kramdown-1.10.0/test/testcases/block/05_blockquote/very_long_line.html0000644000175000017500000001602412672246616025712 0ustar uwabamiuwabami

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

kramdown-1.10.0/test/testcases/block/05_blockquote/nested.text0000644000175000017500000000004012672246616024170 0ustar uwabamiuwabami> foo > > > bar >> baz > > foo kramdown-1.10.0/test/testcases/block/05_blockquote/very_long_line.text0000644000175000017500000001576212672246616025742 0ustar uwabamiuwabami> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. kramdown-1.10.0/test/testcases/block/13_definition_list/0000755000175000017500000000000012672246616023020 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/13_definition_list/simple.html0000644000175000017500000000017712672246616025204 0ustar uwabamiuwabami
kram
down
novalue
kram
down kram
down
kramdown-1.10.0/test/testcases/block/13_definition_list/item_ial.html0000644000175000017500000000033312672246616025470 0ustar uwabamiuwabami
item
definition continued
another {:.cls}
code
IAL at last no code bc of text
kramdown-1.10.0/test/testcases/block/13_definition_list/item_ial.text0000644000175000017500000000020412672246616025505 0ustar uwabamiuwabamiitem : {:.cls} definition continued : another {:.cls} : {:.class} code : {:.cls} IAL at last no code bc of text kramdown-1.10.0/test/testcases/block/13_definition_list/para_wrapping.text0000644000175000017500000000005612672246616026561 0ustar uwabamiuwabamiterm : definition : definition : definition kramdown-1.10.0/test/testcases/block/13_definition_list/multiple_terms.html0000644000175000017500000000030112672246616026745 0ustar uwabamiuwabami
kram
down
now
definition 1
definition 2

definition 3

definition 4

kramdown-1.10.0/test/testcases/block/13_definition_list/too_much_space.html0000644000175000017500000000004412672246616026674 0ustar uwabamiuwabami

para

: no definition

kramdown-1.10.0/test/testcases/block/13_definition_list/deflist_ial.text0000644000175000017500000000006312672246616026204 0ustar uwabamiuwabami{:.dl-horizontal} item : definition {:.dl-other} kramdown-1.10.0/test/testcases/block/13_definition_list/no_def_list.html0000644000175000017500000000006212672246616026171 0ustar uwabamiuwabami

This is a para : and not a definition list

kramdown-1.10.0/test/testcases/block/13_definition_list/separated_by_eob.html0000644000175000017500000000012612672246616027174 0ustar uwabamiuwabami
kram
down
kram
down
kramdown-1.10.0/test/testcases/block/13_definition_list/simple.text0000644000175000017500000000006312672246616025216 0ustar uwabamiuwabamikram : down novalue : kram : down kram : down kramdown-1.10.0/test/testcases/block/13_definition_list/definition_at_beginning.text0000644000175000017500000000002012672246616030552 0ustar uwabamiuwabami: no definition kramdown-1.10.0/test/testcases/block/13_definition_list/with_blocks.text0000644000175000017500000000025012672246616026233 0ustar uwabamiuwabamikram : this is some text : this is some more text kram : > blockquote kram : code kram : kram : down kram : # header kram : * list * items kramdown-1.10.0/test/testcases/block/13_definition_list/deflist_ial.html0000644000175000017500000000012012672246616026156 0ustar uwabamiuwabami
item
definition
kramdown-1.10.0/test/testcases/block/13_definition_list/multiple_terms.text0000644000175000017500000000011712672246616026772 0ustar uwabamiuwabamikram *down* now : definition 1 : definition 2 : definition 3 : definition 4 kramdown-1.10.0/test/testcases/block/13_definition_list/no_def_list.text0000644000175000017500000000005412672246616026212 0ustar uwabamiuwabamiThis is a para \: and not a definition list kramdown-1.10.0/test/testcases/block/13_definition_list/too_much_space.text0000644000175000017500000000002712672246616026715 0ustar uwabamiuwabamipara : no definition kramdown-1.10.0/test/testcases/block/13_definition_list/styled_terms.html0000644000175000017500000000006412672246616026424 0ustar uwabamiuwabami
kram
down
kramdown-1.10.0/test/testcases/block/13_definition_list/para_wrapping.html0000644000175000017500000000017312672246616026541 0ustar uwabamiuwabami
term

definition

definition

definition

kramdown-1.10.0/test/testcases/block/13_definition_list/separated_by_eob.text0000644000175000017500000000003212672246616027210 0ustar uwabamiuwabamikram : down ^ kram : down kramdown-1.10.0/test/testcases/block/13_definition_list/styled_terms.text0000644000175000017500000000001612672246616026441 0ustar uwabamiuwabami*kram* : down kramdown-1.10.0/test/testcases/block/13_definition_list/with_blocks.html0000644000175000017500000000075412672246616026224 0ustar uwabamiuwabami
kram
this is some text

this is some more text

kram

blockquote

kram
code
kram
kram
down
kram

header

kram
  • list
  • items
kramdown-1.10.0/test/testcases/block/13_definition_list/definition_at_beginning.html0000644000175000017500000000002712672246616030541 0ustar uwabamiuwabami

: no definition

kramdown-1.10.0/test/testcases/block/15_math/0000755000175000017500000000000012672246616020570 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/block/15_math/ritex.html0000644000175000017500000000051112672246616022606 0ustar uwabamiuwabamif(x)=ax3+bx2+cx+d kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_notexhints.html.190000644000175000017500000000056712672246616026503 0ustar uwabamiuwabami f ( x ) = a x 3 + b x 2 + c x + d kramdown-1.10.0/test/testcases/block/15_math/normal.text0000644000175000017500000000041112672246616022762 0ustar uwabamiuwabamiThis is a para. $$ \text{LaTeX} \lambda_5 $$ $$\lambda_5 = \alpha + 4$$ $$\lambda_\alpha > 5$$ This is a para. $$\begin{align*} &=5 \\ &=6 \\ \end{align*}$$ $$5+5$$ $$5+5$$ $$5+5$$ $$5+5$$ $$5+5$$ {:.cls} $$5+5$$ ^ $$5+5$$ {:.cls} $$|x| = 5$$ kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_notexhints.text0000644000175000017500000000004412672246616026261 0ustar uwabamiuwabami$$f(x) = a{x^3} + b{x^2} + cx + d$$ kramdown-1.10.0/test/testcases/block/15_math/itex2mml.html0000644000175000017500000000067312672246616023225 0ustar uwabamiuwabamif(x)=ax 3+bx 2+cx+df(x) = a{x^3} + b{x^2} + cx + d kramdown-1.10.0/test/testcases/block/15_math/itex2mml.text0000644000175000017500000000004412672246616023235 0ustar uwabamiuwabami$$f(x) = a{x^3} + b{x^2} + cx + d$$ kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_notexhints.options0000644000175000017500000000010012672246616026761 0ustar uwabamiuwabami:math_engine: mathjaxnode :math_engine_opts: :texhints: false kramdown-1.10.0/test/testcases/block/15_math/gh_128.text0000644000175000017500000000007712672246616022472 0ustar uwabamiuwabami$$ $$ kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview.text0000644000175000017500000000005312672246616024671 0ustar uwabamiuwabamiThis is a $$5 + 5$$ statement $$ 5 + 5 $$ kramdown-1.10.0/test/testcases/block/15_math/ritex.text0000644000175000017500000000004412672246616022627 0ustar uwabamiuwabami$$f(x) = a{x^3} + b{x^2} + cx + d$$ kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_semantics.html.190000644000175000017500000000131712672246616026260 0ustar uwabamiuwabami f ( x ) = a x 3 + b x 2 + c x + d f(x) = a{x^3} + b{x^2} + cx + d kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview.options0000644000175000017500000000004412672246616025400 0ustar uwabamiuwabami:math_engine_opts: :preview: true kramdown-1.10.0/test/testcases/block/15_math/gh_128.html0000644000175000017500000000012712672246616022446 0ustar uwabamiuwabami kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode.options0000644000175000017500000000003212672246616024502 0ustar uwabamiuwabami:math_engine: mathjaxnode kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_semantics.options0000644000175000017500000000010012672246616026544 0ustar uwabamiuwabami:math_engine: mathjaxnode :math_engine_opts: :semantics: true kramdown-1.10.0/test/testcases/block/15_math/ritex.options0000644000175000017500000000002412672246616023334 0ustar uwabamiuwabami:math_engine: ritex kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview_simple.html0000644000175000017500000000031112672246616026217 0ustar uwabamiuwabami

This is a math statement

math
kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview_simple.text0000644000175000017500000000005312672246616026242 0ustar uwabamiuwabamiThis is a $$5 + 5$$ statement $$ 5 + 5 $$ kramdown-1.10.0/test/testcases/block/15_math/itex2mml.options0000644000175000017500000000002712672246616023745 0ustar uwabamiuwabami:math_engine: itex2mml kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode.html.190000644000175000017500000000073512672246616024215 0ustar uwabamiuwabami f ( x ) = a x 3 + b x 2 + c x + d kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview_simple.options0000644000175000017500000000004612672246616026753 0ustar uwabamiuwabami:math_engine_opts: :preview: 'math' kramdown-1.10.0/test/testcases/block/15_math/mathjax_preview.html0000644000175000017500000000031312672246616024650 0ustar uwabamiuwabami

This is a 5 + 5 statement

5 + 5
kramdown-1.10.0/test/testcases/block/15_math/normal.html0000644000175000017500000000133612672246616022751 0ustar uwabamiuwabami

This is a para.

This is a para.

$$5+5$$
kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode_semantics.text0000644000175000017500000000004412672246616026044 0ustar uwabamiuwabami$$f(x) = a{x^3} + b{x^2} + cx + d$$ kramdown-1.10.0/test/testcases/block/15_math/mathjaxnode.text0000644000175000017500000000004412672246616023776 0ustar uwabamiuwabami$$f(x) = a{x^3} + b{x^2} + cx + d$$ kramdown-1.10.0/test/testcases/span/0000755000175000017500000000000012672246616017201 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/05_html/0000755000175000017500000000000012672246616020451 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/05_html/normal.text0000644000175000017500000000124712672246616022653 0ustar uwabamiuwabamiEmpty ! title is a title. This is . This is comment. This is multiline comment. This is tag now . This is tag now. This is an empty tag. This is _something strange_. Auto-closing:
Expanding: An invalid tag:
A

block tag

. An invalid tag. A tag. An unclosed *tag.* Some element with | pipe symbol Some element with | pipe symbol Some element with | pipe symbol| underlined kramdown-1.10.0/test/testcases/span/05_html/across_lines.text0000644000175000017500000000004212672246616024037 0ustar uwabamiuwabamiLink: test kramdown-1.10.0/test/testcases/span/05_html/raw_span_elements.text0000644000175000017500000000016212672246616025064 0ustar uwabamiuwabamiThis is raw --version and --version and --version and ---version. kramdown-1.10.0/test/testcases/span/05_html/markdown_attr.html0000644000175000017500000000040512672246616024212 0ustar uwabamiuwabami

This is text This is *text* This is text This is text This is *nothing* to fear about. This is <http://example.com>.

kramdown-1.10.0/test/testcases/span/05_html/invalid.text0000644000175000017500000000003012672246616022776 0ustar uwabamiuwabamiThis is some text kramdown-1.10.0/test/testcases/span/05_html/raw_span_elements.html0000644000175000017500000000017112672246616025044 0ustar uwabamiuwabami

This is raw --version and --version and --version and ---version.

kramdown-1.10.0/test/testcases/span/05_html/link_with_mailto.text0000644000175000017500000000006112672246616024711 0ustar uwabamiuwabamiLink: text kramdown-1.10.0/test/testcases/span/05_html/button.text0000644000175000017500000000027112672246616022672 0ustar uwabamiuwabami First some text and then a and then text. A it. kramdown-1.10.0/test/testcases/span/05_html/mark_element.text0000644000175000017500000000004012672246616024014 0ustar uwabamiuwabamiLorem ipsum. Test kramdown-1.10.0/test/testcases/span/05_html/mark_element.html0000644000175000017500000000005612672246616024003 0ustar uwabamiuwabami

Lorem ipsum.

Test

kramdown-1.10.0/test/testcases/span/05_html/button.html0000644000175000017500000000037512672246616022657 0ustar uwabamiuwabami

First some text and then a

and then text.

A it.

kramdown-1.10.0/test/testcases/span/05_html/markdown_attr.text0000644000175000017500000000047612672246616024242 0ustar uwabamiuwabamiThis is *text* This is *text* This is *text* This is *text* This is *nothing* to *fear* about. This is . kramdown-1.10.0/test/testcases/span/05_html/across_lines.html0000644000175000017500000000005112672246616024017 0ustar uwabamiuwabami

Link: test

kramdown-1.10.0/test/testcases/span/05_html/normal.html0000644000175000017500000000155212672246616022632 0ustar uwabamiuwabami

Empty !

title is a title.

This is .

This is comment.

This is multiline comment.

This is tag now .

This is tag now.

This is an empty tag.

This is something strange.

Auto-closing:

Expanding:

An invalid tag: <hR>

A <p>block tag</p>.

An invalid </closing> tag.

A tag.

An unclosed tag.

Some element with | pipe symbol

Some element with | pipe symbol

Some element with | pipe symbol|

underlined

kramdown-1.10.0/test/testcases/span/05_html/invalid.html0000644000175000017500000000004612672246616022765 0ustar uwabamiuwabami

This is some text

kramdown-1.10.0/test/testcases/span/05_html/link_with_mailto.html0000644000175000017500000000007012672246616024671 0ustar uwabamiuwabami

Link: text

kramdown-1.10.0/test/testcases/span/02_emphasis/0000755000175000017500000000000012672246616021313 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/02_emphasis/normal.text0000644000175000017500000000106612672246616023514 0ustar uwabamiuwabamiThis *is* so **hard**. This _is_ so __hard__ too. *At* start *At* start At *end* At *end* _At_ start _At_ start At _end_ At _end_ And *nest**ed***. And *nest**ed*. And *nest**ed* like** this. And *not_nest_ed*. And ***nested***. And ___nested___. And **nest*e***. And lonely * here*. And lonely ** here**. And **lonely ** here**. ** and here**. And **compli*cated \*** here Some***what* more * ***he*re Do it *\*this\** way Or this \**this*\* way Or that *\*that*\* way Or that \**that\** way [http://blah.com/blah_%28](http://blah.com/blah_%28) kramdown-1.10.0/test/testcases/span/02_emphasis/empty.text0000644000175000017500000000004712672246616023360 0ustar uwabamiuwabamiThis __is **empty. This ****is empty. kramdown-1.10.0/test/testcases/span/02_emphasis/errors.html0000644000175000017500000000021312672246616023511 0ustar uwabamiuwabami

This is a *star.

This is a **star.

This is *a *star.

This is *a star*.

This** is** a star.

kramdown-1.10.0/test/testcases/span/02_emphasis/nesting.text0000644000175000017500000000073612672246616023676 0ustar uwabamiuwabami- ***test test*** - ___test test___ - *test **test*** - **test *test*** - ***test* test** - ***test** test* - ***test* test** - **test *test*** - *test **test*** - _test __test___ - __test _test___ - ___test_ test__ - ___test__ test_ - ___test_ test__ - __test _test___ - _test __test___ ^ - *a*b - a*b* - a*b*c - **a**b - a**b** - a**b**c ^ - _a_b - a_b_ - a_b_c - __a__b - a__b__ - a__b__c - a__2__c - a__2__3 - 1__2__3 ^ - *a _b_ c* - **a __b__ c** kramdown-1.10.0/test/testcases/span/02_emphasis/nesting.html0000644000175000017500000000224312672246616023651 0ustar uwabamiuwabami
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • test test
  • ab
  • ab
  • abc
  • ab
  • ab
  • abc
  • _a_b
  • a_b_
  • a_b_c
  • __a__b
  • a__b__
  • a__b__c
  • a__2__c
  • a__2__3
  • 1__2__3
  • a _b_ c
  • a __b__ c
kramdown-1.10.0/test/testcases/span/02_emphasis/empty.html0000644000175000017500000000007412672246616023340 0ustar uwabamiuwabami

This __is **empty.

This **is empty.

kramdown-1.10.0/test/testcases/span/02_emphasis/normal.html0000644000175000017500000000173212672246616023474 0ustar uwabamiuwabami

This is so hard.

This is so hard too.

At start At start

At end At end

At start At start

At end At end

And nested.

And nest**ed.

And *nested* like this.

And not_nest_ed.

And nested.

And nested.

And neste.

And lonely * here*.

And lonely ** here**.

And lonely ** here.

** and here**.

And compli*cated * here

Some**what more * **here

Do it *this* way Or this *this* way Or that *that* way Or that *that* way

http://blah.com/blah_%28

kramdown-1.10.0/test/testcases/span/02_emphasis/errors.text0000644000175000017500000000014212672246616023532 0ustar uwabamiuwabamiThis is a *star. This is a **star. This is **a *star*. This is *a star\*. This** is** a star. kramdown-1.10.0/test/testcases/span/abbreviations/0000755000175000017500000000000012672246616022031 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/abbreviations/abbrev.text0000644000175000017500000000103612672246616024200 0ustar uwabamiuwabamiThis is some text. *[is some]: Yes it is *[OtHeR!]: This & that *[is some]: It is, yes *[empty]: There *is some real* concern about OtHeR! is some Think empty about Oesterreich. CSS und CSS3 no abbrev here because there is someone and kulis some *[Oesterreich]: Very nice country *[CSS]: Cascading *[CSS3]: Cascading 3 * (X)HTML test * line two [(X)HTML](http://en.wikipedia.org/wiki/Xhtml) * test (X)HTML *[(X)HTML]: (eXtensible) HyperText Markup Language This is awesome. {:.testit} *[awesome]: Some text here {:.test} kramdown-1.10.0/test/testcases/span/abbreviations/abbrev_defs.html0000644000175000017500000000005012672246616025154 0ustar uwabamiuwabami
*[4]: noabbrev
kramdown-1.10.0/test/testcases/span/abbreviations/abbrev.html0000644000175000017500000000155212672246616024163 0ustar uwabamiuwabami

This is some text.

There is some real concern about OtHeR!

is some Think empty about Oesterreich. CSS und CSS3

no abbrev here because there is someone and kulis some

  • (X)HTML test
  • line two

(X)HTML

  • test (X)HTML

This is awesome.

kramdown-1.10.0/test/testcases/span/abbreviations/abbrev_defs.text0000644000175000017500000000017312672246616025202 0ustar uwabamiuwabami*[ABBR]: Some abbreviations *[one abbr]: one abbrev *[2 and other]: another *[3]: yet another *[4]: noabbrev kramdown-1.10.0/test/testcases/span/line_breaks/0000755000175000017500000000000012672246616021457 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/line_breaks/normal.text0000644000175000017500000000022412672246616023653 0ustar uwabamiuwabamiThis is a line with a line break. This is a line without a line break. This is a line \\ with a line\\ break. Line break on last line. kramdown-1.10.0/test/testcases/span/line_breaks/normal.latex0000644000175000017500000000026112672246616024005 0ustar uwabamiuwabamiThis is a line\newline with a line break. This is a line without a line break. This is a line \newline with a line\textbackslash{} \newline break. Line break on last line. kramdown-1.10.0/test/testcases/span/line_breaks/normal.html0000644000175000017500000000026712672246616023642 0ustar uwabamiuwabami

This is a line
with a line break.

This is a line without a line break.

This is a line
with a line\
break.

Line break on last line.

kramdown-1.10.0/test/testcases/span/math/0000755000175000017500000000000012672246616020132 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/math/ritex.html0000644000175000017500000000054412672246616022156 0ustar uwabamiuwabami

This is f(x)=ax3+bx2+cx+d something!

kramdown-1.10.0/test/testcases/span/math/normal.text0000644000175000017500000000025612672246616022333 0ustar uwabamiuwabamiThis is $$\lambda_\alpha > 5$$ some math. With $$1 + 1$$ new line characters in between. $$5+5$$ inline math, $5.00 \$$no math$$ \$\$5+5$$ inline math \$$5+5$$ \$\$5+5$$ kramdown-1.10.0/test/testcases/span/math/itex2mml.html0000644000175000017500000000072612672246616022566 0ustar uwabamiuwabami

This is f(x)=ax 3+bx 2+cx+df(x) = a{x^3} + b{x^2} + cx + d something!

kramdown-1.10.0/test/testcases/span/math/itex2mml.text0000644000175000017500000000006712672246616022604 0ustar uwabamiuwabamiThis is $$f(x) = a{x^3} + b{x^2} + cx + d$$ something! kramdown-1.10.0/test/testcases/span/math/ritex.text0000644000175000017500000000006712672246616022176 0ustar uwabamiuwabamiThis is $$f(x) = a{x^3} + b{x^2} + cx + d$$ something! kramdown-1.10.0/test/testcases/span/math/mathjaxnode.options0000644000175000017500000000003212672246616024044 0ustar uwabamiuwabami:math_engine: mathjaxnode kramdown-1.10.0/test/testcases/span/math/ritex.options0000644000175000017500000000002412672246616022676 0ustar uwabamiuwabami:math_engine: ritex kramdown-1.10.0/test/testcases/span/math/itex2mml.options0000644000175000017500000000002712672246616023307 0ustar uwabamiuwabami:math_engine: itex2mml kramdown-1.10.0/test/testcases/span/math/mathjaxnode.html.190000644000175000017500000000074712672246616023562 0ustar uwabamiuwabami

This is f ( x ) = a x 3 + b x 2 + c x + d something!

kramdown-1.10.0/test/testcases/span/math/normal.html0000644000175000017500000000047712672246616022320 0ustar uwabamiuwabami

This is some math. With new line characters in between.

inline math, $5.00 $$no math$$

$$5+5$$ inline math

$$5+5$$

kramdown-1.10.0/test/testcases/span/math/mathjaxnode.text0000644000175000017500000000006712672246616023345 0ustar uwabamiuwabamiThis is $$f(x) = a{x^3} + b{x^2} + cx + d$$ something! kramdown-1.10.0/test/testcases/span/escaped_chars/0000755000175000017500000000000012672246616021765 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/escaped_chars/normal.text0000644000175000017500000000014112672246616024157 0ustar uwabamiuwabami\\ \. \* \_ \+ \- \` \( \) \[ \] \{ \} \# \! \<< \>> \: \| \" \' \= \> \< kramdown-1.10.0/test/testcases/span/escaped_chars/normal.html0000644000175000017500000000040312672246616024140 0ustar uwabamiuwabami

\

.

*

_

+

-

`

(

)

[

]

{

}

#

!

<<

>>

:

|

"

'

=

>

<

kramdown-1.10.0/test/testcases/span/03_codespan/0000755000175000017500000000000012672246616021277 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/03_codespan/highlighting-minted.latex0000644000175000017500000000007412672246616026262 0ustar uwabamiuwabamiYou can say \mintinline{ruby}{x = Class.new}, for example. kramdown-1.10.0/test/testcases/span/03_codespan/highlighting.text0000644000175000017500000000007312672246616024652 0ustar uwabamiuwabamiYou can say `x = Class.new`{:.language-ruby}, for example. kramdown-1.10.0/test/testcases/span/03_codespan/normal.text0000644000175000017500000000033312672246616023474 0ustar uwabamiuwabamiThis is `a` simple span. With `some&ml` in it. And `` ` `` backticks. And ``` ``some`` ``` more. With backslash `in\` it. This is a ` literal backtick. As \`are\` these! No `` literal backtick``. `something` kramdown-1.10.0/test/testcases/span/03_codespan/empty.text0000644000175000017500000000007012672246616023340 0ustar uwabamiuwabamiThis is `` empty. This is ``empty. This is ````empty. kramdown-1.10.0/test/testcases/span/03_codespan/errors.html0000644000175000017500000000003012672246616023472 0ustar uwabamiuwabami

Not ended `span.

kramdown-1.10.0/test/testcases/span/03_codespan/highlighting.html0000644000175000017500000000026412672246616024634 0ustar uwabamiuwabami

You can say x = Class.new, for example.

kramdown-1.10.0/test/testcases/span/03_codespan/highlighting-minted.text0000644000175000017500000000007312672246616026130 0ustar uwabamiuwabamiYou can say `x = Class.new`{:.language-ruby}, for example. kramdown-1.10.0/test/testcases/span/03_codespan/empty.html0000644000175000017500000000011512672246616023320 0ustar uwabamiuwabami

This is `` empty.

This is ``empty.

This is ````empty.

kramdown-1.10.0/test/testcases/span/03_codespan/normal.html0000644000175000017500000000053312672246616023456 0ustar uwabamiuwabami

This is a simple span.

With some<ht>&ml in it.

And ` backticks.

And ``some`` more.

With backslash in\ it.

This is a ` literal backtick. As `are` these!

No literal backtick.

something

kramdown-1.10.0/test/testcases/span/03_codespan/highlighting-minted.options0000644000175000017500000000003412672246616026634 0ustar uwabamiuwabami:syntax_highlighter: minted kramdown-1.10.0/test/testcases/span/03_codespan/errors.text0000644000175000017500000000002112672246616023512 0ustar uwabamiuwabamiNot ended `span. kramdown-1.10.0/test/testcases/span/03_codespan/rouge/0000755000175000017500000000000012672246616022420 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/03_codespan/rouge/simple.html0000644000175000017500000000033112672246616024574 0ustar uwabamiuwabami

You can say x = Class.new, for example.

kramdown-1.10.0/test/testcases/span/03_codespan/rouge/disabled.html0000644000175000017500000000007512672246616025057 0ustar uwabamiuwabami

You can say Class.

kramdown-1.10.0/test/testcases/span/03_codespan/rouge/simple.options0000644000175000017500000000003312672246616025322 0ustar uwabamiuwabami:syntax_highlighter: rouge kramdown-1.10.0/test/testcases/span/03_codespan/rouge/simple.text0000644000175000017500000000007312672246616024617 0ustar uwabamiuwabamiYou can say `x = Class.new`{:.language-ruby}, for example. kramdown-1.10.0/test/testcases/span/03_codespan/rouge/disabled.text0000644000175000017500000000004612672246616025075 0ustar uwabamiuwabamiYou can say `Class`{:.language-ruby}. kramdown-1.10.0/test/testcases/span/03_codespan/rouge/disabled.options0000644000175000017500000000011712672246616025603 0ustar uwabamiuwabami:syntax_highlighter: rouge :syntax_highlighter_opts: span: disable: true kramdown-1.10.0/test/testcases/span/01_link/0000755000175000017500000000000012672246616020436 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/01_link/empty_title.text0000644000175000017500000000017112672246616023702 0ustar uwabamiuwabamiImage with empty title: ![alt text](/images/other.png) Link [reference][1] with empty title. [1]: http://example.tld kramdown-1.10.0/test/testcases/span/01_link/link_defs.html0000644000175000017500000000050012672246616023255 0ustar uwabamiuwabami

This is a para. [id]: http://www.example.com/

[4]: nourl

Points to 1 and 2 and 3 but not [4]

Points to _.:,;!?- and otherid8

kramdown-1.10.0/test/testcases/span/01_link/link_defs_with_ial.text0000644000175000017500000000045312672246616025164 0ustar uwabamiuwabamiLink def with [attr] and [attr 2] and [attr 3] and [attr before] [attr]: http://example.com 'title' {: hreflang="en" .test} [attr 2]: http://example.com 'title' {: hreflang="en"} {: .test} [attr 3]: http://example.com {: .test} test {: hreflang="en"} {: .test} [attr before]: http://example.com kramdown-1.10.0/test/testcases/span/01_link/empty.text0000644000175000017500000000010512672246616022476 0ustar uwabamiuwabamiThis is [] empty. This is [][] empty. This is [](test.html) empty. kramdown-1.10.0/test/testcases/span/01_link/links_with_angle_brackets.text0000644000175000017500000000012712672246616026543 0ustar uwabamiuwabamiThis is a [link](). This is a [link]( 'and title'). kramdown-1.10.0/test/testcases/span/01_link/reference.html0000644000175000017500000000214012672246616023257 0ustar uwabamiuwabami

simple URL and URL

simple URL and URL

simple 1 and isurl

simple 1 and isurl

this is [a holy isurl]

no [resolution][] here and [here]

with a break in the text

this not [isurl] and not [isurl]

a Link with_BIG letters

bad [no URL] d isurl

[no url] invalid.html [no url]:

“title”

test url but no title test [urldef]

[urldef]: some.url ‘title”

some with spaces

this is a ‘special’ occasion for /all/ of us

this is predefined for URI

kramdown-1.10.0/test/testcases/span/01_link/imagelinks.html0000644000175000017500000000103412672246616023445 0ustar uwabamiuwabami

Simple: alt text

Simple with title: alt text

Empty img link: alt text

Reference style: alt text

Reference style with title: alt text

No alt text:

No id: imgo

With escaped pipe: an | pipe

kramdown-1.10.0/test/testcases/span/01_link/imagelinks.text0000644000175000017500000000053112672246616023466 0ustar uwabamiuwabamiSimple: ![alt text](/images/other.png) Simple with title: ![alt text](/images/other.png "title") Empty img link: ![alt text]() Reference style: ![alt text][img] Reference style with title: ![alt text][imgo] No alt text: ![](other.png) No id: ![imgo] [img]: other.png [imgo]: other.png "Title" With escaped pipe: ![an \| pipe](other.png) kramdown-1.10.0/test/testcases/span/01_link/image_in_a.text0000644000175000017500000000031512672246616023413 0ustar uwabamiuwabamiSimple: [Some ![alt text](/images/other.png)](local.html) Nested: [Some ![alt ![img](text.png) text](/images/other.png)](local.html) Simple: [Some *text ![alt text](/images/other.png) text*](local.html) kramdown-1.10.0/test/testcases/span/01_link/links_with_angle_brackets.html0000644000175000017500000000017512672246616026526 0ustar uwabamiuwabami

This is a link.

This is a link.

kramdown-1.10.0/test/testcases/span/01_link/reference.options0000644000175000017500000000010612672246616024006 0ustar uwabamiuwabami:link_defs: predefined: [predefined.html] URI: [uri.html, My URI] kramdown-1.10.0/test/testcases/span/01_link/empty.html0000644000175000017500000000014512672246616022462 0ustar uwabamiuwabami

This is [] empty.

This is [][] empty.

This is empty.

kramdown-1.10.0/test/testcases/span/01_link/inline.html.190000644000175000017500000000260612672246616023036 0ustar uwabamiuwabami

simple URL

simple URL

simple URL with formatting

simple URL with single quoted title

simple URL with double quoted title

simple URL [with ] escaped

simple URL with ] escaped

simple URL [with] nested

simple URL with [no](link.html) inside

simple URL with parens

simple URL with parens

simple URL broken on line

simple URL with spaces

simple URL with spaces

simple URL with spaces

simple leading/trailing spaces

simple leading/trailing spaces

simple leading/trailing spaces

bad [URL not

bad [URL with parens](something(new.html)

bad [URL with empty title](something.html ‘’)

bad [URL](

bad [URL](no

kramdown-1.10.0/test/testcases/span/01_link/reference.html.190000644000175000017500000000211012672246616023504 0ustar uwabamiuwabami

simple URL and URL

simple URL and URL

simple 1 and isurl

simple 1 and isurl

this is [a holy isurl]

no [resolution][] here and [here]

with a break in the text

this not [isurl] and not [isurl]

a Link with_BIG letters

bad [no URL] d isurl

[no url] invalid.html [no url]:

“titleâ€

test url but no title test [urldef]

[urldef]: some.url ‘titleâ€

some with spaces

this is a ‘special’ occasion for /all/ of us

this is predefined for URI

kramdown-1.10.0/test/testcases/span/01_link/link_defs.text0000644000175000017500000000116512672246616023305 0ustar uwabamiuwabamiThis is a para. [id]: http://www.example.com/ [otherid1]: http://wwww.example.com/ "title 1" [otherid2]: http://wwww.example.com/ 'title 2' [otherid3]: [otherid4]: 'title' [otherid5]: some spaces.html [otherid6]: some spaces.html 'title' [otherid7]: some spaces "title" [otherid8]:test.html#'test' 'title' [break]: http://www.example.com/test/asdf.html 'Another title' [1]: ignored.url [1]: one.url [2]: two.url [3]: three.url [4]: nourl Points to [1] and [2] and [3] but not [4] [_.:,;!?-]: http://example.com Points to [_.:,;!?-] and [otherid8] kramdown-1.10.0/test/testcases/span/01_link/reference.text0000644000175000017500000000144012672246616023301 0ustar uwabamiuwabami[isurl]: someurl.html [1]: otherurl.html simple [URL][1] and [URL][isurl] simple [URL] [1] and [URL] [isurl] simple [1][] and [isurl][] simple [1] and [isurl] this is [a holy [isurl]] no [resolution][] here and [here] with a [break in the text] [break in the text]: url.html this not \[isurl] and not [isurl\] a [Link with_BIG] letters [link WITH_big]: letters.html 'This is the title' bad [no URL] d [isurl] [no url] invalid.html [no url]: [URL but no title]: invalid.html "title" test [url but no title] test [urldef] [urldef]: some.url 'title" some [with spaces] [with spaces]: with spaces.html "title" this [is a 'special' occasion for /all/ of us] [is a 'special' occasion for /all/ of us]: occasion.html this is [predefined] for [URI] kramdown-1.10.0/test/testcases/span/01_link/inline.html0000644000175000017500000000261612672246616022607 0ustar uwabamiuwabami

simple URL

simple URL

simple URL with formatting

simple URL with single quoted title

simple URL with double quoted title

simple URL [with ] escaped

simple URL with ] escaped

simple URL [with] nested

simple URL with [no](link.html) inside

simple URL with parens

simple URL with parens

simple URL broken on line

simple URL with spaces

simple URL with spaces

simple URL with spaces

simple leading/trailing spaces

simple leading/trailing spaces

simple leading/trailing spaces

bad [URL not

bad [URL with parens](something(new.html)

bad [URL with empty title](something.html ‘’)

bad [URL](

bad [URL](no

kramdown-1.10.0/test/testcases/span/01_link/empty_title.htmlinput0000644000175000017500000000025212672246616024742 0ustar uwabamiuwabami

Image with empty title: alt text

Link reference with empty title.

kramdown-1.10.0/test/testcases/span/01_link/inline.text0000644000175000017500000000176212672246616022630 0ustar uwabamiuwabamisimple [URL]() simple [URL](something.html) simple [URL *with* formatting](something.html) simple [URL with single quoted title](something.html 'a t"itle') simple [URL with double quoted title](something.html "a t'itle") simple [URL \[with \] escaped](something.html) simple [URL with \] escaped](something.html) simple [URL [with] nested](something.html) simple [URL with [no](link.html) inside](something.html) simple [URL with parens](/something/to(do)) simple [URL with parens](/something/to(do "doit") simple [URL broken on line](something.html "title") simple [URL with spaces](with spaces.html) simple [URL with spaces](with spaces.html 'title') simple [URL with spaces](with (spaces).html) simple [leading/trailing spaces]( spaces.html) simple [leading/trailing spaces](spaces.html ) simple [leading/trailing spaces]( spaces.html ) bad [URL [not](something.html) bad [URL with parens](something(new.html) bad [URL with empty title](something.html '') bad [URL]( bad [URL](no kramdown-1.10.0/test/testcases/span/01_link/link_defs_with_ial.html0000644000175000017500000000051412672246616025142 0ustar uwabamiuwabami

Link def with attr and attr 2 and attr 3 and attr before

test

kramdown-1.10.0/test/testcases/span/01_link/image_in_a.html0000644000175000017500000000047212672246616023377 0ustar uwabamiuwabami

Simple: Some alt text

Nested: Some alt ![img](text.png) text

Simple: Some text alt text text

kramdown-1.10.0/test/testcases/span/ial/0000755000175000017500000000000012672246616017746 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/ial/simple.html0000644000175000017500000000031612672246616022125 0ustar uwabamiuwabami

This is a span.

This is a span.

This is an{: .ignored} span ial. This is an{: .escaped} span ial.

kramdown-1.10.0/test/testcases/span/ial/simple.text0000644000175000017500000000023012672246616022140 0ustar uwabamiuwabamiThis is a `span`{: .hund #dog}. This is a `span`{: .hund #dog}{: .katz key='val'}. This is an{: .ignored} span ial. This is an\{: .escaped} span ial. kramdown-1.10.0/test/testcases/span/text_substitutions/0000755000175000017500000000000012672246616023204 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_char.options0000644000175000017500000000007412672246616030126 0ustar uwabamiuwabami:entity_output: :as_char :smart_quotes: apos,apos,quot,quot kramdown-1.10.0/test/testcases/span/text_substitutions/lowerthan.html0000644000175000017500000000002712672246616026074 0ustar uwabamiuwabami

0 < 1 < 2

kramdown-1.10.0/test/testcases/span/text_substitutions/entities_symbolic.text0000644000175000017500000000006612672246616027641 0ustar uwabamiuwabamiThis is the A&O. © 2008 by me ŗ and λ kramdown-1.10.0/test/testcases/span/text_substitutions/entities.html0000644000175000017500000000026512672246616025721 0ustar uwabamiuwabami

This is the A&O. © 2008 by me As well \& as this. Some ŗ other values may ¯ may also show but not st. like &#xYZ;.

This is BS&T; done!

kramdown-1.10.0/test/testcases/span/text_substitutions/greaterthan.text0000644000175000017500000000001212672246616026407 0ustar uwabamiuwabami2 > 1 > 0 kramdown-1.10.0/test/testcases/span/text_substitutions/typography.text0000644000175000017500000000116312672246616026321 0ustar uwabamiuwabamiThis is... something---this too--! This <> some text, << this >> too! "Fancy quotes" are 'cool', even in the '80s! Je t' aime. You're a funny one! Thomas' name Mark's name. "...you" "'Nested' quotes are 'possible'", too! '"Otherway" is "round"'! 'Opening now!' '80s are really cool. Cluster's Last Stand. Nam liber tempor "...At vero eos et accusam" "_Single underscores_ should work." "*Single asterisks* should work." '__Double underscores__ should work.' '**Double asterisks** should work.' "_Hurrah!_" '__Absolutely__.' "...some Text" "... some Text" This: "...some Text" This: "... some Text" kramdown-1.10.0/test/testcases/span/text_substitutions/entities_numeric.options0000644000175000017500000000003112672246616030161 0ustar uwabamiuwabami:entity_output: :numeric kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_char.html.190000644000175000017500000000007012672246616027623 0ustar uwabamiuwabami

This "is" 'the' A&O. © 2008 by me ŗ and λ

kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_input.text0000644000175000017500000000006612672246616027642 0ustar uwabamiuwabamiThis is the A&O. © 2008 by me ŗ and λ kramdown-1.10.0/test/testcases/span/text_substitutions/greaterthan.html0000644000175000017500000000002712672246616026375 0ustar uwabamiuwabami

2 > 1 > 0

kramdown-1.10.0/test/testcases/span/text_substitutions/typography.html0000644000175000017500000000222612672246616026302 0ustar uwabamiuwabami

This is… something—this too–!

This «is» some text, « this » too!

“Fancy quotes” are ‘cool’, even in the ’80s! Je t’ aime. You’re a funny one! Thomas’ name Mark’s name. “…you” “‘Nested’ quotes are ‘possible’”, too! ‘“Otherway” is “round”’!

‘Opening now!’

’80s are really cool.

Cluster’s Last Stand.

Nam liber tempor “…At vero eos et accusam”

Single underscores should work.”

Single asterisks should work.”

Double underscores should work.’

Double asterisks should work.’

Hurrah!

Absolutely.’

“…some Text”

“… some Text”

This: “…some Text”

This: “… some Text”

kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_input.options0000644000175000017500000000003212672246616030342 0ustar uwabamiuwabami:entity_output: :as_input kramdown-1.10.0/test/testcases/span/text_substitutions/entities.options0000644000175000017500000000003212672246616026440 0ustar uwabamiuwabami:entity_output: :as_input kramdown-1.10.0/test/testcases/span/text_substitutions/entities_symbolic.html0000644000175000017500000000010212672246616027610 0ustar uwabamiuwabami

This is the A&O. © 2008 by me ŗ and λ

kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_char.text0000644000175000017500000000007212672246616027415 0ustar uwabamiuwabamiThis "is" 'the' A&O. © 2008 by me ŗ and λ kramdown-1.10.0/test/testcases/span/text_substitutions/entities_numeric.text0000644000175000017500000000006612672246616027462 0ustar uwabamiuwabamiThis is the A&O. © 2008 by me ŗ and λ kramdown-1.10.0/test/testcases/span/text_substitutions/entities_symbolic.options0000644000175000017500000000003212672246616030341 0ustar uwabamiuwabami:entity_output: :symbolic kramdown-1.10.0/test/testcases/span/text_substitutions/entities_numeric.html0000644000175000017500000000010012672246616027427 0ustar uwabamiuwabami

This is the A&O. © 2008 by me ŗ and λ

kramdown-1.10.0/test/testcases/span/text_substitutions/entities.text0000644000175000017500000000022712672246616025737 0ustar uwabamiuwabamiThis is the A&O. © 2008 by me As well \& as this. Some ŗ other values may ¯ may also show but not st. like &#xYZ;. This is BS&T; done! kramdown-1.10.0/test/testcases/span/text_substitutions/lowerthan.text0000644000175000017500000000001212672246616026106 0ustar uwabamiuwabami0 < 1 < 2 kramdown-1.10.0/test/testcases/span/text_substitutions/typography.options0000644000175000017500000000003112672246616027021 0ustar uwabamiuwabami:entity_output: symbolic kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_char.html0000644000175000017500000000012712672246616027376 0ustar uwabamiuwabami

This "is" 'the' A&O. © 2008 by me ŗ and λ

kramdown-1.10.0/test/testcases/span/text_substitutions/entities_as_input.html0000644000175000017500000000010112672246616027610 0ustar uwabamiuwabami

This is the A&O. © 2008 by me ŗ and λ

kramdown-1.10.0/test/testcases/span/04_footnote/0000755000175000017500000000000012672246616021341 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/04_footnote/placement.text0000644000175000017500000000017212672246616024217 0ustar uwabamiuwabami* footnotes will be placed here {:footnotes} Some para with a[^1] footnote. [^1]: Footnote \\\` text And another para. kramdown-1.10.0/test/testcases/span/04_footnote/regexp_problem.text0000644000175000017500000000016512672246616025263 0ustar uwabamiuwabami# Something something[^note1]. # Footnotes [^note1]: A note # Test kramdown-1.10.0/test/testcases/span/04_footnote/backlink_text.options0000644000175000017500000000005212672246616025575 0ustar uwabamiuwabami:footnote_backlink: 'text &8617; ' kramdown-1.10.0/test/testcases/span/04_footnote/markers.text0000644000175000017500000000054712672246616023721 0ustar uwabamiuwabamiThis is some *ref.[^fn] [^fn]: Some foot note text {: .class} > a blockquote [^3] * and a list item [^1] # And a header[^now] [^1]:some *text* [^3]: other text with more lines > and a quote A marker without a definition [^without]. A marker [^empty] used twice[^fn] and thrice[^fn]. [^now]: code block continued here [^empty]: kramdown-1.10.0/test/testcases/span/04_footnote/backlink_text.html0000644000175000017500000000041512672246616025051 0ustar uwabamiuwabami

Some footnote here1

  1. Some text here text &8617; <img />

kramdown-1.10.0/test/testcases/span/04_footnote/footnote_nr.text0000644000175000017500000000012612672246616024602 0ustar uwabamiuwabamiThis is a footnote[^ab]. And another[^bc]. [^ab]: Some text. [^bc]: Some other text. kramdown-1.10.0/test/testcases/span/04_footnote/inside_footnote.text0000644000175000017500000000026112672246616025436 0ustar uwabamiuwabamiLorem ipsum[^first] dolor sit amet. Lorem ipsum[^second] dolor sit amet. [^first]: Consecutur adisping.[^third] [^second]: Sed ut perspiciatis unde omnis. [^third]: Sed ut. kramdown-1.10.0/test/testcases/span/04_footnote/without_backlink.text0000644000175000017500000000005712672246616025612 0ustar uwabamiuwabamiSome footnote here[^fn] [^fn]: Some text here kramdown-1.10.0/test/testcases/span/04_footnote/regexp_problem.html0000644000175000017500000000045512672246616025245 0ustar uwabamiuwabami

Something

something1.

Footnotes

Test

  1. A note

kramdown-1.10.0/test/testcases/span/04_footnote/markers.latex0000644000175000017500000000075312672246616024051 0ustar uwabamiuwabamiThis is some *ref.\footnote{Some foot note text} \begin{quote} a blockquote \footnote{other text with more lines \begin{quote} and a quote \end{quote}} \end{quote} \begin{itemize} \item and a list item \footnote{some \emph{text}} \end{itemize} \section*{And a header\footnote{\begin{verbatim}code block continued here \end{verbatim}}} A marker without a definition [\^{}without]. A marker \footnote{} used twice\footnote{Some foot note text} and thrice\footnote{Some foot note text}. kramdown-1.10.0/test/testcases/span/04_footnote/definitions.latex0000644000175000017500000000030112672246616024705 0ustar uwabamiuwabamiSome para. \begin{quote} blockquote \end{quote} \begin{itemize} \item a list with some text \end{itemize} \begin{itemize} \item other list \end{itemize} \begin{verbatim}code \end{verbatim} kramdown-1.10.0/test/testcases/span/04_footnote/footnote_nr.html0000644000175000017500000000070612672246616024566 0ustar uwabamiuwabami

This is a footnote35. And another36.

  1. Some text.

  2. Some other text.

kramdown-1.10.0/test/testcases/span/04_footnote/footnote_nr.options0000644000175000017500000000002112672246616025303 0ustar uwabamiuwabami:footnote_nr: 35 kramdown-1.10.0/test/testcases/span/04_footnote/footnote_nr.latex0000644000175000017500000000012212672246616024727 0ustar uwabamiuwabamiThis is a footnote\footnote{Some text.}. And another\footnote{Some other text.}. kramdown-1.10.0/test/testcases/span/04_footnote/definitions.html0000644000175000017500000000026012672246616024540 0ustar uwabamiuwabami

Some para.

blockquote

  • a list with some text
  • other list
code
kramdown-1.10.0/test/testcases/span/04_footnote/definitions.text0000644000175000017500000000036712672246616024570 0ustar uwabamiuwabamiSome para. [^footnote]: ignored definition [^footnote]: Some footnote text > blockquote [^other]: some foot note text * a list with some text [^tnote]: foot note * other list ^ code [^1]: > a blockquote and some para kramdown-1.10.0/test/testcases/span/04_footnote/placement.html0000644000175000017500000000043312672246616024177 0ustar uwabamiuwabami
  1. Footnote \` text

Some para with a1 footnote.

And another para.

kramdown-1.10.0/test/testcases/span/04_footnote/without_backlink.options0000644000175000017500000000002712672246616026316 0ustar uwabamiuwabami:footnote_backlink: '' kramdown-1.10.0/test/testcases/span/04_footnote/without_backlink.html0000644000175000017500000000030312672246616025564 0ustar uwabamiuwabami

Some footnote here1

  1. Some text here

kramdown-1.10.0/test/testcases/span/04_footnote/markers.html0000644000175000017500000000305212672246616023673 0ustar uwabamiuwabami

This is some *ref.1

a blockquote 2

  • and a list item 3

And a header4

A marker without a definition [^without].

A marker 5 used twice1 and thrice1.

  1. Some foot note text 2 3

  2. other text with more lines

    and a quote

  3. some text

  4. code block
    continued here
    

kramdown-1.10.0/test/testcases/span/04_footnote/backlink_text.text0000644000175000017500000000005712672246616025073 0ustar uwabamiuwabamiSome footnote here[^fn] [^fn]: Some text here kramdown-1.10.0/test/testcases/span/04_footnote/inside_footnote.html0000644000175000017500000000130412672246616025415 0ustar uwabamiuwabami

Lorem ipsum1 dolor sit amet.

Lorem ipsum2 dolor sit amet.

  1. Consecutur adisping.3

  2. Sed ut perspiciatis unde omnis.

  3. Sed ut.

kramdown-1.10.0/test/testcases/span/autolinks/0000755000175000017500000000000012672246616021212 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/autolinks/url_links.html0000644000175000017500000000441012672246616024101 0ustar uwabamiuwabami

This should be a http://www.example.com/ link. This should be a john.doe@example.com link. As should john.doe@example.com this. As should john_doe@example.com this. As should CSS@example.com this. Another ampersand http://www.example.com/?doit&x=y link. More entities http://www.example.com/?doit&x="y&z=y.

Email international übung@macht.den.meister.de, ü.äß@hülse.de Email invalid: <me@example.com>

Autolink with underscore: http://www.example.com/with_under_score

http://www.example.com/

kramdown-1.10.0/test/testcases/span/autolinks/url_links.text0000644000175000017500000000110712672246616024121 0ustar uwabamiuwabamiThis should be a link. This should be a link. As should this. As should this. As should this. Another ampersand link. More entities . Email international <übung@macht.den.meister.de>, <ü.äß@hülse.de> Email invalid: <[me@example.com](mailtos:me@example.com)> Autolink with underscore: *[CSS]: Cascading kramdown-1.10.0/test/testcases/span/extension/0000755000175000017500000000000012672246616021215 5ustar uwabamiuwabamikramdown-1.10.0/test/testcases/span/extension/nomarkdown.text0000644000175000017500000000004712672246616024303 0ustar uwabamiuwabamiThis is {::nomarkdown}*some*{:/} text. kramdown-1.10.0/test/testcases/span/extension/ignored.html0000644000175000017500000000005212672246616023527 0ustar uwabamiuwabami

This is {::something}paragraph{:/}

kramdown-1.10.0/test/testcases/span/extension/options.html0000644000175000017500000000005712672246616023600 0ustar uwabamiuwabami

This is an option *true*!

kramdown-1.10.0/test/testcases/span/extension/ignored.text0000644000175000017500000000004312672246616023547 0ustar uwabamiuwabamiThis is {::something}paragraph{:/} kramdown-1.10.0/test/testcases/span/extension/comment.html0000644000175000017500000000034412672246616023546 0ustar uwabamiuwabami

This is a paragraph. This is a paragraph. This is a . This is a paragraph. This is a {:/comment} simple {:/} paragraph. This is a {::comment} paragraph.

kramdown-1.10.0/test/testcases/span/extension/nomarkdown.html0000644000175000017500000000003412672246616024257 0ustar uwabamiuwabami

This is *some* text.

kramdown-1.10.0/test/testcases/span/extension/options.text0000644000175000017500000000011512672246616023613 0ustar uwabamiuwabamiThis is an {::options parse_span_html="false" /} option *true*! kramdown-1.10.0/test/testcases/span/extension/comment.text0000644000175000017500000000041112672246616023561 0ustar uwabamiuwabamiThis is a {::comment}simple{:/} paragraph. This is a {::comment}simple{:/comment} paragraph. This is a {::comment}simple {:/other} paragraph{:/comment}. This is a {::comment/} paragraph. This is a {:/comment} simple {:/} paragraph. This is a {::comment} paragraph. kramdown-1.10.0/test/testcases/encoding.html0000644000175000017500000000174512672246616020723 0ustar uwabamiuwabami

Das ist gewöhnlich ein Über-Problem mit manchen
Sälen http://example.org und anderen Dinge. Siehe Über mich!

Vielleicht höre ich nicht richtig?

  • Sollten wir uns das überlegen? Verhöhne mich nicht!
  • Ho ho höher! Sind *wir* da?

Titel sind urschön

Manche mögens ärmer

öha
was nun?
Töne
Laute Geräusche
vielleicht noch was ähnliches
hoch höher am höchsten
über drüber müde

Das ist schön gemacht

kramdown-1.10.0/test/test_files.rb0000644000175000017500000005530712672246616016742 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'minitest/autorun' require 'kramdown' require 'yaml' require 'tmpdir' Encoding.default_external = 'utf-8' if RUBY_VERSION >= '1.9' class TestFiles < Minitest::Test EXCLUDE_KD_FILES = [('test/testcases/block/04_header/with_auto_ids.text' if RUBY_VERSION <= '1.8.6'), # bc of dep stringex not working ('test/testcases/span/03_codespan/rouge/' if RUBY_VERSION < '2.0'), #bc of rouge ('test/testcases/block/06_codeblock/rouge/' if RUBY_VERSION < '2.0'), #bc of rouge ].compact # Generate test methods for kramdown-to-xxx conversion Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file| next if EXCLUDE_KD_FILES.any? {|f| text_file =~ /#{f}/} basename = text_file.sub(/\.text$/, '') opts_file = text_file.sub(/\.text$/, '.options') (Dir[basename + ".*"] - [text_file, opts_file]).each do |output_file| next if (RUBY_VERSION >= '1.9' && File.exist?(output_file + '.19')) || (RUBY_VERSION < '1.9' && output_file =~ /\.19$/) output_format = File.extname(output_file.sub(/\.19$/, ''))[1..-1] next if !Kramdown::Converter.const_defined?(output_format[0..0].upcase + output_format[1..-1]) define_method('test_' + text_file.tr('.', '_') + "_to_#{output_format}") do opts_file = File.join(File.dirname(text_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} doc = Kramdown::Document.new(File.read(text_file), options) assert_equal(File.read(output_file), doc.send("to_#{output_format}")) end end end # Generate test methods for html-to-{html,kramdown} conversion `tidy -v 2>&1` if $?.exitstatus != 0 warn("Skipping html-to-{html,kramdown} tests because tidy executable is missing") else EXCLUDE_HTML_FILES = ['test/testcases/block/06_codeblock/whitespace.html', # bc of span inside pre 'test/testcases/block/09_html/simple.html', # bc of xml elements 'test/testcases/span/03_codespan/highlighting.html', # bc of span elements inside code element 'test/testcases/block/04_header/with_auto_ids.html', # bc of auto_ids=true option 'test/testcases/block/04_header/header_type_offset.html', # bc of header_offset option 'test/testcases/block/06_codeblock/rouge/simple.html', # bc of double surrounding
('test/testcases/span/03_codespan/rouge/simple.html' if RUBY_VERSION < '2.0'), ('test/testcases/span/03_codespan/rouge/disabled.html' if RUBY_VERSION < '2.0'), 'test/testcases/block/15_math/ritex.html', # bc of tidy 'test/testcases/span/math/ritex.html', # bc of tidy 'test/testcases/block/15_math/itex2mml.html', # bc of tidy 'test/testcases/span/math/itex2mml.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_notexhints.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_semantics.html', # bc of tidy 'test/testcases/span/math/mathjaxnode.html', # bc of tidy 'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview 'test/testcases/block/15_math/mathjax_preview_simple.html', # bc of mathjax preview 'test/testcases/span/05_html/mark_element.html', # bc of tidy ].compact EXCLUDE_HTML_TEXT_FILES = ['test/testcases/block/09_html/parse_as_span.htmlinput', 'test/testcases/block/09_html/parse_as_raw.htmlinput', ].compact Dir[File.dirname(__FILE__) + '/testcases/**/*.{html,html.19,htmlinput,htmlinput.19}'].each do |html_file| next if EXCLUDE_HTML_FILES.any? {|f| html_file =~ /#{f}(\.19)?$/} next if (RUBY_VERSION >= '1.9' && File.exist?(html_file + '.19')) || (RUBY_VERSION < '1.9' && html_file =~ /\.19$/) out_files = [] out_files << [(html_file =~ /\.htmlinput(\.19)?$/ ? html_file.sub(/input(\.19)?$/, '') : html_file), :to_html] if html_file =~ /\.htmlinput(\.19)?$/ && !EXCLUDE_HTML_TEXT_FILES.any? {|f| html_file =~ /#{f}/} out_files << [html_file.sub(/htmlinput(\.19)?$/, 'text'), :to_kramdown] end out_files.select {|f, _| File.exist?(f)}.each do |out_file, out_method| define_method('test_' + html_file.tr('.', '_') + "_to_#{File.extname(out_file)}") do opts_file = html_file.sub(/\.html(input)?(\.19)?$/, '.options') opts_file = File.join(File.dirname(html_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} doc = Kramdown::Document.new(File.read(html_file), options.merge(:input => 'html')) if out_method == :to_html assert_equal(tidy_output(File.read(out_file)), tidy_output(doc.send(out_method))) else assert_equal(File.read(out_file), doc.send(out_method)) end end end end end def tidy_output(out) cmd = "tidy -q --doctype omit #{RUBY_VERSION >= '1.9' ? '-utf8' : '-raw'} 2>/dev/null" result = IO.popen(cmd, 'r+') do |io| io.write(out) io.close_write io.read end if $?.exitstatus == 2 raise "Problem using tidy" end result end # Generate test methods for text-to-latex conversion and compilation `latex -v 2>&1` if $?.exitstatus != 0 warn("Skipping latex compilation tests because latex executable is missing") else EXCLUDE_LATEX_FILES = ['test/testcases/span/01_link/image_in_a.text', # bc of image link 'test/testcases/span/01_link/imagelinks.text', # bc of image links 'test/testcases/span/01_link/empty_title.text', 'test/testcases/span/04_footnote/markers.text', # bc of footnote in header 'test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text', 'test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text', ].compact Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file| next if EXCLUDE_LATEX_FILES.any? {|f| text_file =~ /#{f}$/} define_method('test_' + text_file.tr('.', '_') + "_to_latex_compilation") do latex = Kramdown::Document.new(File.read(text_file), :auto_ids => false, :footnote_nr => 1, :template => 'document').to_latex Dir.mktmpdir do |tmpdir| result = IO.popen("latex -output-directory='#{tmpdir}' 2>/dev/null", 'r+') do |io| io.write(latex) io.close_write io.read end assert($?.exitstatus == 0, result.scan(/^!(.*\n.*)/).join("\n")) end end end end # Generate test methods for text->kramdown->html conversion `tidy -v 2>&1` if $?.exitstatus != 0 warn("Skipping text->kramdown->html tests because tidy executable is missing") else EXCLUDE_TEXT_FILES = ['test/testcases/span/05_html/markdown_attr.text', # bc of markdown attr 'test/testcases/block/09_html/markdown_attr.text', # bc of markdown attr 'test/testcases/span/extension/options.text', # bc of parse_span_html option 'test/testcases/block/12_extension/options.text', # bc of options option 'test/testcases/block/12_extension/options3.text', # bc of options option 'test/testcases/block/09_html/content_model/tables.text', # bc of parse_block_html option 'test/testcases/block/09_html/html_to_native/header.text', # bc of auto_ids option that interferes 'test/testcases/block/09_html/html_to_native/table_simple.text', # bc of tr style attr getting removed 'test/testcases/block/09_html/simple.text', # bc of webgen:block elements 'test/testcases/block/11_ial/simple.text', # bc of change of ordering of attributes in header 'test/testcases/span/extension/comment.text', # bc of comment text modifications (can this be avoided?) 'test/testcases/block/04_header/header_type_offset.text', # bc of header_offset being applied twice ('test/testcases/block/04_header/with_auto_ids.text' if RUBY_VERSION <= '1.8.6'), # bc of dep stringex not working ('test/testcases/span/03_codespan/rouge/simple.text' if RUBY_VERSION < '2.0'), #bc of rouge ('test/testcases/span/03_codespan/rouge/disabled.text' if RUBY_VERSION < '2.0'), #bc of rouge 'test/testcases/block/06_codeblock/rouge/simple.text', 'test/testcases/block/15_math/ritex.text', # bc of tidy 'test/testcases/span/math/ritex.text', # bc of tidy 'test/testcases/block/15_math/itex2mml.text', # bc of tidy 'test/testcases/span/math/itex2mml.text', # bc of tidy 'test/testcases/block/15_math/mathjaxnode.text', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_notexhints.text', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_semantics.text', # bc of tidy 'test/testcases/span/math/mathjaxnode.text', # bc of tidy 'test/testcases/span/01_link/link_defs_with_ial.text', # bc of attribute ordering 'test/testcases/span/05_html/mark_element.text', # bc of tidy ].compact Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file| next if EXCLUDE_TEXT_FILES.any? {|f| text_file =~ /#{f}$/} html_file = text_file.sub(/\.text$/, '.html') html_file += '.19' if RUBY_VERSION >= '1.9' && File.exist?(html_file + '.19') next unless File.exist?(html_file) define_method('test_' + text_file.tr('.', '_') + "_to_kramdown_to_html") do opts_file = text_file.sub(/\.text$/, '.options') opts_file = File.join(File.dirname(text_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} kdtext = Kramdown::Document.new(File.read(text_file), options).to_kramdown html = Kramdown::Document.new(kdtext, options).to_html assert_equal(tidy_output(File.read(html_file)), tidy_output(html)) end end end # Generate test methods for html-to-kramdown-to-html conversion `tidy -v 2>&1` if $?.exitstatus != 0 warn("Skipping html-to-kramdown-to-html tests because tidy executable is missing") else EXCLUDE_HTML_KD_FILES = ['test/testcases/span/extension/options.html', # bc of parse_span_html option 'test/testcases/span/05_html/normal.html', # bc of br tag before closing p tag 'test/testcases/block/12_extension/nomarkdown.html', # bc of nomarkdown extension 'test/testcases/block/09_html/simple.html', # bc of webgen:block elements 'test/testcases/block/09_html/markdown_attr.html', # bc of markdown attr 'test/testcases/block/09_html/html_to_native/table_simple.html', # bc of invalidly converted simple table 'test/testcases/block/06_codeblock/whitespace.html', # bc of entity to char conversion 'test/testcases/block/06_codeblock/rouge/simple.html', # bc of double surrounding
'test/testcases/block/11_ial/simple.html', # bc of change of ordering of attributes in header 'test/testcases/span/03_codespan/highlighting.html', # bc of span elements inside code element 'test/testcases/block/04_header/with_auto_ids.html', # bc of auto_ids=true option 'test/testcases/block/04_header/header_type_offset.html', # bc of header_offset option 'test/testcases/block/16_toc/toc_exclude.html', # bc of different attribute ordering 'test/testcases/span/autolinks/url_links.html', # bc of quot entity being converted to char ('test/testcases/span/03_codespan/rouge/simple.html' if RUBY_VERSION < '2.0'), ('test/testcases/span/03_codespan/rouge/disabled.html' if RUBY_VERSION < '2.0'), 'test/testcases/block/15_math/ritex.html', # bc of tidy 'test/testcases/span/math/ritex.html', # bc of tidy 'test/testcases/block/15_math/itex2mml.html', # bc of tidy 'test/testcases/span/math/itex2mml.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_notexhints.html', # bc of tidy 'test/testcases/block/15_math/mathjaxnode_semantics.html', # bc of tidy 'test/testcases/span/math/mathjaxnode.html', # bc of tidy 'test/testcases/block/15_math/mathjax_preview.html', # bc of mathjax preview 'test/testcases/block/15_math/mathjax_preview_simple.html', # bc of mathjax preview 'test/testcases/span/01_link/link_defs_with_ial.html', # bc of attribute ordering 'test/testcases/span/05_html/mark_element.html', # bc of tidy ].compact Dir[File.dirname(__FILE__) + '/testcases/**/*.{html,html.19}'].each do |html_file| next if EXCLUDE_HTML_KD_FILES.any? {|f| html_file =~ /#{f}(\.19)?$/} next if (RUBY_VERSION >= '1.9' && File.exist?(html_file + '.19')) || (RUBY_VERSION < '1.9' && html_file =~ /\.19$/) define_method('test_' + html_file.tr('.', '_') + "_to_kramdown_to_html") do kd = Kramdown::Document.new(File.read(html_file), :input => 'html', :auto_ids => false, :footnote_nr => 1).to_kramdown opts_file = html_file.sub(/\.html(\.19)?$/, '.options') opts_file = File.join(File.dirname(html_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} doc = Kramdown::Document.new(kd, options) assert_equal(tidy_output(File.read(html_file)), tidy_output(doc.to_html)) end end end EXCLUDE_GFM_FILES = [ 'test/testcases/block/03_paragraph/no_newline_at_end.text', 'test/testcases/block/03_paragraph/indented.text', 'test/testcases/block/03_paragraph/two_para.text', 'test/testcases/block/04_header/atx_header.text', 'test/testcases/block/04_header/setext_header.text', 'test/testcases/block/05_blockquote/indented.text', 'test/testcases/block/05_blockquote/lazy.text', 'test/testcases/block/05_blockquote/nested.text', 'test/testcases/block/05_blockquote/no_newline_at_end.text', 'test/testcases/block/06_codeblock/error.text', 'test/testcases/block/07_horizontal_rule/error.text', 'test/testcases/block/08_list/escaping.text', 'test/testcases/block/08_list/item_ial.text', 'test/testcases/block/08_list/lazy.text', 'test/testcases/block/08_list/list_and_others.text', 'test/testcases/block/08_list/other_first_element.text', 'test/testcases/block/08_list/simple_ul.text', 'test/testcases/block/08_list/special_cases.text', 'test/testcases/block/09_html/comment.text', 'test/testcases/block/09_html/html_to_native/code.text', 'test/testcases/block/09_html/html_to_native/emphasis.text', 'test/testcases/block/09_html/html_to_native/typography.text', 'test/testcases/block/09_html/parse_as_raw.text', 'test/testcases/block/09_html/simple.text', 'test/testcases/block/12_extension/comment.text', 'test/testcases/block/12_extension/ignored.text', 'test/testcases/block/12_extension/nomarkdown.text', 'test/testcases/block/13_definition_list/item_ial.text', 'test/testcases/block/13_definition_list/multiple_terms.text', 'test/testcases/block/13_definition_list/no_def_list.text', 'test/testcases/block/13_definition_list/simple.text', 'test/testcases/block/13_definition_list/with_blocks.text', 'test/testcases/block/14_table/errors.text', 'test/testcases/block/14_table/escaping.text', 'test/testcases/block/14_table/simple.text', 'test/testcases/block/15_math/normal.text', 'test/testcases/encoding.text', 'test/testcases/span/01_link/inline.text', 'test/testcases/span/01_link/link_defs.text', 'test/testcases/span/01_link/reference.text', 'test/testcases/span/02_emphasis/normal.text', 'test/testcases/span/03_codespan/normal.text', 'test/testcases/span/04_footnote/definitions.text', 'test/testcases/span/04_footnote/markers.text', 'test/testcases/span/05_html/across_lines.text', 'test/testcases/span/05_html/markdown_attr.text', 'test/testcases/span/05_html/normal.text', 'test/testcases/span/05_html/raw_span_elements.text', 'test/testcases/span/autolinks/url_links.text', 'test/testcases/span/extension/comment.text', 'test/testcases/span/ial/simple.text', 'test/testcases/span/line_breaks/normal.text', 'test/testcases/span/text_substitutions/entities_as_char.text', 'test/testcases/span/text_substitutions/entities.text', 'test/testcases/span/text_substitutions/typography.text', ('test/testcases/span/03_codespan/rouge/simple.text' if RUBY_VERSION < '2.0'), ('test/testcases/span/03_codespan/rouge/disabled.text' if RUBY_VERSION < '2.0'), ('test/testcases/block/06_codeblock/rouge/simple.text' if RUBY_VERSION < '2.0'), #bc of rouge ('test/testcases/block/06_codeblock/rouge/disabled.text' if RUBY_VERSION < '2.0'), #bc of rouge ].compact # Generate test methods for gfm-to-html conversion Dir[File.dirname(__FILE__) + '/{testcases,testcases_gfm}/**/*.text'].each do |text_file| next if EXCLUDE_GFM_FILES.any? {|f| text_file =~ /#{f}$/} basename = text_file.sub(/\.text$/, '') html_file = [(".html.19" if RUBY_VERSION >= '1.9'), ".html"].compact. map {|ext| basename + ext }. detect {|file| File.exist?(file) } next unless html_file define_method('test_gfm_' + text_file.tr('.', '_') + "_to_html") do opts_file = basename + '.options' opts_file = File.join(File.dirname(html_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} doc = Kramdown::Document.new(File.read(text_file), options.merge(:input => 'GFM')) assert_equal(File.read(html_file), doc.to_html) end end EXCLUDE_PDF_MODIFY = ['test/testcases/span/text_substitutions/entities.text', 'test/testcases/span/text_substitutions/entities_numeric.text', 'test/testcases/span/text_substitutions/entities_as_char.text', 'test/testcases/span/text_substitutions/entities_as_input.text', 'test/testcases/span/text_substitutions/entities_symbolic.text', 'test/testcases/block/04_header/with_auto_ids.text', ].compact # Generate test methods for asserting that converters don't modify the document tree. Dir[File.dirname(__FILE__) + '/testcases/**/*.text'].each do |text_file| opts_file = text_file.sub(/\.text$/, '.options') options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {:auto_ids => false, :footnote_nr => 1} (Kramdown::Converter.constants.map {|c| c.to_sym} - [:Base, :RemoveHtmlTags, :MathEngine, :SyntaxHighlighter]).each do |conv_class| next if conv_class == :Pdf && (RUBY_VERSION < '2.0' || EXCLUDE_PDF_MODIFY.any? {|f| text_file =~ /#{f}$/}) define_method("test_whether_#{conv_class}_modifies_tree_with_file_#{text_file.tr('.', '_')}") do doc = Kramdown::Document.new(File.read(text_file), options) options_before = Marshal.load(Marshal.dump(doc.options)) tree_before = Marshal.load(Marshal.dump(doc.root)) Kramdown::Converter.const_get(conv_class).convert(doc.root, doc.options) assert_equal(options_before, doc.options) assert_tree_not_changed(tree_before, doc.root) end end end def assert_tree_not_changed(old, new) assert_equal(old.type, new.type, "type mismatch") if old.value.kind_of?(Kramdown::Element) assert_tree_not_changed(old.value, new.value) else assert_equal(old.value, new.value, "value mismatch") end assert_equal(old.attr, new.attr, "attr mismatch") assert_equal(old.options, new.options, "options mismatch") assert_equal(old.children.length, new.children.length, "children count mismatch") old.children.each_with_index do |child, index| assert_tree_not_changed(child, new.children[index]) end end end kramdown-1.10.0/AUTHORS0000644000175000017500000000007512672246616014335 0ustar uwabamiuwabamiThe author of kramdown is Thomas Leitner . kramdown-1.10.0/kramdown.gemspec0000644000175000017500000007321612672246617016464 0ustar uwabamiuwabami######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "kramdown" s.version = "1.10.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Thomas Leitner"] s.date = "2016-03-02" s.description = "kramdown is yet-another-markdown-parser but fast, pure Ruby,\nusing a strict syntax definition and supporting several common extensions.\n" s.email = "t_leitner@gmx.at" s.executables = ["kramdown"] s.files = ["AUTHORS", "CONTRIBUTERS", "COPYING", "README.md", "Rakefile", "VERSION", "benchmark/benchmark.rb", "benchmark/benchmark.sh", "benchmark/generate_data.rb", "benchmark/mdbasics.text", "benchmark/mdsyntax.text", "benchmark/testing.sh", "benchmark/timing.sh", "bin/kramdown", "data/kramdown/document.html", "data/kramdown/document.latex", "doc/_design.scss", "doc/bg.png", "doc/default.scss", "doc/default.template", "doc/documentation.page", "doc/documentation.template", "doc/index.page", "doc/installation.page", "doc/links.markdown", "doc/metainfo", "doc/news.feed", "doc/news.page", "doc/options.page", "doc/quickref.page", "doc/sidebar.template", "doc/sitemap.sitemap", "doc/syntax.page", "doc/tests.page", "doc/virtual", "lib/kramdown.rb", "lib/kramdown/compatibility.rb", "lib/kramdown/converter.rb", "lib/kramdown/converter/base.rb", "lib/kramdown/converter/hash_ast.rb", "lib/kramdown/converter/html.rb", "lib/kramdown/converter/kramdown.rb", "lib/kramdown/converter/latex.rb", "lib/kramdown/converter/math_engine/itex2mml.rb", "lib/kramdown/converter/math_engine/mathjax.rb", "lib/kramdown/converter/math_engine/mathjaxnode.rb", "lib/kramdown/converter/math_engine/ritex.rb", "lib/kramdown/converter/pdf.rb", "lib/kramdown/converter/remove_html_tags.rb", "lib/kramdown/converter/syntax_highlighter.rb", "lib/kramdown/converter/syntax_highlighter/coderay.rb", "lib/kramdown/converter/syntax_highlighter/minted.rb", "lib/kramdown/converter/syntax_highlighter/rouge.rb", "lib/kramdown/converter/toc.rb", "lib/kramdown/document.rb", "lib/kramdown/element.rb", "lib/kramdown/error.rb", "lib/kramdown/options.rb", "lib/kramdown/parser.rb", "lib/kramdown/parser/base.rb", "lib/kramdown/parser/gfm.rb", "lib/kramdown/parser/html.rb", "lib/kramdown/parser/kramdown.rb", "lib/kramdown/parser/kramdown/abbreviation.rb", "lib/kramdown/parser/kramdown/autolink.rb", "lib/kramdown/parser/kramdown/blank_line.rb", "lib/kramdown/parser/kramdown/block_boundary.rb", "lib/kramdown/parser/kramdown/blockquote.rb", "lib/kramdown/parser/kramdown/codeblock.rb", "lib/kramdown/parser/kramdown/codespan.rb", "lib/kramdown/parser/kramdown/emphasis.rb", "lib/kramdown/parser/kramdown/eob.rb", "lib/kramdown/parser/kramdown/escaped_chars.rb", "lib/kramdown/parser/kramdown/extensions.rb", "lib/kramdown/parser/kramdown/footnote.rb", "lib/kramdown/parser/kramdown/header.rb", "lib/kramdown/parser/kramdown/horizontal_rule.rb", "lib/kramdown/parser/kramdown/html.rb", "lib/kramdown/parser/kramdown/html_entity.rb", "lib/kramdown/parser/kramdown/line_break.rb", "lib/kramdown/parser/kramdown/link.rb", "lib/kramdown/parser/kramdown/list.rb", "lib/kramdown/parser/kramdown/math.rb", "lib/kramdown/parser/kramdown/paragraph.rb", "lib/kramdown/parser/kramdown/smart_quotes.rb", "lib/kramdown/parser/kramdown/table.rb", "lib/kramdown/parser/kramdown/typographic_symbol.rb", "lib/kramdown/parser/markdown.rb", "lib/kramdown/utils.rb", "lib/kramdown/utils/configurable.rb", "lib/kramdown/utils/entities.rb", "lib/kramdown/utils/html.rb", "lib/kramdown/utils/ordered_hash.rb", "lib/kramdown/utils/string_scanner.rb", "lib/kramdown/utils/unidecoder.rb", "lib/kramdown/version.rb", "man/man1/kramdown.1", "setup.rb", "test/run_tests.rb", "test/test_files.rb", "test/test_location.rb", "test/test_string_scanner_kramdown.rb", "test/testcases/block/01_blank_line/spaces.html", "test/testcases/block/01_blank_line/spaces.text", "test/testcases/block/01_blank_line/tabs.html", "test/testcases/block/01_blank_line/tabs.text", "test/testcases/block/02_eob/beginning.html", "test/testcases/block/02_eob/beginning.text", "test/testcases/block/02_eob/end.html", "test/testcases/block/02_eob/end.text", "test/testcases/block/02_eob/middle.html", "test/testcases/block/02_eob/middle.text", "test/testcases/block/03_paragraph/indented.html", "test/testcases/block/03_paragraph/indented.html.gfm", "test/testcases/block/03_paragraph/indented.text", "test/testcases/block/03_paragraph/no_newline_at_end.html", "test/testcases/block/03_paragraph/no_newline_at_end.text", "test/testcases/block/03_paragraph/one_para.html", "test/testcases/block/03_paragraph/one_para.text", "test/testcases/block/03_paragraph/two_para.html", "test/testcases/block/03_paragraph/two_para.text", "test/testcases/block/04_header/atx_header.html", "test/testcases/block/04_header/atx_header.text", "test/testcases/block/04_header/atx_header_no_newline_at_end.html", "test/testcases/block/04_header/atx_header_no_newline_at_end.text", "test/testcases/block/04_header/header_type_offset.html", "test/testcases/block/04_header/header_type_offset.kramdown", "test/testcases/block/04_header/header_type_offset.latex", "test/testcases/block/04_header/header_type_offset.options", "test/testcases/block/04_header/header_type_offset.text", "test/testcases/block/04_header/setext_header.html", "test/testcases/block/04_header/setext_header.text", "test/testcases/block/04_header/setext_header_no_newline_at_end.html", "test/testcases/block/04_header/setext_header_no_newline_at_end.text", "test/testcases/block/04_header/with_auto_id_prefix.html", "test/testcases/block/04_header/with_auto_id_prefix.options", "test/testcases/block/04_header/with_auto_id_prefix.text", "test/testcases/block/04_header/with_auto_id_stripping.html", "test/testcases/block/04_header/with_auto_id_stripping.options", "test/testcases/block/04_header/with_auto_id_stripping.text", "test/testcases/block/04_header/with_auto_ids.html", "test/testcases/block/04_header/with_auto_ids.options", "test/testcases/block/04_header/with_auto_ids.text", "test/testcases/block/05_blockquote/indented.html", "test/testcases/block/05_blockquote/indented.text", "test/testcases/block/05_blockquote/lazy.html", "test/testcases/block/05_blockquote/lazy.text", "test/testcases/block/05_blockquote/nested.html", "test/testcases/block/05_blockquote/nested.text", "test/testcases/block/05_blockquote/no_newline_at_end.html", "test/testcases/block/05_blockquote/no_newline_at_end.text", "test/testcases/block/05_blockquote/very_long_line.html", "test/testcases/block/05_blockquote/very_long_line.text", "test/testcases/block/05_blockquote/with_code_blocks.html", "test/testcases/block/05_blockquote/with_code_blocks.text", "test/testcases/block/06_codeblock/disable-highlighting.html", "test/testcases/block/06_codeblock/disable-highlighting.options", "test/testcases/block/06_codeblock/disable-highlighting.text", "test/testcases/block/06_codeblock/error.html", "test/testcases/block/06_codeblock/error.text", "test/testcases/block/06_codeblock/highlighting-minted-with-opts.latex", "test/testcases/block/06_codeblock/highlighting-minted-with-opts.options", "test/testcases/block/06_codeblock/highlighting-minted-with-opts.text", "test/testcases/block/06_codeblock/highlighting-minted.latex", "test/testcases/block/06_codeblock/highlighting-minted.options", "test/testcases/block/06_codeblock/highlighting-minted.text", "test/testcases/block/06_codeblock/highlighting-opts.html", "test/testcases/block/06_codeblock/highlighting-opts.options", "test/testcases/block/06_codeblock/highlighting-opts.text", "test/testcases/block/06_codeblock/highlighting.html", "test/testcases/block/06_codeblock/highlighting.options", "test/testcases/block/06_codeblock/highlighting.text", "test/testcases/block/06_codeblock/issue_gh45.html", "test/testcases/block/06_codeblock/issue_gh45.test", "test/testcases/block/06_codeblock/lazy.html", "test/testcases/block/06_codeblock/lazy.text", "test/testcases/block/06_codeblock/no_newline_at_end.html", "test/testcases/block/06_codeblock/no_newline_at_end.text", "test/testcases/block/06_codeblock/no_newline_at_end_1.html", "test/testcases/block/06_codeblock/no_newline_at_end_1.text", "test/testcases/block/06_codeblock/normal.html", "test/testcases/block/06_codeblock/normal.text", "test/testcases/block/06_codeblock/rouge/disabled.html", "test/testcases/block/06_codeblock/rouge/disabled.options", "test/testcases/block/06_codeblock/rouge/disabled.text", "test/testcases/block/06_codeblock/rouge/simple.html", "test/testcases/block/06_codeblock/rouge/simple.options", "test/testcases/block/06_codeblock/rouge/simple.text", "test/testcases/block/06_codeblock/tilde_syntax.html", "test/testcases/block/06_codeblock/tilde_syntax.text", "test/testcases/block/06_codeblock/whitespace.html", "test/testcases/block/06_codeblock/whitespace.text", "test/testcases/block/06_codeblock/with_blank_line.html", "test/testcases/block/06_codeblock/with_blank_line.text", "test/testcases/block/06_codeblock/with_eob_marker.html", "test/testcases/block/06_codeblock/with_eob_marker.text", "test/testcases/block/06_codeblock/with_ial.html", "test/testcases/block/06_codeblock/with_ial.text", "test/testcases/block/06_codeblock/with_lang_in_fenced_block.html", "test/testcases/block/06_codeblock/with_lang_in_fenced_block.options", "test/testcases/block/06_codeblock/with_lang_in_fenced_block.text", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.html", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.options", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_any_char.text", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.html", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.options", "test/testcases/block/06_codeblock/with_lang_in_fenced_block_name_with_dash.text", "test/testcases/block/07_horizontal_rule/error.html", "test/testcases/block/07_horizontal_rule/error.html.19", "test/testcases/block/07_horizontal_rule/error.text", "test/testcases/block/07_horizontal_rule/normal.html", "test/testcases/block/07_horizontal_rule/normal.text", "test/testcases/block/07_horizontal_rule/sepspaces.html", "test/testcases/block/07_horizontal_rule/sepspaces.text", "test/testcases/block/07_horizontal_rule/septabs.html", "test/testcases/block/07_horizontal_rule/septabs.text", "test/testcases/block/08_list/escaping.html", "test/testcases/block/08_list/escaping.text", "test/testcases/block/08_list/item_ial.html", "test/testcases/block/08_list/item_ial.text", "test/testcases/block/08_list/lazy.html", "test/testcases/block/08_list/lazy.text", "test/testcases/block/08_list/list_and_hr.html", "test/testcases/block/08_list/list_and_hr.text", "test/testcases/block/08_list/list_and_others.html", "test/testcases/block/08_list/list_and_others.text", "test/testcases/block/08_list/mixed.html", "test/testcases/block/08_list/mixed.text", "test/testcases/block/08_list/nested.html", "test/testcases/block/08_list/nested.text", "test/testcases/block/08_list/other_first_element.html", "test/testcases/block/08_list/other_first_element.text", "test/testcases/block/08_list/simple_ol.html", "test/testcases/block/08_list/simple_ol.text", "test/testcases/block/08_list/simple_ul.html", "test/testcases/block/08_list/simple_ul.text", "test/testcases/block/08_list/single_item.html", "test/testcases/block/08_list/single_item.text", "test/testcases/block/08_list/special_cases.html", "test/testcases/block/08_list/special_cases.text", "test/testcases/block/09_html/comment.html", "test/testcases/block/09_html/comment.text", "test/testcases/block/09_html/content_model/deflists.html", "test/testcases/block/09_html/content_model/deflists.options", "test/testcases/block/09_html/content_model/deflists.text", "test/testcases/block/09_html/content_model/tables.html", "test/testcases/block/09_html/content_model/tables.options", "test/testcases/block/09_html/content_model/tables.text", "test/testcases/block/09_html/html5_attributes.html", "test/testcases/block/09_html/html5_attributes.text", "test/testcases/block/09_html/html_after_block.html", "test/testcases/block/09_html/html_after_block.text", "test/testcases/block/09_html/html_and_codeblocks.html", "test/testcases/block/09_html/html_and_codeblocks.options", "test/testcases/block/09_html/html_and_codeblocks.text", "test/testcases/block/09_html/html_and_headers.html", "test/testcases/block/09_html/html_and_headers.text", "test/testcases/block/09_html/html_to_native/code.html", "test/testcases/block/09_html/html_to_native/code.text", "test/testcases/block/09_html/html_to_native/comment.html", "test/testcases/block/09_html/html_to_native/comment.text", "test/testcases/block/09_html/html_to_native/emphasis.html", "test/testcases/block/09_html/html_to_native/emphasis.text", "test/testcases/block/09_html/html_to_native/entity.html", "test/testcases/block/09_html/html_to_native/entity.text", "test/testcases/block/09_html/html_to_native/header.html", "test/testcases/block/09_html/html_to_native/header.options", "test/testcases/block/09_html/html_to_native/header.text", "test/testcases/block/09_html/html_to_native/list_dl.html", "test/testcases/block/09_html/html_to_native/list_dl.text", "test/testcases/block/09_html/html_to_native/list_ol.html", "test/testcases/block/09_html/html_to_native/list_ol.text", "test/testcases/block/09_html/html_to_native/list_ul.html", "test/testcases/block/09_html/html_to_native/list_ul.text", "test/testcases/block/09_html/html_to_native/options", "test/testcases/block/09_html/html_to_native/paragraph.html", "test/testcases/block/09_html/html_to_native/paragraph.text", "test/testcases/block/09_html/html_to_native/table_normal.html", "test/testcases/block/09_html/html_to_native/table_normal.text", "test/testcases/block/09_html/html_to_native/table_simple.html", "test/testcases/block/09_html/html_to_native/table_simple.text", "test/testcases/block/09_html/html_to_native/typography.html", "test/testcases/block/09_html/html_to_native/typography.html.19", "test/testcases/block/09_html/html_to_native/typography.text", "test/testcases/block/09_html/invalid_html_1.html", "test/testcases/block/09_html/invalid_html_1.text", "test/testcases/block/09_html/invalid_html_2.html", "test/testcases/block/09_html/invalid_html_2.text", "test/testcases/block/09_html/markdown_attr.html", "test/testcases/block/09_html/markdown_attr.text", "test/testcases/block/09_html/not_parsed.html", "test/testcases/block/09_html/not_parsed.text", "test/testcases/block/09_html/parse_as_raw.html", "test/testcases/block/09_html/parse_as_raw.htmlinput", "test/testcases/block/09_html/parse_as_raw.options", "test/testcases/block/09_html/parse_as_raw.text", "test/testcases/block/09_html/parse_as_span.html", "test/testcases/block/09_html/parse_as_span.htmlinput", "test/testcases/block/09_html/parse_as_span.options", "test/testcases/block/09_html/parse_as_span.text", "test/testcases/block/09_html/parse_block_html.html", "test/testcases/block/09_html/parse_block_html.options", "test/testcases/block/09_html/parse_block_html.text", "test/testcases/block/09_html/processing_instruction.html", "test/testcases/block/09_html/processing_instruction.text", "test/testcases/block/09_html/simple.html", "test/testcases/block/09_html/simple.html.19", "test/testcases/block/09_html/simple.options", "test/testcases/block/09_html/simple.text", "test/testcases/block/09_html/textarea.html", "test/testcases/block/09_html/textarea.text", "test/testcases/block/10_ald/simple.html", "test/testcases/block/10_ald/simple.text", "test/testcases/block/11_ial/auto_id_and_ial.html", "test/testcases/block/11_ial/auto_id_and_ial.options", "test/testcases/block/11_ial/auto_id_and_ial.text", "test/testcases/block/11_ial/nested.html", "test/testcases/block/11_ial/nested.text", "test/testcases/block/11_ial/simple.html", "test/testcases/block/11_ial/simple.text", "test/testcases/block/12_extension/comment.html", "test/testcases/block/12_extension/comment.text", "test/testcases/block/12_extension/ignored.html", "test/testcases/block/12_extension/ignored.text", "test/testcases/block/12_extension/nomarkdown.html", "test/testcases/block/12_extension/nomarkdown.kramdown", "test/testcases/block/12_extension/nomarkdown.latex", "test/testcases/block/12_extension/nomarkdown.text", "test/testcases/block/12_extension/options.html", "test/testcases/block/12_extension/options.text", "test/testcases/block/12_extension/options2.html", "test/testcases/block/12_extension/options2.text", "test/testcases/block/12_extension/options3.html", "test/testcases/block/12_extension/options3.text", "test/testcases/block/13_definition_list/definition_at_beginning.html", "test/testcases/block/13_definition_list/definition_at_beginning.text", "test/testcases/block/13_definition_list/deflist_ial.html", "test/testcases/block/13_definition_list/deflist_ial.text", "test/testcases/block/13_definition_list/item_ial.html", "test/testcases/block/13_definition_list/item_ial.text", "test/testcases/block/13_definition_list/multiple_terms.html", "test/testcases/block/13_definition_list/multiple_terms.text", "test/testcases/block/13_definition_list/no_def_list.html", "test/testcases/block/13_definition_list/no_def_list.text", "test/testcases/block/13_definition_list/para_wrapping.html", "test/testcases/block/13_definition_list/para_wrapping.text", "test/testcases/block/13_definition_list/separated_by_eob.html", "test/testcases/block/13_definition_list/separated_by_eob.text", "test/testcases/block/13_definition_list/simple.html", "test/testcases/block/13_definition_list/simple.text", "test/testcases/block/13_definition_list/styled_terms.html", "test/testcases/block/13_definition_list/styled_terms.text", "test/testcases/block/13_definition_list/too_much_space.html", "test/testcases/block/13_definition_list/too_much_space.text", "test/testcases/block/13_definition_list/with_blocks.html", "test/testcases/block/13_definition_list/with_blocks.text", "test/testcases/block/14_table/errors.html", "test/testcases/block/14_table/errors.text", "test/testcases/block/14_table/escaping.html", "test/testcases/block/14_table/escaping.text", "test/testcases/block/14_table/footer.html", "test/testcases/block/14_table/footer.text", "test/testcases/block/14_table/header.html", "test/testcases/block/14_table/header.text", "test/testcases/block/14_table/no_table.html", "test/testcases/block/14_table/no_table.text", "test/testcases/block/14_table/simple.html", "test/testcases/block/14_table/simple.html.19", "test/testcases/block/14_table/simple.text", "test/testcases/block/14_table/table_with_footnote.html", "test/testcases/block/14_table/table_with_footnote.latex", "test/testcases/block/14_table/table_with_footnote.text", "test/testcases/block/15_math/gh_128.html", "test/testcases/block/15_math/gh_128.text", "test/testcases/block/15_math/itex2mml.html", "test/testcases/block/15_math/itex2mml.options", "test/testcases/block/15_math/itex2mml.text", "test/testcases/block/15_math/mathjax_preview.html", "test/testcases/block/15_math/mathjax_preview.options", "test/testcases/block/15_math/mathjax_preview.text", "test/testcases/block/15_math/mathjax_preview_simple.html", "test/testcases/block/15_math/mathjax_preview_simple.options", "test/testcases/block/15_math/mathjax_preview_simple.text", "test/testcases/block/15_math/mathjaxnode.html.19", "test/testcases/block/15_math/mathjaxnode.options", "test/testcases/block/15_math/mathjaxnode.text", "test/testcases/block/15_math/mathjaxnode_notexhints.html.19", "test/testcases/block/15_math/mathjaxnode_notexhints.options", "test/testcases/block/15_math/mathjaxnode_notexhints.text", "test/testcases/block/15_math/mathjaxnode_semantics.html.19", "test/testcases/block/15_math/mathjaxnode_semantics.options", "test/testcases/block/15_math/mathjaxnode_semantics.text", "test/testcases/block/15_math/normal.html", "test/testcases/block/15_math/normal.text", "test/testcases/block/15_math/ritex.html", "test/testcases/block/15_math/ritex.options", "test/testcases/block/15_math/ritex.text", "test/testcases/block/16_toc/no_toc.html", "test/testcases/block/16_toc/no_toc.text", "test/testcases/block/16_toc/toc_exclude.html", "test/testcases/block/16_toc/toc_exclude.options", "test/testcases/block/16_toc/toc_exclude.text", "test/testcases/block/16_toc/toc_levels.html", "test/testcases/block/16_toc/toc_levels.options", "test/testcases/block/16_toc/toc_levels.text", "test/testcases/block/16_toc/toc_with_footnotes.html", "test/testcases/block/16_toc/toc_with_footnotes.options", "test/testcases/block/16_toc/toc_with_footnotes.text", "test/testcases/encoding.html", "test/testcases/encoding.text", "test/testcases/span/01_link/empty.html", "test/testcases/span/01_link/empty.text", "test/testcases/span/01_link/empty_title.htmlinput", "test/testcases/span/01_link/empty_title.text", "test/testcases/span/01_link/image_in_a.html", "test/testcases/span/01_link/image_in_a.text", "test/testcases/span/01_link/imagelinks.html", "test/testcases/span/01_link/imagelinks.text", "test/testcases/span/01_link/inline.html", "test/testcases/span/01_link/inline.html.19", "test/testcases/span/01_link/inline.text", "test/testcases/span/01_link/link_defs.html", "test/testcases/span/01_link/link_defs.text", "test/testcases/span/01_link/link_defs_with_ial.html", "test/testcases/span/01_link/link_defs_with_ial.text", "test/testcases/span/01_link/links_with_angle_brackets.html", "test/testcases/span/01_link/links_with_angle_brackets.text", "test/testcases/span/01_link/reference.html", "test/testcases/span/01_link/reference.html.19", "test/testcases/span/01_link/reference.options", "test/testcases/span/01_link/reference.text", "test/testcases/span/02_emphasis/empty.html", "test/testcases/span/02_emphasis/empty.text", "test/testcases/span/02_emphasis/errors.html", "test/testcases/span/02_emphasis/errors.text", "test/testcases/span/02_emphasis/nesting.html", "test/testcases/span/02_emphasis/nesting.text", "test/testcases/span/02_emphasis/normal.html", "test/testcases/span/02_emphasis/normal.text", "test/testcases/span/03_codespan/empty.html", "test/testcases/span/03_codespan/empty.text", "test/testcases/span/03_codespan/errors.html", "test/testcases/span/03_codespan/errors.text", "test/testcases/span/03_codespan/highlighting-minted.latex", "test/testcases/span/03_codespan/highlighting-minted.options", "test/testcases/span/03_codespan/highlighting-minted.text", "test/testcases/span/03_codespan/highlighting.html", "test/testcases/span/03_codespan/highlighting.text", "test/testcases/span/03_codespan/normal.html", "test/testcases/span/03_codespan/normal.text", "test/testcases/span/03_codespan/rouge/disabled.html", "test/testcases/span/03_codespan/rouge/disabled.options", "test/testcases/span/03_codespan/rouge/disabled.text", "test/testcases/span/03_codespan/rouge/simple.html", "test/testcases/span/03_codespan/rouge/simple.options", "test/testcases/span/03_codespan/rouge/simple.text", "test/testcases/span/04_footnote/backlink_text.html", "test/testcases/span/04_footnote/backlink_text.options", "test/testcases/span/04_footnote/backlink_text.text", "test/testcases/span/04_footnote/definitions.html", "test/testcases/span/04_footnote/definitions.latex", "test/testcases/span/04_footnote/definitions.text", "test/testcases/span/04_footnote/footnote_nr.html", "test/testcases/span/04_footnote/footnote_nr.latex", "test/testcases/span/04_footnote/footnote_nr.options", "test/testcases/span/04_footnote/footnote_nr.text", "test/testcases/span/04_footnote/inside_footnote.html", "test/testcases/span/04_footnote/inside_footnote.text", "test/testcases/span/04_footnote/markers.html", "test/testcases/span/04_footnote/markers.latex", "test/testcases/span/04_footnote/markers.text", "test/testcases/span/04_footnote/placement.html", "test/testcases/span/04_footnote/placement.text", "test/testcases/span/04_footnote/regexp_problem.html", "test/testcases/span/04_footnote/regexp_problem.text", "test/testcases/span/04_footnote/without_backlink.html", "test/testcases/span/04_footnote/without_backlink.options", "test/testcases/span/04_footnote/without_backlink.text", "test/testcases/span/05_html/across_lines.html", "test/testcases/span/05_html/across_lines.text", "test/testcases/span/05_html/button.html", "test/testcases/span/05_html/button.text", "test/testcases/span/05_html/invalid.html", "test/testcases/span/05_html/invalid.text", "test/testcases/span/05_html/link_with_mailto.html", "test/testcases/span/05_html/link_with_mailto.text", "test/testcases/span/05_html/mark_element.html", "test/testcases/span/05_html/mark_element.text", "test/testcases/span/05_html/markdown_attr.html", "test/testcases/span/05_html/markdown_attr.text", "test/testcases/span/05_html/normal.html", "test/testcases/span/05_html/normal.text", "test/testcases/span/05_html/raw_span_elements.html", "test/testcases/span/05_html/raw_span_elements.text", "test/testcases/span/abbreviations/abbrev.html", "test/testcases/span/abbreviations/abbrev.text", "test/testcases/span/abbreviations/abbrev_defs.html", "test/testcases/span/abbreviations/abbrev_defs.text", "test/testcases/span/autolinks/url_links.html", "test/testcases/span/autolinks/url_links.text", "test/testcases/span/escaped_chars/normal.html", "test/testcases/span/escaped_chars/normal.text", "test/testcases/span/extension/comment.html", "test/testcases/span/extension/comment.text", "test/testcases/span/extension/ignored.html", "test/testcases/span/extension/ignored.text", "test/testcases/span/extension/nomarkdown.html", "test/testcases/span/extension/nomarkdown.text", "test/testcases/span/extension/options.html", "test/testcases/span/extension/options.text", "test/testcases/span/ial/simple.html", "test/testcases/span/ial/simple.text", "test/testcases/span/line_breaks/normal.html", "test/testcases/span/line_breaks/normal.latex", "test/testcases/span/line_breaks/normal.text", "test/testcases/span/math/itex2mml.html", "test/testcases/span/math/itex2mml.options", "test/testcases/span/math/itex2mml.text", "test/testcases/span/math/mathjaxnode.html.19", "test/testcases/span/math/mathjaxnode.options", "test/testcases/span/math/mathjaxnode.text", "test/testcases/span/math/normal.html", "test/testcases/span/math/normal.text", "test/testcases/span/math/ritex.html", "test/testcases/span/math/ritex.options", "test/testcases/span/math/ritex.text", "test/testcases/span/text_substitutions/entities.html", "test/testcases/span/text_substitutions/entities.options", "test/testcases/span/text_substitutions/entities.text", "test/testcases/span/text_substitutions/entities_as_char.html", "test/testcases/span/text_substitutions/entities_as_char.html.19", "test/testcases/span/text_substitutions/entities_as_char.options", "test/testcases/span/text_substitutions/entities_as_char.text", "test/testcases/span/text_substitutions/entities_as_input.html", "test/testcases/span/text_substitutions/entities_as_input.options", "test/testcases/span/text_substitutions/entities_as_input.text", "test/testcases/span/text_substitutions/entities_numeric.html", "test/testcases/span/text_substitutions/entities_numeric.options", "test/testcases/span/text_substitutions/entities_numeric.text", "test/testcases/span/text_substitutions/entities_symbolic.html", "test/testcases/span/text_substitutions/entities_symbolic.options", "test/testcases/span/text_substitutions/entities_symbolic.text", "test/testcases/span/text_substitutions/greaterthan.html", "test/testcases/span/text_substitutions/greaterthan.text", "test/testcases/span/text_substitutions/lowerthan.html", "test/testcases/span/text_substitutions/lowerthan.text", "test/testcases/span/text_substitutions/typography.html", "test/testcases/span/text_substitutions/typography.options", "test/testcases/span/text_substitutions/typography.text", "test/testcases_gfm/atx_header.html", "test/testcases_gfm/atx_header.text", "test/testcases_gfm/backticks_disable_highlighting.html", "test/testcases_gfm/backticks_disable_highlighting.options", "test/testcases_gfm/backticks_disable_highlighting.text", "test/testcases_gfm/backticks_syntax.html", "test/testcases_gfm/backticks_syntax.text", "test/testcases_gfm/hard_line_breaks.html", "test/testcases_gfm/hard_line_breaks.text", "test/testcases_gfm/hard_line_breaks_off.html", "test/testcases_gfm/hard_line_breaks_off.options", "test/testcases_gfm/hard_line_breaks_off.text", "test/testcases_gfm/strikethrough.html", "test/testcases_gfm/strikethrough.html.19", "test/testcases_gfm/strikethrough.text", "test/testcases_gfm/two_para_hard_line_breaks.html", "test/testcases_gfm/two_para_hard_line_breaks.text"] s.homepage = "http://kramdown.gettalong.org" s.licenses = ["MIT"] s.rdoc_options = ["--main", "lib/kramdown/document.rb"] s.require_paths = ["lib"] s.rubygems_version = "1.8.23" s.summary = "kramdown is a fast, pure-Ruby Markdown-superset converter." if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, ["~> 1.0.0"]) s.add_development_dependency(%q, ["~> 1.5"]) s.add_development_dependency(%q, ["~> 5.0"]) s.add_development_dependency(%q, ["~> 2.0"]) s.add_development_dependency(%q, ["~> 1.0"]) s.add_development_dependency(%q, ["~> 1.8"]) s.add_development_dependency(%q, ["~> 1.5.1"]) else s.add_dependency(%q, ["~> 1.0.0"]) s.add_dependency(%q, ["~> 1.5"]) s.add_dependency(%q, ["~> 5.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, ["~> 1.0"]) s.add_dependency(%q, ["~> 1.8"]) s.add_dependency(%q, ["~> 1.5.1"]) end else s.add_dependency(%q, ["~> 1.0.0"]) s.add_dependency(%q, ["~> 1.5"]) s.add_dependency(%q, ["~> 5.0"]) s.add_dependency(%q, ["~> 2.0"]) s.add_dependency(%q, ["~> 1.0"]) s.add_dependency(%q, ["~> 1.8"]) s.add_dependency(%q, ["~> 1.5.1"]) end end kramdown-1.10.0/man/0000755000175000017500000000000012672246616014036 5ustar uwabamiuwabamikramdown-1.10.0/man/man1/0000755000175000017500000000000012672246616014672 5ustar uwabamiuwabamikramdown-1.10.0/man/man1/kramdown.10000644000175000017500000002666012672246616016610 0ustar uwabamiuwabami.TH "KRAMDOWN" 1 "February 2015" .SH NAME kramdown \- a fast, pure-Ruby Markdown-superset converter .SH SYNOPSIS .B kramdown [\fIoptions\fR] [\fIFILE\fR ...] .SH DESCRIPTION kramdown is primarily used for parsing a superset of Markdown and converting it to different output formats. It supports standard Markdown (with some minor modifications) and various extensions like tables and definition lists. Due to its modular architecture it also allows other input formats than Markdown, for example, HTML or Github Flavored Markdown. If \fIFILE\fR is not specified, kramdown reads from the standard input. The result is written to the standard output. There are two sets of options that kramdown accepts: The first one includes the options that are used directly by the kramdown binary. The second set of options controls how kramdown parses and converts its input. .SH OPTIONS .TP .B \-i, \-\-input ARG Specify the input format. Available input formats: kramdown (this is the default), markdown, GFM or html. .TP .B \-o, \-\-output ARG Specify one or more output formats separated by commas: html (default), kramdown, latex, pdf or remove_html_tags. .TP .B \-v, \-\-version Show the version of kramdown. .TP .B \-h, \-\-help Show the help. .SH KRAMDOWN OPTIONS .TP .B \-\-auto-id-prefix ARG Prefix used for automatically generated header IDs This option can be used to set a prefix for the automatically generated header IDs so that there is no conflict when rendering multiple kramdown documents into one output file separately. The prefix should only contain characters that are valid in an ID! Default: '' Used by: HTML/Latex converter .TP .B \-\-[no\-]auto-id-stripping Strip all formatting from header text for automatic ID generation If this option is `true`, only the text elements of a header are used for generating the ID later (in contrast to just using the raw header text line). This option will be removed in version 2.0 because this will be the default then. Default: false Used by: kramdown parser .TP .B \-\-[no\-]auto-ids Use automatic header ID generation If this option is `true`, ID values for all headers are automatically generated if no ID is explicitly specified. Default: true Used by: HTML/Latex converter .TP .B \-\-coderay-bold-every ARG Defines how often a line number should be made bold Can either be an integer or false (to turn off bold line numbers completely). Default: 10 Used by: HTML converter .TP .B \-\-coderay-css ARG Defines how the highlighted code gets styled Possible values are :class (CSS classes are applied to the code elements, one must supply the needed CSS file) or :style (default CSS styles are directly applied to the code elements). Default: style Used by: HTML converter .TP .B \-\-coderay-default-lang ARG Sets the default language for highlighting code blocks If no language is set for a code block, the default language is used instead. The value has to be one of the languages supported by coderay or nil if no default language should be used. Default: nil Used by: HTML converter .TP .B \-\-coderay-line-number-start ARG The start value for the line numbers Default: 1 Used by: HTML converter .TP .B \-\-coderay-line-numbers ARG Defines how and if line numbers should be shown The possible values are :table, :inline or nil. If this option is nil, no line numbers are shown. Default: :inline Used by: HTML converter .TP .B \-\-coderay-tab-width ARG The tab width used in highlighted code Used by: HTML converter .TP .B \-\-coderay-wrap ARG Defines how the highlighted code should be wrapped The possible values are :span, :div or nil. Default: :div Used by: HTML converter .TP .B \-\-[no\-]enable-coderay Use coderay for syntax highlighting If this option is `true`, coderay is used by the HTML converter for syntax highlighting the content of code spans and code blocks. Default: true Used by: HTML converter .TP .B \-\-entity-output ARG Defines how entities are output The possible values are :as_input (entities are output in the same form as found in the input), :numeric (entities are output in numeric form), :symbolic (entities are output in symbolic form if possible) or :as_char (entities are output as characters if possible, only available on Ruby 1.9). Default: :as_char Used by: HTML converter, kramdown converter .TP .B \-\-footnote-backlink ARG Defines the text that should be used for the footnote backlinks The footnote backlink is just text, so any special HTML characters will be escaped. If the footnote backlint text is an empty string, no footnote backlinks will be generated. Default: '&8617;' Used by: HTML converter .TP .B \-\-footnote-nr ARG The number of the first footnote This option can be used to specify the number that is used for the first footnote. Default: 1 Used by: HTML converter .TP .B \-\-[no\-]hard-wrap Interprets line breaks literally Insert HTML `
` tags inside paragraphs where the original Markdown document had newlines (by default, Markdown ignores these newlines). Default: true Used by: GFM parser .TP .B \-\-header-offset ARG Sets the output offset for headers If this option is c (may also be negative) then a header with level n will be output as a header with level c+n. If c+n is lower than 1, level 1 will be used. If c+n is greater than 6, level 6 will be used. Default: 0 Used by: HTML converter, Kramdown converter, Latex converter .TP .B \-\-[no\-]html-to-native Convert HTML elements to native elements If this option is `true`, the parser converts HTML elements to native elements. For example, when parsing `hallo` the emphasis tag would normally be converted to an `:html` element with tag type `:em`. If `html_to_native` is `true`, then the emphasis would be converted to a native `:em` element. This is useful for converters that cannot deal with HTML elements. Default: false Used by: kramdown parser .TP .B \-\-latex-headers ARG Defines the LaTeX commands for different header levels The commands for the header levels one to six can be specified by separating them with commas. Default: section,subsection,subsubsection,paragraph,subparagraph,subparagraph Used by: Latex converter .TP .B \-\-line-width ARG Defines the line width to be used when outputting a document Default: 72 Used by: kramdown converter .TP .B \-\-link-defs ARG Pre-defines link definitions This option can be used to pre-define link definitions. The value needs to be a Hash where the keys are the link identifiers and the values are two element Arrays with the link URL and the link title. If the value is a String, it has to contain a valid YAML hash and the hash has to follow the above guidelines. Default: {} Used by: kramdown parser .TP .B \-\-math-engine ARG Set the math engine Specifies the math engine that should be used for converting math blocks/spans. If this option is set to +nil+, no math engine is used and the math blocks/spans are output as is. Options for the selected math engine can be set with the math_engine_opts configuration option. Default: mathjax Used by: HTML converter .TP .B \-\-math-engine-opts ARG Set the math engine options Specifies options for the math engine set via the math_engine configuration option. The value needs to be a hash with key-value pairs that are understood by the used math engine. Default: {} Used by: HTML converter .TP .B \-\-[no\-]parse-block-html Process kramdown syntax in block HTML tags If this option is `true`, the kramdown parser processes the content of block HTML tags as text containing block-level elements. Since this is not wanted normally, the default is `false`. It is normally better to selectively enable kramdown processing via the markdown attribute. Default: false Used by: kramdown parser .TP .B \-\-[no\-]parse-span-html Process kramdown syntax in span HTML tags If this option is `true`, the kramdown parser processes the content of span HTML tags as text containing span-level elements. Default: true Used by: kramdown parser .TP .B \-\-[no\-]remove-block-html-tags Remove block HTML tags If this option is `true`, the RemoveHtmlTags converter removes block HTML tags. Default: true Used by: RemoveHtmlTags converter .TP .B \-\-[no\-]remove-span-html-tags Remove span HTML tags If this option is `true`, the RemoveHtmlTags converter removes span HTML tags. Default: false Used by: RemoveHtmlTags converter .TP .B \-\-smart-quotes ARG Defines the HTML entity names or code points for smart quote output The entities identified by entity name or code point that should be used for, in order, a left single quote, a right single quote, a left double and a right double quote are specified by separating them with commas. Default: lsquo,rsquo,ldquo,rdquo Used by: HTML/Latex converter .TP .B \-\-syntax-highlighter ARG Set the syntax highlighter Specifies the syntax highlighter that should be used for highlighting code blocks and spans. If this option is set to +nil+, no syntax highlighting is done. Options for the syntax highlighter can be set with the syntax_highlighter_opts configuration option. Default: coderay Used by: HTML/Latex converter .TP .B \-\-syntax-highlighter-opts ARG Set the syntax highlighter options Specifies options for the syntax highlighter set via the syntax_highlighter configuration option. The value needs to be a hash with key-value pairs that are understood by the used syntax highlighter. Default: {} Used by: HTML/Latex converter .TP .B \-\-template ARG The name of an ERB template file that should be used to wrap the output or the ERB template itself. This is used to wrap the output in an environment so that the output can be used as a stand-alone document. For example, an HTML template would provide the needed header and body tags so that the whole output is a valid HTML file. If no template is specified, the output will be just the converted text. When resolving the template file, the given template name is used first. If such a file is not found, the converter extension (the same as the converter name) is appended. If the file still cannot be found, the templates name is interpreted as a template name that is provided by kramdown (without the converter extension). If the file is still not found, the template name is checked if it starts with 'string://' and if it does, this prefix is removed and the rest is used as template content. kramdown provides a default template named 'document' for each converter. Default: '' Used by: all converters .TP .B \-\-toc-levels ARG Defines the levels that are used for the table of contents The individual levels can be specified by separating them with commas (e.g. 1,2,3) or by using the range syntax (e.g. 1..3). Only the specified levels are used for the table of contents. Default: 1..6 Used by: HTML/Latex converter .TP .B \-\-[no\-]transliterated-header-ids Transliterate the header text before generating the ID Only ASCII characters are used in headers IDs. This is not good for languages with many non-ASCII characters. By enabling this option the header text is transliterated to ASCII as good as possible so that the resulting header ID is more useful. The stringex library needs to be installed for this feature to work! Default: false Used by: HTML/Latex converter .SH EXIT STATUS The exit status is 0 if no error happened. Otherwise it is 1. .SH SEE ALSO The kramdown website, http://kramdown.gettalong.org/ for more information, especially on the supported input syntax. .SH AUTHOR kramdown was written by Thomas Leitner . .PP This manual page was written by Thomas Leitner . kramdown-1.10.0/VERSION0000644000175000017500000000000712672246616014330 0ustar uwabamiuwabami1.10.0 kramdown-1.10.0/bin/0000755000175000017500000000000012672246616014033 5ustar uwabamiuwabamikramdown-1.10.0/bin/kramdown0000755000175000017500000000351712672246616015611 0ustar uwabamiuwabami#!/usr/bin/env ruby # -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'optparse' require 'kramdown' options = {} format = ['html'] OptionParser.new do |opts| opts.banner = "Usage: kramdown [options] [FILE FILE ...]" opts.summary_indent = ' '*4 opts.separator "" opts.separator "Command line options:" opts.separator "" opts.on("-i", "--input ARG", "Specify the input format: kramdown (default), html, GFM or markdown") {|v| options[:input] = v} opts.on("-o", "--output ARG", Array, "Specify one or more output formats separated by commas: html (default), kramdown, latex, pdf or remove_html_tags") {|v| format = v} opts.on("-v", "--version", "Show the version of kramdown") do puts Kramdown::VERSION exit end opts.on("-h", "--help", "Show the help") do puts opts.summarize('', 5, 72) exit end opts.separator "" opts.separator "kramdown options:" opts.separator "" Kramdown::Options.definitions.sort.each do |n, definition| no = n.to_s.tr('_', '-') if definition.type == Kramdown::Options::Boolean opts.on("--[no-]#{no}") {|v| options[n] = Kramdown::Options.parse(n, v)} else type = definition.type type = String if type == Symbol || type == Object opts.on("--#{no} ARG", type) {|v| options[n] = Kramdown::Options.parse(n, v)} end definition.desc.split(/\n/).each do |line| opts.separator opts.summary_indent + ' '*6 + line end opts.separator '' end end.parse! begin doc = Kramdown::Document.new(ARGF.read, options) result = '' format.each {|f| result = doc.send("to_#{f}")} puts result doc.warnings.each {|warn| $stderr.puts "Warning: #{warn}"} rescue Kramdown::Error => e $stderr.puts "Error: #{e.message}" exit(1) end kramdown-1.10.0/lib/0000755000175000017500000000000012672246616014031 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown.rb0000644000175000017500000000030012672246616016171 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/document' kramdown-1.10.0/lib/kramdown/0000755000175000017500000000000012672246616015653 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/error.rb0000644000175000017500000000060412672246616017331 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown # This error is raised when an error condition is encountered. # # *Note* that this error is only raised by the support framework for the parsers and converters. class Error < RuntimeError; end end kramdown-1.10.0/lib/kramdown/converter.rb0000644000175000017500000000456712672246616020223 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/utils' module Kramdown # This module contains all available converters, i.e. classes that take a root Element and convert # it to a specific output format. The result is normally a string. For example, the # Converter::Html module converts an element tree into valid HTML. # # Converters use the Base class for common functionality (like applying a template to the output) # \- see its API documentation for how to create a custom converter class. module Converter autoload :Base, 'kramdown/converter/base' autoload :Html, 'kramdown/converter/html' autoload :Latex, 'kramdown/converter/latex' autoload :Kramdown, 'kramdown/converter/kramdown' autoload :Toc, 'kramdown/converter/toc' autoload :RemoveHtmlTags, 'kramdown/converter/remove_html_tags' autoload :Pdf, 'kramdown/converter/pdf' autoload :HashAST, 'kramdown/converter/hash_ast' extend ::Kramdown::Utils::Configurable configurable(:syntax_highlighter) ['Minted', "Coderay", "Rouge"].each do |klass_name| kn_down = klass_name.downcase.intern add_syntax_highlighter(kn_down) do |converter, text, lang, type, opts| require "kramdown/converter/syntax_highlighter/#{kn_down}" klass = ::Kramdown::Utils.deep_const_get("::Kramdown::Converter::SyntaxHighlighter::#{klass_name}") if !klass.const_defined?(:AVAILABLE) || klass::AVAILABLE add_syntax_highlighter(kn_down, klass) else add_syntax_highlighter(kn_down) {|*args| nil} end syntax_highlighter(kn_down).call(converter, text, lang, type, opts) end end configurable(:math_engine) ['Mathjax', "MathjaxNode", "Ritex", "Itex2MML"].each do |klass_name| kn_down = klass_name.downcase.intern add_math_engine(kn_down) do |converter, el, opts| require "kramdown/converter/math_engine/#{kn_down}" klass = ::Kramdown::Utils.deep_const_get("::Kramdown::Converter::MathEngine::#{klass_name}") if !klass.const_defined?(:AVAILABLE) || klass::AVAILABLE add_math_engine(kn_down, klass) else add_math_engine(kn_down) {|*args| nil} end math_engine(kn_down).call(converter, el, opts) end end end end kramdown-1.10.0/lib/kramdown/utils.rb0000644000175000017500000000275112672246616017345 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown # == \Utils Module # # This module contains utility class/modules/methods that can be used by both parsers and # converters. module Utils autoload :Entities, 'kramdown/utils/entities' autoload :Html, 'kramdown/utils/html' autoload :OrderedHash, 'kramdown/utils/ordered_hash' autoload :Unidecoder, 'kramdown/utils/unidecoder' autoload :StringScanner, 'kramdown/utils/string_scanner' autoload :Configurable, 'kramdown/utils/configurable' # Treat +name+ as if it were snake cased (e.g. snake_case) and camelize it (e.g. SnakeCase). def self.camelize(name) name.split('_').inject('') {|s,x| s << x[0..0].upcase << x[1..-1] } end # Treat +name+ as if it were camelized (e.g. CamelizedName) and snake-case it (e.g. camelized_name). def self.snake_case(name) name = name.dup name.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2') name.gsub!(/([a-z])([A-Z])/,'\1_\2') name.downcase! name end if RUBY_VERSION < '2.0' # Resolve the recursive constant +str+. def self.deep_const_get(str) names = str.split(/::/) names.shift if names.first.empty? names.inject(::Object) {|mod, s| mod.const_get(s)} end else def self.deep_const_get(str) ::Object.const_get(str) end end end end kramdown-1.10.0/lib/kramdown/parser.rb0000644000175000017500000000134012672246616017472 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown # This module contains all available parsers. A parser takes an input string and converts the # string to an element tree. # # New parsers should be derived from the Base class which provides common functionality - see its # API documentation for how to create a custom converter class. module Parser autoload :Base, 'kramdown/parser/base' autoload :Kramdown, 'kramdown/parser/kramdown' autoload :Html, 'kramdown/parser/html' autoload :Markdown, 'kramdown/parser/markdown' autoload :GFM, 'kramdown/parser/gfm' end end kramdown-1.10.0/lib/kramdown/options.rb0000644000175000017500000004445712672246616017711 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'yaml' module Kramdown # This module defines all options that are used by parsers and/or converters as well as providing # methods to deal with the options. module Options # Helper class introducing a boolean type for specifying boolean values (+true+ and +false+) as # option types. class Boolean # Return +true+ if +other+ is either +true+ or +false+ def self.===(other) FalseClass === other || TrueClass === other end end # ---------------------------- # :section: Option definitions # # This sections describes the methods that can be used on the Options module. # ---------------------------- # Struct class for storing the definition of an option. Definition = Struct.new(:name, :type, :default, :desc, :validator) # Allowed option types. ALLOWED_TYPES = [String, Integer, Float, Symbol, Boolean, Object] @options = {} # Define a new option called +name+ (a Symbol) with the given +type+ (String, Integer, Float, # Symbol, Boolean, Object), default value +default+ and the description +desc+. If a block is # specified, it should validate the value and either raise an error or return a valid value. # # The type 'Object' should only be used for complex types for which none of the other types # suffices. A block needs to be specified when using type 'Object' and it has to cope with # a value given as string and as the opaque type. def self.define(name, type, default, desc, &block) name = name.to_sym raise ArgumentError, "Option name #{name} is already used" if @options.has_key?(name) raise ArgumentError, "Invalid option type #{type} specified" if !ALLOWED_TYPES.include?(type) raise ArgumentError, "Invalid type for default value" if !(type === default) && !default.nil? raise ArgumentError, "Missing validator block" if type == Object && block.nil? @options[name] = Definition.new(name, type, default, desc, block) end # Return all option definitions. def self.definitions @options end # Return +true+ if an option called +name+ is defined. def self.defined?(name) @options.has_key?(name.to_sym) end # Return a Hash with the default values for all options. def self.defaults temp = {} @options.each {|n, o| temp[o.name] = o.default} temp end # Merge the #defaults Hash with the *parsed* options from the given Hash, i.e. only valid option # names are considered and their value is run through the #parse method. def self.merge(hash) temp = defaults hash.each do |k,v| k = k.to_sym @options.has_key?(k) ? temp[k] = parse(k, v) : temp[k] = v end temp end # Parse the given value +data+ as if it was a value for the option +name+ and return the parsed # value with the correct type. # # If +data+ already has the correct type, it is just returned. Otherwise it is converted to a # String and then to the correct type. def self.parse(name, data) name = name.to_sym raise ArgumentError, "No option named #{name} defined" if !@options.has_key?(name) if !(@options[name].type === data) data = data.to_s data = if @options[name].type == String data elsif @options[name].type == Integer Integer(data) rescue raise Kramdown::Error, "Invalid integer value for option '#{name}': '#{data}'" elsif @options[name].type == Float Float(data) rescue raise Kramdown::Error, "Invalid float value for option '#{name}': '#{data}'" elsif @options[name].type == Symbol str_to_sym(data) elsif @options[name].type == Boolean data.downcase.strip != 'false' && !data.empty? end end data = @options[name].validator[data] if @options[name].validator data end # Converts the given String +data+ into a Symbol or +nil+ with the # following provisions: # # - A leading colon is stripped from the string. # - An empty value or a value equal to "nil" results in +nil+. def self.str_to_sym(data) data = data.strip data = data[1..-1] if data[0] == ?: (data.empty? || data == 'nil' ? nil : data.to_sym) end # ---------------------------- # :section: Option Validators # # This sections contains all pre-defined option validators. # ---------------------------- # Ensures that the option value +val+ for the option called +name+ is a valid array. The # parameter +val+ can be # # - a comma separated string which is split into an array of values # - or an array. # # Additionally, the array is checked for the correct size. def self.simple_array_validator(val, name, size) if String === val val = val.split(/,/) elsif !(Array === val) raise Kramdown::Error, "Invalid type #{val.class} for option #{name}" end if val.size != size raise Kramdown::Error, "Option #{name} needs exactly #{size} values" end val end # Ensures that the option value +val+ for the option called +name+ is a valid hash. The # parameter +val+ can be # # - a hash in YAML format # - or a Ruby Hash object. def self.simple_hash_validator(val, name) if String === val begin val = YAML.load(val) rescue RuntimeError, ArgumentError, SyntaxError raise Kramdown::Error, "Invalid YAML value for option #{name}" end end raise Kramdown::Error, "Invalid type #{val.class} for option #{name}" if !(Hash === val) val end # ---------------------------- # :section: Option Definitions # # This sections contains all option definitions that are used by the included # parsers/converters. # ---------------------------- define(:template, String, '', <hallo
` the emphasis tag would normally be converted to an `:html` element with tag type `:em`. If `html_to_native` is `true`, then the emphasis would be converted to a native `:em` element. This is useful for converters that cannot deal with HTML elements. Default: false Used by: kramdown parser EOF define(:link_defs, Object, {}, < 2 || v.size < 1 raise Kramdown::Error, "Invalid structure for hash value of option #{name}" end v << nil if v.size == 1 end val end define(:footnote_nr, Integer, 1, <` tags inside paragraphs where the original Markdown document had newlines (by default, Markdown ignores these newlines). Default: true Used by: GFM parser EOF define(:syntax_highlighter, Symbol, :coderay, < # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown # The kramdown version. VERSION = '1.10.0' end kramdown-1.10.0/lib/kramdown/document.rb0000644000175000017500000001165512672246616020026 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # # = kramdown # # kramdown is fast, pure Ruby Markdown superset converter, using a strict syntax definition and # supporting several common extensions. # # The kramdown library is mainly written to support the kramdown-to-HTML conversion chain. However, # due to its flexibility it supports other input and output formats as well. Here is a list of the # supported formats: # # * input formats: kramdown (a Markdown superset), Markdown, GFM, HTML # * output formats: HTML, kramdown, LaTeX (and therefore PDF), PDF via Prawn # # All the documentation on the available input and output formats is available at # http://kramdown.gettalong.org. # # == Usage # # kramdown has a simple API, so using kramdown is as easy as # # require 'kramdown' # # Kramdown::Document.new(text).to_html # # For detailed information have a look at the *\Kramdown::Document* class. # # == License # # MIT - see the COPYING file. require 'kramdown/compatibility' require 'kramdown/version' require 'kramdown/element' require 'kramdown/error' require 'kramdown/parser' require 'kramdown/converter' require 'kramdown/options' require 'kramdown/utils' module Kramdown # Return the data directory for kramdown. def self.data_dir unless defined?(@@data_dir) require 'rbconfig' @@data_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data', 'kramdown')) @@data_dir = File.expand_path(File.join(Config::CONFIG["datadir"], "kramdown")) if !File.exists?(@@data_dir) raise "kramdown data directory not found! This is a bug, please report it!" unless File.directory?(@@data_dir) end @@data_dir end # The main interface to kramdown. # # This class provides a one-stop-shop for using kramdown to convert text into various output # formats. Use it like this: # # require 'kramdown' # doc = Kramdown::Document.new('This *is* some kramdown text') # puts doc.to_html # # The #to_html method is a shortcut for using the Converter::Html class. See #method_missing for # more information. # # The second argument to the ::new method is an options hash for customizing the behaviour of the # used parser and the converter. See ::new for more information! class Document # The root Element of the element tree. It is immediately available after the ::new method has # been called. attr_accessor :root # The options hash which holds the options for parsing/converting the Kramdown document. attr_reader :options # An array of warning messages. It is filled with warnings during the parsing phase (i.e. in # ::new) and the conversion phase. attr_reader :warnings # Create a new Kramdown document from the string +source+ and use the provided +options+. The # options that can be used are defined in the Options module. # # The special options key :input can be used to select the parser that should parse the # +source+. It has to be the name of a class in the Kramdown::Parser module. For example, to # select the kramdown parser, one would set the :input key to +Kramdown+. If this key is not # set, it defaults to +Kramdown+. # # The +source+ is immediately parsed by the selected parser so that the root element is # immediately available and the output can be generated. def initialize(source, options = {}) @options = Options.merge(options).freeze parser = (@options[:input] || 'kramdown').to_s parser = parser[0..0].upcase + parser[1..-1] try_require('parser', parser) if Parser.const_defined?(parser) @root, @warnings = Parser.const_get(parser).parse(source, @options) else raise Kramdown::Error.new("kramdown has no parser to handle the specified input format: #{@options[:input]}") end end # Check if a method is invoked that begins with +to_+ and if so, try to instantiate a converter # class (i.e. a class in the Kramdown::Converter module) and use it for converting the document. # # For example, +to_html+ would instantiate the Kramdown::Converter::Html class. def method_missing(id, *attr, &block) if id.to_s =~ /^to_(\w+)$/ && (name = Utils.camelize($1)) && try_require('converter', name) && Converter.const_defined?(name) output, warnings = Converter.const_get(name).convert(@root, @options) @warnings.concat(warnings) output else super end end def inspect #:nodoc: "" end # Try requiring a parser or converter class and don't raise an error if the file is not found. def try_require(type, name) require("kramdown/#{type}/#{Utils.snake_case(name)}") true rescue LoadError true end protected :try_require end end kramdown-1.10.0/lib/kramdown/utils/0000755000175000017500000000000012672246616017013 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/utils/entities.rb0000644000175000017500000002765112672246616021177 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Utils # Provides convenience methods for handling named and numeric entities. module Entities # Represents an entity that has a +code_point+ and +name+. class Entity < Struct.new(:code_point, :name) # Return the UTF8 representation of the entity. def char [code_point].pack('U*') rescue nil end end # Array of arrays. Each sub-array specifies a code point and the associated name. # # This table is not used directly -- Entity objects are automatically created from it and put # into a Hash map when this file is loaded. ENTITY_TABLE = [ [913, 'Alpha'], [914, 'Beta'], [915, 'Gamma'], [916, 'Delta'], [917, 'Epsilon'], [918, 'Zeta'], [919, 'Eta'], [920, 'Theta'], [921, 'Iota'], [922, 'Kappa'], [923, 'Lambda'], [924, 'Mu'], [925, 'Nu'], [926, 'Xi'], [927, 'Omicron'], [928, 'Pi'], [929, 'Rho'], [931, 'Sigma'], [932, 'Tau'], [933, 'Upsilon'], [934, 'Phi'], [935, 'Chi'], [936, 'Psi'], [937, 'Omega'], [945, 'alpha'], [946, 'beta'], [947, 'gamma'], [948, 'delta'], [949, 'epsilon'], [950, 'zeta'], [951, 'eta'], [952, 'theta'], [953, 'iota'], [954, 'kappa'], [955, 'lambda'], [956, 'mu'], [957, 'nu'], [958, 'xi'], [959, 'omicron'], [960, 'pi'], [961, 'rho'], [963, 'sigma'], [964, 'tau'], [965, 'upsilon'], [966, 'phi'], [967, 'chi'], [968, 'psi'], [969, 'omega'], [962, 'sigmaf'], [977, 'thetasym'], [978, 'upsih'], [982, 'piv'], [8204, 'zwnj'], [8205, 'zwj'], [8206, 'lrm'], [8207, 'rlm'], [8230, 'hellip'], [8242, 'prime'], [8243, 'Prime'], [8254, 'oline'], [8260, 'frasl'], [8472, 'weierp'], [8465, 'image'], [8476, 'real'], [8501, 'alefsym'], [8226, 'bull'], [8482, 'trade'], [8592, 'larr'], [8594, 'rarr'], [8593, 'uarr'], [8595, 'darr'], [8596, 'harr'], [8629, 'crarr'], [8657, 'uArr'], [8659, 'dArr'], [8656, 'lArr'], [8658, 'rArr'], [8660, 'hArr'], [8704, 'forall'], [8706, 'part'], [8707, 'exist'], [8709, 'empty'], [8711, 'nabla'], [8712, 'isin'], [8715, 'ni'], [8713, 'notin'], [8721, 'sum'], [8719, 'prod'], [8722, 'minus'], [8727, 'lowast'], [8730, 'radic'], [8733, 'prop'], [8734, 'infin'], [8736, 'ang'], [8743, 'and'], [8744, 'or'], [8745, 'cup'], [8746, 'cap'], [8747, 'int'], [8756, 'there4'], [8764, 'sim'], [8776, 'asymp'], [8773, 'cong'], [8800, 'ne'], [8801, 'equiv'], [8804, 'le'], [8805, 'ge'], [8834, 'sub'], [8835, 'sup'], [8838, 'sube'], [8839, 'supe'], [8836, 'nsub'], [8853, 'oplus'], [8855, 'otimes'], [8869, 'perp'], [8901, 'sdot'], [8942, 'vellip'], [8968, 'rceil'], [8969, 'lceil'], [8970, 'lfloor'], [8971, 'rfloor'], [9001, 'rang'], [9002, 'lang'], [9674, 'loz'], [9824, 'spades'], [9827, 'clubs'], [9829, 'hearts'], [9830, 'diams'], [38, 'amp'], [34, 'quot'], [39, 'apos'], [169, 'copy'], [60, 'lt'], [62, 'gt'], [338, 'OElig'], [339, 'oelig'], [352, 'Scaron'], [353, 'scaron'], [376, 'Yuml'], [710, 'circ'], [732, 'tilde'], [8211, 'ndash'], [8212, 'mdash'], [8216, 'lsquo'], [8217, 'rsquo'], [8220, 'ldquo'], [8221, 'rdquo'], [8224, 'dagger'], [8225, 'Dagger'], [8240, 'permil'], [8364, 'euro'], [8249, 'lsaquo'], [8250, 'rsaquo'], [160, 'nbsp'], [161, 'iexcl'], [163, 'pound'], [164, 'curren'], [165, 'yen'], [166, 'brvbar'], [167, 'sect'], [168, 'uml'], [171, 'laquo'], [187, 'raquo'], [174, 'reg'], [170, 'ordf'], [172, 'not'], [173, 'shy'], [175, 'macr'], [176, 'deg'], [177, 'plusmn'], [180, 'acute'], [181, 'micro'], [182, 'para'], [183, 'middot'], [184, 'cedil'], [186, 'ordm'], [162, 'cent'], [185, 'sup1'], [178, 'sup2'], [179, 'sup3'], [189, 'frac12'], [188, 'frac14'], [190, 'frac34'], [191, 'iquest'], [192, 'Agrave'], [193, 'Aacute'], [194, 'Acirc'], [195, 'Atilde'], [196, 'Auml'], [197, 'Aring'], [198, 'AElig'], [199, 'Ccedil'], [200, 'Egrave'], [201, 'Eacute'], [202, 'Ecirc'], [203, 'Euml'], [204, 'Igrave'], [205, 'Iacute'], [206, 'Icirc'], [207, 'Iuml'], [208, 'ETH'], [209, 'Ntilde'], [210, 'Ograve'], [211, 'Oacute'], [212, 'Ocirc'], [213, 'Otilde'], [214, 'Ouml'], [215, 'times'], [216, 'Oslash'], [217, 'Ugrave'], [218, 'Uacute'], [219, 'Ucirc'], [220, 'Uuml'], [221, 'Yacute'], [222, 'THORN'], [223, 'szlig'], [224, 'agrave'], [225, 'aacute'], [226, 'acirc'], [227, 'atilde'], [228, 'auml'], [229, 'aring'], [230, 'aelig'], [231, 'ccedil'], [232, 'egrave'], [233, 'eacute'], [234, 'ecirc'], [235, 'euml'], [236, 'igrave'], [237, 'iacute'], [238, 'icirc'], [239, 'iuml'], [240, 'eth'], [241, 'ntilde'], [242, 'ograve'], [243, 'oacute'], [244, 'ocirc'], [245, 'otilde'], [246, 'ouml'], [247, 'divide'], [248, 'oslash'], [249, 'ugrave'], [250, 'uacute'], [251, 'ucirc'], [252, 'uuml'], [253, 'yacute'], [254, 'thorn'], [255, 'yuml'], [8218, 'sbquo'], [402, 'fnof'], [8222, 'bdquo'], [128, 8364], [130, 8218], [131, 402], [132, 8222], [133, 8230], [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249], [140, 338], [142, 381], [145, 8216], [146, 8217], [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732], [153, 8482], [154, 353], [155, 8250], [156, 339], [158, 382], [159, 376], [8194, 'ensp'], [8195, 'emsp'], [8201, 'thinsp'], ] # Contains the mapping of code point (or name) to the actual Entity object. ENTITY_MAP = Hash.new do |h,k| if k.kind_of?(Integer) h[k] = Entity.new(k, nil) else raise Kramdown::Error, "Can't handle generic non-integer character reference '#{k}'" end end ENTITY_TABLE.each do |code_point, data| if data.kind_of?(String) ENTITY_MAP[code_point] = ENTITY_MAP[data] = Entity.new(code_point, data) else ENTITY_MAP[code_point] = ENTITY_MAP[data] end end # Return the entity for the given code point or name +point_or_name+. def entity(point_or_name) ENTITY_MAP[point_or_name] end module_function :entity end end end kramdown-1.10.0/lib/kramdown/utils/unidecoder.rb0000644000175000017500000000231012672246616021455 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # # This file is based on code originally from the Stringex library and needs the data files from # Stringex to work correctly. module Kramdown module Utils # Provides the ability to tranliterate Unicode strings into plain ASCII ones. module Unidecoder gem 'stringex' if defined?(Gem) path = $:.find {|dir| File.directory?(File.join(File.expand_path(dir), "stringex", "unidecoder_data"))} if RUBY_VERSION <= '1.8.6' || !path def self.decode(string) string end else CODEPOINTS = Hash.new do |h, k| h[k] = YAML.load_file(File.join(path, "stringex", "unidecoder_data", "#{k}.yml")) end # Transliterate string from Unicode into ASCII. def self.decode(string) string.gsub(/[^\x00-\x7f]/u) do |codepoint| begin unpacked = codepoint.unpack("U")[0] CODEPOINTS["x%02x" % (unpacked >> 8)][unpacked & 255] rescue "?" end end end end end end end kramdown-1.10.0/lib/kramdown/utils/ordered_hash.rb0000644000175000017500000000425612672246616021776 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Utils if RUBY_VERSION < '1.9' # A partial hash implementation which preserves the insertion order of the keys. # # *Note* that this class is only used on Ruby 1.8 since the built-in Hash on Ruby 1.9 # automatically preserves the insertion order. However, to remain compatibility only the # methods defined in this class may be used when working with OrderedHash on Ruby 1.9. class OrderedHash include Enumerable # Initialize the OrderedHash object. def initialize @data = {} @order = [] end # Iterate over the stored keys in insertion order. def each @order.each {|k| yield(k, @data[k])} end # Return the value for the +key+. def [](key) @data[key] end # Return +true+ if the hash contains the key. def has_key?(key) @data.has_key?(key) end # Return +true+ if the hash contains no keys. def empty? @data.empty? end # Set the value for the +key+ to +val+. def []=(key, val) @order << key if !@data.has_key?(key) @data[key] = val end # Delete the +key+. def delete(key) @order.delete(key) @data.delete(key) end def merge!(other) other.each {|k,v| self[k] = v} self end def dup #:nodoc: new_object = super new_object.instance_variable_set(:@data, @data.dup) new_object.instance_variable_set(:@order, @order.dup) new_object end def ==(other) #:nodoc: return false unless other.kind_of?(self.class) @data == other.instance_variable_get(:@data) && @order == other.instance_variable_get(:@order) end def inspect #:nodoc: "{" + map {|k,v| "#{k.inspect}=>#{v.inspect}"}.join(" ") + "}" end end else OrderedHash = Hash end end end kramdown-1.10.0/lib/kramdown/utils/html.rb0000644000175000017500000000520712672246616020310 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'rexml/parsers/baseparser' module Kramdown module Utils # Provides convenience methods for HTML related tasks. # # *Note* that this module has to be mixed into a class that has a @root (containing an element # of type :root) and an @options (containing an options hash) instance variable so that some of # the methods can work correctly. module Html # Convert the entity +e+ to a string. The optional parameter +original+ may contain the # original representation of the entity. # # This method uses the option +entity_output+ to determine the output form for the entity. def entity_to_str(e, original = nil) entity_output = @options[:entity_output] if e.char.respond_to?(:encoding) && entity_output == :as_char && (c = e.char.encode(@root.options[:encoding]) rescue nil) && ((c = e.char) == '"' || !ESCAPE_MAP.has_key?(c)) c elsif (entity_output == :as_input || entity_output == :as_char) && original original elsif (entity_output == :symbolic || ESCAPE_MAP.has_key?(e.char)) && !e.name.nil? "&#{e.name};" else # default to :numeric "&##{e.code_point};" end end # Return the HTML representation of the attributes +attr+. def html_attributes(attr) attr.map {|k,v| v.nil? || (k == 'id' && v.strip.empty?) ? '' : " #{k}=\"#{escape_html(v.to_s, :attribute)}\"" }.join('') end # :stopdoc: ESCAPE_MAP = { '<' => '<', '>' => '>', '&' => '&', '"' => '"' } ESCAPE_ALL_RE = /<|>|&/ ESCAPE_TEXT_RE = Regexp.union(REXML::Parsers::BaseParser::REFERENCE_RE, /<|>|&/) ESCAPE_ATTRIBUTE_RE = Regexp.union(REXML::Parsers::BaseParser::REFERENCE_RE, /<|>|&|"/) ESCAPE_RE_FROM_TYPE = { :all => ESCAPE_ALL_RE, :text => ESCAPE_TEXT_RE, :attribute => ESCAPE_ATTRIBUTE_RE } # :startdoc: # Escape the special HTML characters in the string +str+. The parameter +type+ specifies what # is escaped: :all - all special HTML characters except the quotation mark as well as # entities, :text - all special HTML characters except the quotation mark but no entities and # :attribute - all special HTML characters including the quotation mark but no entities. def escape_html(str, type = :all) str.gsub(ESCAPE_RE_FROM_TYPE[type]) {|m| ESCAPE_MAP[m] || m} end end end end kramdown-1.10.0/lib/kramdown/utils/configurable.rb0000644000175000017500000000262212672246616022002 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Utils # Methods for registering configurable extensions. module Configurable # Create a new configurable extension called +name+. # # Three methods will be defined on the calling object which allow to use this configurable # extension: # # configurables:: Returns a hash of hashes that is used to store all configurables of the # object. # # (ext_name):: Return the configured extension +ext_name+. # # add_(ext_name, data=nil, &block):: Define an extension +ext_name+ by specifying either # the data as argument or by using a block. def configurable(name) singleton_class = (class << self; self; end) singleton_class.send(:define_method, :configurables) do @_configurables ||= Hash.new {|h, k| h[k] = {}} end unless respond_to?(:configurables) singleton_class.send(:define_method, name) do |data| configurables[name][data] end singleton_class.send(:define_method, "add_#{name}".intern) do |data, *args, &block| configurables[name][data] = args.first || block end end end end end kramdown-1.10.0/lib/kramdown/utils/string_scanner.rb0000644000175000017500000000513612672246616022364 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'strscan' module Kramdown module Utils # This patched StringScanner adds line number information for current scan position and a # start_line_number override for nested StringScanners. class StringScanner < ::StringScanner # The start line number. Used for nested StringScanners that scan a sub-string of the source # document. The kramdown parser uses this, e.g., for span level parsers. attr_reader :start_line_number # Takes the start line number as optional second argument. # # Note: The original second argument is no longer used so this should be safe. def initialize(string, start_line_number = 1) super(string) @start_line_number = start_line_number || 1 @previous_pos = 0 @previous_line_number = @start_line_number end # Sets the byte position of the scan pointer. # # Note: This also resets some internal variables, so always use pos= when setting the position # and don't use any other method for that! def pos=(pos) if self.pos > pos @previous_line_number = @start_line_number @previous_pos = 0 end super end # Return information needed to revert the byte position of the string scanner in a performant # way. # # The returned data can be fed to #revert_pos to revert the position to the saved one. # # Note: Just saving #pos won't be enough. def save_pos [pos, @previous_pos, @previous_line_number] end # Revert the position to one saved by #save_pos. def revert_pos(data) self.pos = data[0] @previous_pos, @previous_line_number = data[1], data[2] end # Returns the line number for current charpos. # # NOTE: Requires that all line endings are normalized to '\n' # # NOTE: Normally we'd have to add one to the count of newlines to get the correct line number. # However we add the one indirectly by using a one-based start_line_number. def current_line_number # Not using string[@previous_pos..best_pos].count('\n') because it is slower strscan = ::StringScanner.new(string) strscan.pos = @previous_pos old_pos = pos + 1 @previous_line_number += 1 while strscan.skip_until(/\n/) && strscan.pos <= old_pos @previous_pos = (eos? ? pos : pos + 1) @previous_line_number end end end end kramdown-1.10.0/lib/kramdown/converter/0000755000175000017500000000000012672246616017662 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/converter/kramdown.rb0000644000175000017500000003372712672246616022045 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/converter' require 'kramdown/utils' module Kramdown module Converter # Converts an element tree to the kramdown format. class Kramdown < Base # :stopdoc: include ::Kramdown::Utils::Html def initialize(root, options) super @linkrefs = [] @footnotes = [] @abbrevs = [] @stack = [] end def convert(el, opts = {:indent => 0}) res = send("convert_#{el.type}", el, opts) if ![:html_element, :li, :dd, :td].include?(el.type) && (ial = ial_for_element(el)) res << ial res << "\n\n" if Element.category(el) == :block elsif [:ul, :dl, :ol, :codeblock].include?(el.type) && opts[:next] && ([el.type, :codeblock].include?(opts[:next].type) || (opts[:next].type == :blank && opts[:nnext] && [el.type, :codeblock].include?(opts[:nnext].type))) res << "^\n\n" elsif Element.category(el) == :block && ![:li, :dd, :dt, :td, :th, :tr, :thead, :tbody, :tfoot, :blank].include?(el.type) && (el.type != :html_element || @stack.last.type != :html_element) && (el.type != :p || !el.options[:transparent]) res << "\n" end res end def inner(el, opts = {:indent => 0}) @stack.push(el) result = '' el.children.each_with_index do |inner_el, index| options = opts.dup options[:index] = index options[:prev] = (index == 0 ? nil : el.children[index-1]) options[:pprev] = (index <= 1 ? nil : el.children[index-2]) options[:next] = (index == el.children.length - 1 ? nil : el.children[index+1]) options[:nnext] = (index >= el.children.length - 2 ? nil : el.children[index+2]) result << convert(inner_el, options) end @stack.pop result end def convert_blank(el, opts) "" end ESCAPED_CHAR_RE = /(\$\$|[\\*_`\[\]\{"'|])|^[ ]{0,3}(:)/ def convert_text(el, opts) if opts[:raw_text] el.value else el.value.gsub(/\A\n/) do opts[:prev] && opts[:prev].type == :br ? '' : "\n" end.gsub(/\s+/, ' ').gsub(ESCAPED_CHAR_RE) { "\\#{$1 || $2}" } end end def convert_p(el, opts) w = @options[:line_width] - opts[:indent].to_s.to_i first, second, *rest = inner(el, opts).strip.gsub(/(.{1,#{w}})( +|$\n?)/, "\\1\n").split(/\n/) first.gsub!(/^(?:(#|>)|(\d+)\.|([+-]\s))/) { $1 || $3 ? "\\#{$1 || $3}" : "#{$2}\\."} if first second.gsub!(/^([=-]+\s*?)$/, "\\\1") if second res = [first, second, *rest].compact.join("\n") + "\n" if el.children.length == 1 && el.children.first.type == :math res = "\\#{res}" elsif res.start_with?('\$$') && res.end_with?("\\$$\n") res.sub!(/^\\\$\$/, '\$\$') end res end def convert_codeblock(el, opts) el.value.split(/\n/).map {|l| l.empty? ? " " : " #{l}"}.join("\n") + "\n" end def convert_blockquote(el, opts) opts[:indent] += 2 inner(el, opts).chomp.split(/\n/).map {|l| "> #{l}"}.join("\n") << "\n" end def convert_header(el, opts) res = '' res << "#{'#' * output_header_level(el.options[:level])} #{inner(el, opts)}" res[-1, 1] = "\\#" if res[-1] == ?# res << " {##{el.attr['id']}}" if el.attr['id'] && !el.attr['id'].strip.empty? res << "\n" end def convert_hr(el, opts) "* * *\n" end def convert_ul(el, opts) inner(el, opts).sub(/\n+\Z/, "\n") end alias :convert_ol :convert_ul alias :convert_dl :convert_ul def convert_li(el, opts) sym, width = if @stack.last.type == :ul ['* ', el.children.first && el.children.first.type == :codeblock ? 4 : 2] else ["#{opts[:index] + 1}.".ljust(4), 4] end if ial = ial_for_element(el) sym << ial << " " end opts[:indent] += width text = inner(el, opts) newlines = text.scan(/\n*\Z/).first first, *last = text.split(/\n/) last = last.map {|l| " "*width + l}.join("\n") text = (first.nil? ? "\n" : first + (last.empty? ? "" : "\n") + last + newlines) if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent] res = "#{sym}#{text}" res << "^\n" if el.children.size == 1 && @stack.last.children.last == el && (@stack.last.children.any? {|c| c.children.first.type != :p} || @stack.last.children.size == 1) res elsif el.children.first && el.children.first.type == :codeblock "#{sym}\n #{text}" else "#{sym}#{text}" end end def convert_dd(el, opts) sym, width = ": ", (el.children.first && el.children.first.type == :codeblock ? 4 : 2) if ial = ial_for_element(el) sym << ial << " " end opts[:indent] += width text = inner(el, opts) newlines = text.scan(/\n*\Z/).first first, *last = text.split(/\n/) last = last.map {|l| " "*width + l}.join("\n") text = first.to_s + (last.empty? ? "" : "\n") + last + newlines text.chomp! if text =~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dd text << "\n" if (text !~ /\n\n\Z/ && opts[:next] && opts[:next].type == :dt) text << "\n" if el.children.empty? if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent] "\n#{sym}#{text}" elsif el.children.first && el.children.first.type == :codeblock "#{sym}\n #{text}" else "#{sym}#{text}" end end def convert_dt(el, opts) inner(el, opts) << "\n" end HTML_TAGS_WITH_BODY=['div', 'script', 'iframe', 'textarea'] def convert_html_element(el, opts) markdown_attr = el.options[:category] == :block && el.children.any? do |c| c.type != :html_element && (c.type != :p || !c.options[:transparent]) && Element.category(c) == :block end opts[:force_raw_text] = true if %w{script pre code}.include?(el.value) opts[:raw_text] = opts[:force_raw_text] || opts[:block_raw_text] || (el.options[:category] != :span && !markdown_attr) opts[:block_raw_text] = true if el.options[:category] == :block && opts[:raw_text] res = inner(el, opts) if el.options[:category] == :span "<#{el.value}#{html_attributes(el.attr)}" << (!res.empty? || HTML_TAGS_WITH_BODY.include?(el.value) ? ">#{res}" : " />") else output = '' attr = el.attr.dup attr['markdown'] = '1' if markdown_attr output << "<#{el.value}#{html_attributes(attr)}" if !res.empty? && el.options[:content_model] != :block output << ">#{res}" elsif !res.empty? output << ">\n#{res}" << "" elsif HTML_TAGS_WITH_BODY.include?(el.value) output << ">" else output << " />" end output << "\n" if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw output end end def convert_xml_comment(el, opts) if el.options[:category] == :block && (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw) el.value + "\n" else el.value.dup end end alias :convert_xml_pi :convert_xml_comment def convert_table(el, opts) opts[:alignment] = el.options[:alignment] inner(el, opts) end def convert_thead(el, opts) rows = inner(el, opts) if opts[:alignment].all? {|a| a == :default} "#{rows}|" << "-"*10 << "\n" else "#{rows}| " << opts[:alignment].map do |a| case a when :left then ":-" when :right then "-:" when :center then ":-:" when :default then "-" end end.join(' ') << "\n" end end def convert_tbody(el, opts) res = '' res << inner(el, opts) res << '|' << '-'*10 << "\n" if opts[:next] && opts[:next].type == :tbody res end def convert_tfoot(el, opts) "|" << "="*10 << "\n#{inner(el, opts)}" end def convert_tr(el, opts) "| " << el.children.map {|c| convert(c, opts)}.join(" | ") << " |\n" end def convert_td(el, opts) inner(el, opts) end def convert_comment(el, opts) if el.options[:category] == :block "{::comment}\n#{el.value}\n{:/}\n" else "{::comment}#{el.value}{:/}" end end def convert_br(el, opts) " \n" end def convert_a(el, opts) if el.attr['href'].empty? "[#{inner(el, opts)}]()" elsif el.attr['href'] =~ /^(?:http|ftp)/ || el.attr['href'].count("()") > 0 index = if link_el = @linkrefs.find {|c| c.attr['href'] == el.attr['href']} @linkrefs.index(link_el) + 1 else @linkrefs << el @linkrefs.size end "[#{inner(el, opts)}][#{index}]" else title = parse_title(el.attr['title']) "[#{inner(el, opts)}](#{el.attr['href']}#{title})" end end def convert_img(el, opts) alt_text = el.attr['alt'].to_s.gsub(ESCAPED_CHAR_RE) { $1 ? "\\#{$1}" : $2 } if el.attr['src'].empty? "![#{alt_text}]()" else title = parse_title(el.attr['title']) link = if el.attr['src'].count("()") > 0 "<#{el.attr['src']}>" else el.attr['src'] end "![#{alt_text}](#{link}#{title})" end end def convert_codespan(el, opts) delim = (el.value.scan(/`+/).max || '') + '`' "#{delim}#{' ' if delim.size > 1}#{el.value}#{' ' if delim.size > 1}#{delim}" end def convert_footnote(el, opts) @footnotes << [el.options[:name], el.value] "[^#{el.options[:name]}]" end def convert_raw(el, opts) attr = (el.options[:type] || []).join(' ') attr = " type=\"#{attr}\"" if attr.length > 0 if @stack.last.type == :html_element el.value elsif el.options[:category] == :block "{::nomarkdown#{attr}}\n#{el.value}\n{:/}\n" else "{::nomarkdown#{attr}}#{el.value}{:/}" end end def convert_em(el, opts) "*#{inner(el, opts)}*" + (opts[:next] && [:em, :strong].include?(opts[:next].type) && !ial_for_element(el) ? '{::}' : '') end def convert_strong(el, opts) "**#{inner(el, opts)}**" + (opts[:next] && [:em, :strong].include?(opts[:next].type) && !ial_for_element(el) ? '{::}' : '') end def convert_entity(el, opts) entity_to_str(el.value, el.options[:original]) end TYPOGRAPHIC_SYMS = { :mdash => '---', :ndash => '--', :hellip => '...', :laquo_space => '<< ', :raquo_space => ' >>', :laquo => '<<', :raquo => '>>' } def convert_typographic_sym(el, opts) TYPOGRAPHIC_SYMS[el.value] end def convert_smart_quote(el, opts) el.value.to_s =~ /[rl]dquo/ ? "\"" : "'" end def convert_math(el, opts) "$$#{el.value}$$" + (el.options[:category] == :block ? "\n" : '') end def convert_abbreviation(el, opts) el.value end def convert_root(el, opts) res = inner(el, opts) res << create_link_defs res << create_footnote_defs res << create_abbrev_defs res end def create_link_defs res = '' res << "\n\n" if @linkrefs.size > 0 @linkrefs.each_with_index do |el, i| title = parse_title(el.attr['title']) res << "[#{i+1}]: #{el.attr['href']}#{title}\n" end res end def create_footnote_defs res = '' @footnotes.each do |name, data| res << "[^#{name}]:\n" res << inner(data).chomp.split(/\n/).map {|l| " #{l}"}.join("\n") + "\n\n" end res end def create_abbrev_defs return '' unless @root.options[:abbrev_defs] res = '' @root.options[:abbrev_defs].each do |name, text| res << "*[#{name}]: #{text}\n" res << ial_for_element(Element.new(:unused, nil, @root.options[:abbrev_attr][name])).to_s << "\n\n" end res end # Return the IAL containing the attributes of the element +el+. def ial_for_element(el) res = el.attr.map do |k,v| next if [:img, :a].include?(el.type) && ['href', 'src', 'alt', 'title'].include?(k) next if el.type == :header && k == 'id' && !v.strip.empty? if v.nil? '' elsif k == 'class' && !v.empty? && !v.index(/[\.#]/) " " + v.split(/\s+/).map {|w| ".#{w}"}.join(" ") elsif k == 'id' && !v.strip.empty? " ##{v}" else " #{k}=\"#{v.to_s}\"" end end.compact.join('') res = "toc" << (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) && (el.options[:ial][:refs].include?('toc') rescue nil) res = "footnotes" << (res.strip.empty? ? '' : " #{res}") if (el.type == :ul || el.type == :ol) && (el.options[:ial][:refs].include?('footnotes') rescue nil) res.strip.empty? ? nil : "{:#{res}}" end def parse_title(attr) attr.to_s.empty? ? '' : ' "' + attr.gsub(/"/, '"') + '"' end # :startdoc: end end end kramdown-1.10.0/lib/kramdown/converter/syntax_highlighter.rb0000644000175000017500000000357212672246616024122 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Converter # == Container for Syntax Highlighters # # This module serves as container for the syntax highlighters that can be used together with # kramdown. # # A syntax highlighter should not store any data itself but should use the provided converter # object to do so (See Kramdown::Converter::Base#data). # # == Implementing a Syntax Highlighter # # Implementing a new syntax highlighter is easy because it is just an object that needs to # respond to #call. # # The method #call needs to take the following arguments: # # converter:: This argument contains the converter object that calls the syntax highlighter. It # can be used, for example, to store data in Kramdown::Converter::Base#data for one # conversion run. # # text:: The raw text that should be highlighted. # # lang:: The language that the text should be highlighted for (e.g. ruby, python, ...). # # type:: The type of text, either :span for span-level code or :block for a codeblock. # # opts:: A Hash with options that may be passed from the converter. # # The return value of the method should be the highlighted text, suitable for the given # converter (e.g. HTML for the HTML converter). # # == Special Implementation Details # # HTML converter:: If the syntax highlighter is used with a HTML converter, it should return # :block type text correctly wrapped (i.e. normally inside a pre-tag, but may # also be a table-tag or just a div-tag) but :span type text *without* a # code-tag! module SyntaxHighlighter end end end kramdown-1.10.0/lib/kramdown/converter/base.rb0000644000175000017500000002355512672246616021133 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'erb' require 'kramdown/utils' require 'kramdown/document' module Kramdown module Converter # == \Base class for converters # # This class serves as base class for all converters. It provides methods that can/should be # used by all converters (like #generate_id) as well as common functionality that is # automatically applied to the result (for example, embedding the output into a template). # # A converter object is used as a throw-away object, i.e. it is only used for storing the needed # state information during conversion. Therefore one can't instantiate a converter object # directly but only use the Base::convert method. # # == Implementing a converter # # Implementing a new converter is rather easy: just derive a new class from this class and put # it in the Kramdown::Converter module (the latter is only needed if auto-detection should work # properly). Then you need to implement the #convert method which has to contain the conversion # code for converting an element and has to return the conversion result. # # The actual transformation of the document tree can be done in any way. However, writing one # method per element type is a straight forward way to do it - this is how the Html and Latex # converters do the transformation. # # Have a look at the Base::convert method for additional information! class Base # Can be used by a converter for storing arbitrary information during the conversion process. attr_reader :data # The hash with the conversion options. attr_reader :options # The root element that is converted. attr_reader :root # The warnings array. attr_reader :warnings # Initialize the converter with the given +root+ element and +options+ hash. def initialize(root, options) @options = options @root = root @data = {} @warnings = [] end private_class_method(:new, :allocate) # Returns whether the template should be applied before the conversion of the tree. # # Defaults to false. def apply_template_before? false end # Returns whether the template should be applied ater the conversion of the tree. # # Defaults to true. def apply_template_after? true end # Convert the element tree +tree+ and return the resulting conversion object (normally a # string) and an array with warning messages. The parameter +options+ specifies the conversion # options that should be used. # # Initializes a new instance of the calling class and then calls the #convert method with # +tree+ as parameter. # # If the +template+ option is specified and non-empty, the template is evaluate with ERB # before and/or after the tree conversion depending on the result of #apply_template_before? # and #apply_template_after?. If the template is evaluated before, an empty string is used for # the body; if evaluated after, the result is used as body. See ::apply_template. # # The template resolution is done in the following way (for the converter ConverterName): # # 1. Look in the current working directory for the template. # # 2. Append +.converter_name+ (e.g. +.html+) to the template name and look for the resulting # file in the current working directory (the form +.convertername+ is deprecated). # # 3. Append +.converter_name+ to the template name and look for it in the kramdown data # directory (the form +.convertername+ is deprecated). # # 4. Check if the template name starts with 'string://' and if so, strip this prefix away and # use the rest as template. def self.convert(tree, options = {}) converter = new(tree, ::Kramdown::Options.merge(options.merge(tree.options[:options] || {}))) apply_template(converter, '') if !converter.options[:template].empty? && converter.apply_template_before? result = converter.convert(tree) result.encode!(tree.options[:encoding]) if result.respond_to?(:encode!) && result.encoding != Encoding::BINARY result = apply_template(converter, result) if !converter.options[:template].empty? && converter.apply_template_after? [result, converter.warnings] end # Convert the element +el+ and return the resulting object. # # This is the only method that has to be implemented by sub-classes! def convert(el) raise NotImplementedError end # Apply the +template+ using +body+ as the body string. # # The template is evaluated using ERB and the body is available in the @body instance variable # and the converter object in the @converter instance variable. def self.apply_template(converter, body) # :nodoc: erb = ERB.new(get_template(converter.options[:template])) obj = Object.new obj.instance_variable_set(:@converter, converter) obj.instance_variable_set(:@body, body) erb.result(obj.instance_eval{binding}) end # Return the template specified by +template+. def self.get_template(template) #DEPRECATED: use content of #get_template_new in 2.0 format_ext = '.' + self.name.split(/::/).last.downcase shipped = File.join(::Kramdown.data_dir, template + format_ext) if File.exist?(template) File.read(template) elsif File.exist?(template + format_ext) File.read(template + format_ext) elsif File.exist?(shipped) File.read(shipped) elsif template.start_with?('string://') template.sub(/\Astring:\/\//, '') else get_template_new(template) end end def self.get_template_new(template) # :nodoc: format_ext = '.' + ::Kramdown::Utils.snake_case(self.name.split(/::/).last) shipped = File.join(::Kramdown.data_dir, template + format_ext) if File.exist?(template) File.read(template) elsif File.exist?(template + format_ext) File.read(template + format_ext) elsif File.exist?(shipped) File.read(shipped) elsif template.start_with?('string://') template.sub(/\Astring:\/\//, '') else raise "The specified template file #{template} does not exist" end end # Add the given warning +text+ to the warning array. def warning(text) @warnings << text end # Return +true+ if the header element +el+ should be used for the table of contents (as # specified by the +toc_levels+ option). def in_toc?(el) @options[:toc_levels].include?(el.options[:level]) && (el.attr['class'] || '') !~ /\bno_toc\b/ end # Return the output header level given a level. # # Uses the +header_offset+ option for adjusting the header level. def output_header_level(level) [[level + @options[:header_offset], 6].min, 1].max end # Extract the code block/span language from the attributes. def extract_code_language(attr) if attr['class'] && attr['class'] =~ /\blanguage-\S+/ attr['class'].scan(/\blanguage-(\S+)/).first.first end end # See #extract_code_language # # *Warning*: This version will modify the given attributes if a language is present. def extract_code_language!(attr) lang = extract_code_language(attr) attr['class'] = attr['class'].sub(/\blanguage-\S+/, '').strip if lang attr.delete('class') if lang && attr['class'].empty? lang end # Highlight the given +text+ in the language +lang+ with the syntax highlighter configured # through the option 'syntax_highlighter'. def highlight_code(text, lang, type, opts = {}) return nil unless @options[:syntax_highlighter] highlighter = ::Kramdown::Converter.syntax_highlighter(@options[:syntax_highlighter]) if highlighter highlighter.call(self, text, lang, type, opts) else warning("The configured syntax highlighter #{@options[:syntax_highlighter]} is not available.") nil end end # Format the given math element with the math engine configured through the option # 'math_engine'. def format_math(el, opts = {}) return nil unless @options[:math_engine] engine = ::Kramdown::Converter.math_engine(@options[:math_engine]) if engine engine.call(self, el, opts) else warning("The configured math engine #{@options[:math_engine]} is not available.") nil end end # Generate an unique alpha-numeric ID from the the string +str+ for use as a header ID. # # Uses the option +auto_id_prefix+: the value of this option is prepended to every generated # ID. def generate_id(str) str = ::Kramdown::Utils::Unidecoder.decode(str) if @options[:transliterated_header_ids] gen_id = str.gsub(/^[^a-zA-Z]+/, '') gen_id.tr!('^a-zA-Z0-9 -', '') gen_id.tr!(' ', '-') gen_id.downcase! gen_id = 'section' if gen_id.length == 0 @used_ids ||= {} if @used_ids.has_key?(gen_id) gen_id += '-' << (@used_ids[gen_id] += 1).to_s else @used_ids[gen_id] = 0 end @options[:auto_id_prefix] + gen_id end SMART_QUOTE_INDICES = {:lsquo => 0, :rsquo => 1, :ldquo => 2, :rdquo => 3} # :nodoc: # Return the entity that represents the given smart_quote element. def smart_quote_entity(el) res = @options[:smart_quotes][SMART_QUOTE_INDICES[el.value]] ::Kramdown::Utils::Entities.entity(res) end end end end kramdown-1.10.0/lib/kramdown/converter/toc.rb0000644000175000017500000000347212672246616021002 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/converter' module Kramdown module Converter # Converts a Kramdown::Document to an element tree that represents the table of contents. # # The returned tree consists of Element objects of type :toc where the root element is just used # as container object. Each :toc element contains as value the wrapped :header element and under # the attribute key :id the header ID that should be used (note that this ID may not exist in # the wrapped element). # # Since the TOC tree consists of special :toc elements, one cannot directly feed this tree to # other converters! class Toc < Base def initialize(root, options) super @toc = Element.new(:toc) @stack = [] @options[:template] = '' end def convert(el) if el.type == :header && in_toc?(el) attr = el.attr.dup attr['id'] = generate_id(el.options[:raw_text]) if @options[:auto_ids] && !attr['id'] add_to_toc(el, attr['id']) if attr['id'] else el.children.each {|child| convert(child)} end @toc end private def add_to_toc(el, id) toc_element = Element.new(:toc, el, :id => id) success = false while !success if @stack.empty? @toc.children << toc_element @stack << toc_element success = true elsif @stack.last.value.options[:level] < el.options[:level] @stack.last.children << toc_element @stack << toc_element success = true else @stack.pop end end end end end end kramdown-1.10.0/lib/kramdown/converter/html.rb0000644000175000017500000004026112672246616021156 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser' require 'kramdown/converter' require 'kramdown/utils' module Kramdown module Converter # Converts a Kramdown::Document to HTML. # # You can customize the HTML converter by sub-classing it and overriding the +convert_NAME+ # methods. Each such method takes the following parameters: # # [+el+] The element of type +NAME+ to be converted. # # [+indent+] A number representing the current amount of spaces for indent (only used for # block-level elements). # # The return value of such a method has to be a string containing the element +el+ formatted as # HTML element. class Html < Base include ::Kramdown::Utils::Html include ::Kramdown::Parser::Html::Constants # The amount of indentation used when nesting HTML tags. attr_accessor :indent # Initialize the HTML converter with the given Kramdown document +doc+. def initialize(root, options) super @footnote_counter = @footnote_start = @options[:footnote_nr] @footnotes = [] @footnotes_by_name = {} @footnote_location = nil @toc = [] @toc_code = nil @indent = 2 @stack = [] end # The mapping of element type to conversion method. DISPATCHER = Hash.new {|h,k| h[k] = "convert_#{k}"} # Dispatch the conversion of the element +el+ to a +convert_TYPE+ method using the +type+ of # the element. def convert(el, indent = -@indent) send(DISPATCHER[el.type], el, indent) end # Return the converted content of the children of +el+ as a string. The parameter +indent+ has # to be the amount of indentation used for the element +el+. # # Pushes +el+ onto the @stack before converting the child elements and pops it from the stack # afterwards. def inner(el, indent) result = '' indent += @indent @stack.push(el) el.children.each do |inner_el| result << send(DISPATCHER[inner_el.type], inner_el, indent) end @stack.pop result end def convert_blank(el, indent) "\n" end def convert_text(el, indent) escape_html(el.value, :text) end def convert_p(el, indent) if el.options[:transparent] inner(el, indent) else format_as_block_html(el.type, el.attr, inner(el, indent), indent) end end def convert_codeblock(el, indent) attr = el.attr.dup lang = extract_code_language!(attr) lang = el.options[:lang] if el.options.has_key?(:lang) highlighted_code = highlight_code(el.value, lang, :block) if highlighted_code add_syntax_highlighter_to_class_attr(attr) "#{' '*indent}#{highlighted_code}#{' '*indent}
\n" else result = escape_html(el.value) result.chomp! if el.attr['class'].to_s =~ /\bshow-whitespaces\b/ result.gsub!(/(?:(^[ \t]+)|([ \t]+$)|([ \t]+))/) do |m| suffix = ($1 ? '-l' : ($2 ? '-r' : '')) m.scan(/./).map do |c| case c when "\t" then "\t" when " " then "" end end.join('') end end code_attr = {} code_attr['class'] = "language-#{lang.sub(/\?.*$/, '')}" if lang "#{' '*indent}#{result}\n
\n" end end def convert_blockquote(el, indent) format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent) end def convert_header(el, indent) attr = el.attr.dup if @options[:auto_ids] && !attr['id'] attr['id'] = generate_id(el.options[:raw_text]) end @toc << [el.options[:level], attr['id'], el.children] if attr['id'] && in_toc?(el) level = output_header_level(el.options[:level]) format_as_block_html("h#{level}", attr, inner(el, indent), indent) end def convert_hr(el, indent) "#{' '*indent}\n" end def convert_ul(el, indent) if !@toc_code && (el.options[:ial][:refs].include?('toc') rescue nil) @toc_code = [el.type, el.attr, (0..128).to_a.map{|a| rand(36).to_s(36)}.join] @toc_code.last elsif !@footnote_location && el.options[:ial] && (el.options[:ial][:refs] || []).include?('footnotes') @footnote_location = (0..128).to_a.map{|a| rand(36).to_s(36)}.join else format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent) end end alias :convert_ol :convert_ul def convert_dl(el, indent) format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent) end def convert_li(el, indent) output = ' '*indent << "<#{el.type}" << html_attributes(el.attr) << ">" res = inner(el, indent) if el.children.empty? || (el.children.first.type == :p && el.children.first.options[:transparent]) output << res << (res =~ /\n\Z/ ? ' '*indent : '') else output << "\n" << res << ' '*indent end output << "\n" end alias :convert_dd :convert_li def convert_dt(el, indent) format_as_block_html(el.type, el.attr, inner(el, indent), indent) end def convert_html_element(el, indent) res = inner(el, indent) if el.options[:category] == :span "<#{el.value}#{html_attributes(el.attr)}" << (res.empty? && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value) ? " />" : ">#{res}") else output = '' output << ' '*indent if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw output << "<#{el.value}#{html_attributes(el.attr)}" if el.options[:is_closed] && el.options[:content_model] == :raw output << " />" elsif !res.empty? && el.options[:content_model] != :block output << ">#{res}" elsif !res.empty? output << ">\n#{res.chomp}\n" << ' '*indent << "" elsif HTML_ELEMENTS_WITHOUT_BODY.include?(el.value) output << " />" else output << ">" end output << "\n" if @stack.last.type != :html_element || @stack.last.options[:content_model] != :raw output end end def convert_xml_comment(el, indent) if el.options[:category] == :block && (@stack.last.type != :html_element || @stack.last.options[:content_model] != :raw) ' '*indent << el.value << "\n" else el.value end end alias :convert_xml_pi :convert_xml_comment def convert_table(el, indent) format_as_indented_block_html(el.type, el.attr, inner(el, indent), indent) end alias :convert_thead :convert_table alias :convert_tbody :convert_table alias :convert_tfoot :convert_table alias :convert_tr :convert_table ENTITY_NBSP = ::Kramdown::Utils::Entities.entity('nbsp') # :nodoc: def convert_td(el, indent) res = inner(el, indent) type = (@stack[-2].type == :thead ? :th : :td) attr = el.attr alignment = @stack[-3].options[:alignment][@stack.last.children.index(el)] if alignment != :default attr = el.attr.dup attr['style'] = (attr.has_key?('style') ? "#{attr['style']}; ": '') << "text-align: #{alignment}" end format_as_block_html(type, attr, res.empty? ? entity_to_str(ENTITY_NBSP) : res, indent) end def convert_comment(el, indent) if el.options[:category] == :block "#{' '*indent}\n" else "" end end def convert_br(el, indent) "
" end def convert_a(el, indent) res = inner(el, indent) attr = el.attr.dup if attr['href'].start_with?('mailto:') mail_addr = attr['href'][7..-1] attr['href'] = obfuscate('mailto') << ":" << obfuscate(mail_addr) res = obfuscate(res) if res == mail_addr end format_as_span_html(el.type, attr, res) end def convert_img(el, indent) "" end def convert_codespan(el, indent) attr = el.attr.dup lang = extract_code_language(attr) result = highlight_code(el.value, lang, :span) if result add_syntax_highlighter_to_class_attr(attr) else result = escape_html(el.value) end format_as_span_html('code', attr, result) end def convert_footnote(el, indent) repeat = '' if (footnote = @footnotes_by_name[el.options[:name]]) number = footnote[2] repeat = ":#{footnote[3] += 1}" else number = @footnote_counter @footnote_counter += 1 @footnotes << [el.options[:name], el.value, number, 0] @footnotes_by_name[el.options[:name]] = @footnotes.last end "#{number}" end def convert_raw(el, indent) if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('html') el.value + (el.options[:category] == :block ? "\n" : '') else '' end end def convert_em(el, indent) format_as_span_html(el.type, el.attr, inner(el, indent)) end alias :convert_strong :convert_em def convert_entity(el, indent) entity_to_str(el.value, el.options[:original]) end TYPOGRAPHIC_SYMS = { :mdash => [::Kramdown::Utils::Entities.entity('mdash')], :ndash => [::Kramdown::Utils::Entities.entity('ndash')], :hellip => [::Kramdown::Utils::Entities.entity('hellip')], :laquo_space => [::Kramdown::Utils::Entities.entity('laquo'), ::Kramdown::Utils::Entities.entity('nbsp')], :raquo_space => [::Kramdown::Utils::Entities.entity('nbsp'), ::Kramdown::Utils::Entities.entity('raquo')], :laquo => [::Kramdown::Utils::Entities.entity('laquo')], :raquo => [::Kramdown::Utils::Entities.entity('raquo')] } # :nodoc: def convert_typographic_sym(el, indent) TYPOGRAPHIC_SYMS[el.value].map {|e| entity_to_str(e)}.join('') end def convert_smart_quote(el, indent) entity_to_str(smart_quote_entity(el)) end def convert_math(el, indent) if (result = format_math(el, :indent => indent)) result elsif el.options[:category] == :block format_as_block_html('pre', el.attr, "$$\n#{el.value}\n$$", indent) else format_as_span_html('span', el.attr, "$#{el.value}$") end end def convert_abbreviation(el, indent) title = @root.options[:abbrev_defs][el.value] attr = @root.options[:abbrev_attr][el.value].dup attr['title'] = title unless title.empty? format_as_span_html("abbr", attr, el.value) end def convert_root(el, indent) result = inner(el, indent) if @footnote_location result.sub!(/#{@footnote_location}/, footnote_content.gsub(/\\/, "\\\\\\\\")) else result << footnote_content end if @toc_code toc_tree = generate_toc_tree(@toc, @toc_code[0], @toc_code[1] || {}) text = if toc_tree.children.size > 0 convert(toc_tree, 0) else '' end result.sub!(/#{@toc_code.last}/, text.gsub(/\\/, "\\\\\\\\")) end result end # Format the given element as span HTML. def format_as_span_html(name, attr, body) "<#{name}#{html_attributes(attr)}>#{body}" end # Format the given element as block HTML. def format_as_block_html(name, attr, body, indent) "#{' '*indent}<#{name}#{html_attributes(attr)}>#{body}\n" end # Format the given element as block HTML with a newline after the start tag and indentation # before the end tag. def format_as_indented_block_html(name, attr, body, indent) "#{' '*indent}<#{name}#{html_attributes(attr)}>\n#{body}#{' '*indent}\n" end # Add the syntax highlighter name to the 'class' attribute of the given attribute hash. def add_syntax_highlighter_to_class_attr(attr) (attr['class'] = (attr['class'] || '') + " highlighter-#{@options[:syntax_highlighter]}").lstrip! end # Generate and return an element tree for the table of contents. def generate_toc_tree(toc, type, attr) sections = Element.new(type, nil, attr) sections.attr['id'] ||= 'markdown-toc' stack = [] toc.each do |level, id, children| li = Element.new(:li, nil, nil, {:level => level}) li.children << Element.new(:p, nil, nil, {:transparent => true}) a = Element.new(:a, nil) a.attr['href'] = "##{id}" a.attr['id'] = "#{sections.attr['id']}-#{id}" a.children.concat(remove_footnotes(Marshal.load(Marshal.dump(children)))) li.children.last.children << a li.children << Element.new(type) success = false while !success if stack.empty? sections.children << li stack << li success = true elsif stack.last.options[:level] < li.options[:level] stack.last.children.last.children << li stack << li success = true else item = stack.pop item.children.pop unless item.children.last.children.size > 0 end end end while !stack.empty? item = stack.pop item.children.pop unless item.children.last.children.size > 0 end sections end # Remove all footnotes from the given elements. def remove_footnotes(elements) elements.delete_if do |c| remove_footnotes(c.children) c.type == :footnote end end # Obfuscate the +text+ by using HTML entities. def obfuscate(text) result = "" text.each_byte do |b| result << (b > 128 ? b.chr : "&#%03d;" % b) end result.force_encoding(text.encoding) if result.respond_to?(:force_encoding) result end FOOTNOTE_BACKLINK_FMT = "%s%s" # Return a HTML ordered list with the footnote content for the used footnotes. def footnote_content ol = Element.new(:ol) ol.attr['start'] = @footnote_start if @footnote_start != 1 i = 0 backlink_text = escape_html(@options[:footnote_backlink], :text) while i < @footnotes.length name, data, _, repeat = *@footnotes[i] li = Element.new(:li, nil, {'id' => "fn:#{name}"}) li.children = Marshal.load(Marshal.dump(data.children)) if li.children.last.type == :p para = li.children.last insert_space = true else li.children << (para = Element.new(:p)) insert_space = false end unless @options[:footnote_backlink].empty? para.children << Element.new(:raw, FOOTNOTE_BACKLINK_FMT % [insert_space ? ' ' : '', name, backlink_text]) (1..repeat).each do |index| para.children << Element.new(:raw, FOOTNOTE_BACKLINK_FMT % [" ", "#{name}:#{index}", "#{backlink_text}#{index+1}"]) end end ol.children << Element.new(:raw, convert(li, 4)) i += 1 end (ol.children.empty? ? '' : format_as_indented_block_html('div', {:class => "footnotes"}, convert(ol, 2), 0)) end end end end kramdown-1.10.0/lib/kramdown/converter/remove_html_tags.rb0000644000175000017500000000311212672246616023543 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/converter' module Kramdown module Converter # Removes all block (and optionally span) level HTML tags from the element tree. # # This converter can be used on parsed HTML documents to get an element tree that will only # contain native kramdown elements. # # *Note* that the returned element tree may not be fully conformant (i.e. the content models of # *some elements may be violated)! # # This converter modifies the given tree in-place and returns it. class RemoveHtmlTags < Base def initialize(root, options) super @options[:template] = '' end def convert(el) children = el.children.dup index = 0 while index < children.length if [:xml_pi].include?(children[index].type) || (children[index].type == :html_element && %w[style script].include?(children[index].value)) children[index..index] = [] elsif children[index].type == :html_element && ((@options[:remove_block_html_tags] && children[index].options[:category] == :block) || (@options[:remove_span_html_tags] && children[index].options[:category] == :span)) children[index..index] = children[index].children else convert(children[index]) index += 1 end end el.children = children el end end end end kramdown-1.10.0/lib/kramdown/converter/syntax_highlighter/0000755000175000017500000000000012672246616023566 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/converter/syntax_highlighter/minted.rb0000644000175000017500000000156112672246616025376 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::SyntaxHighlighter # Uses Minted to highlight code blocks and code spans. module Minted def self.call(converter, text, lang, type, _opts) opts = converter.options[:syntax_highlighter_opts] # Fallback to default language lang ||= opts[:default_lang] options = [] options << "breaklines" if opts[:wrap] options << "linenos" if opts[:line_numbers] options << "frame=#{opts[:frame]}" if opts[:frame] if lang && type == :block "\\begin{minted}[#{options.join(',')}]{#{lang}}\n#{text}\n\\end{minted}" elsif lang && type == :span "\\mintinline{#{lang}}{#{text}}" else nil end end end end kramdown-1.10.0/lib/kramdown/converter/syntax_highlighter/coderay.rb0000644000175000017500000000511412672246616025542 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::SyntaxHighlighter # Uses Coderay to highlight code blocks and code spans. module Coderay begin require 'coderay' # Highlighting via coderay is available if this constant is +true+. AVAILABLE = true rescue LoadError AVAILABLE = false # :nodoc: end def self.call(converter, text, lang, type, _unused_opts) return nil unless converter.options[:enable_coderay] if type == :span && lang ::CodeRay.scan(text, lang.to_sym).html(options(converter, :span)).chomp elsif type == :block && (lang || options(converter, :default_lang)) lang = (lang || options(converter, :default_lang)).to_s.gsub(/-/, '_').to_sym ::CodeRay.scan(text, lang).html(options(converter, :block)).chomp << "\n" else nil end rescue converter.warning("There was an error using CodeRay: #{$!.message}") nil end def self.options(converter, type) prepare_options(converter) converter.data[:syntax_highlighter_coderay][type] end def self.prepare_options(converter) return if converter.data.key?(:syntax_highlighter_coderay) cache = converter.data[:syntax_highlighter_coderay] = {} opts = converter.options[:syntax_highlighter_opts].dup span_opts = (opts.delete(:span) || {}).dup block_opts = (opts.delete(:block) || {}).dup [span_opts, block_opts].each do |hash| hash.keys.each do |k| hash[k.kind_of?(String) ? Kramdown::Options.str_to_sym(k) : k] = hash.delete(k) end end cache[:default_lang] = converter.options[:coderay_default_lang] || opts.delete(:default_lang) cache[:span] = { :css => converter.options[:coderay_css] }.update(opts).update(span_opts).update(:wrap => :span) cache[:block] = { :wrap => converter.options[:coderay_wrap], :line_numbers => converter.options[:coderay_line_numbers], :line_number_start => converter.options[:coderay_line_number_start], :tab_width => converter.options[:coderay_tab_width], :bold_every => converter.options[:coderay_bold_every], :css => converter.options[:coderay_css] }.update(opts).update(block_opts) [:css, :wrap, :line_numbers].each do |key| [:block, :span].each do |type| cache[type][key] = cache[type][key].to_sym if cache[type][key].kind_of?(String) end end end end end kramdown-1.10.0/lib/kramdown/converter/syntax_highlighter/rouge.rb0000644000175000017500000000317112672246616025236 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::SyntaxHighlighter # Uses Rouge which is CSS-compatible to Pygments to highlight code blocks and code spans. module Rouge begin require 'rouge' # Highlighting via Rouge is available if this constant is +true+. AVAILABLE = true rescue LoadError, SyntaxError AVAILABLE = false # :nodoc: end def self.call(converter, text, lang, type, _unused_opts) opts = options(converter, type) lexer = ::Rouge::Lexer.find_fancy(lang || opts[:default_lang], text) return nil if opts[:disable] || !lexer formatter = (opts.delete(:formatter) || ::Rouge::Formatters::HTML).new(opts) formatter.format(lexer.lex(text)) end def self.options(converter, type) prepare_options(converter) converter.data[:syntax_highlighter_rouge][type] end def self.prepare_options(converter) return if converter.data.key?(:syntax_highlighter_rouge) cache = converter.data[:syntax_highlighter_rouge] = {} opts = converter.options[:syntax_highlighter_opts].dup span_opts = (opts.delete(:span) || {}).dup block_opts = (opts.delete(:block) || {}).dup [span_opts, block_opts].each do |hash| hash.keys.each do |k| hash[k.kind_of?(String) ? Kramdown::Options.str_to_sym(k) : k] = hash.delete(k) end end cache[:span] = opts.merge(span_opts).update(:wrap => false) cache[:block] = opts.merge(block_opts) end end end kramdown-1.10.0/lib/kramdown/converter/hash_ast.rb0000644000175000017500000000145612672246616022007 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser' require 'kramdown/converter' require 'kramdown/utils' module Kramdown module Converter # Converts a Kramdown::Document to a nested hash for further processing or debug output. class HashAST < Base def convert(el) hash = {:type => el.type} hash[:attr] = el.attr unless el.attr.empty? hash[:value] = el.value unless el.value.nil? hash[:options] = el.options unless el.options.empty? unless el.children.empty? hash[:children] = [] el.children.each {|child| hash[:children] << convert(child)} end hash end end end end kramdown-1.10.0/lib/kramdown/converter/pdf.rb0000644000175000017500000004477012672246616020774 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'prawn' require 'prawn/table' require 'kramdown/converter' require 'kramdown/utils' require 'open-uri' module Kramdown module Converter # Converts an element tree to a PDF using the prawn PDF library. # # This basic version provides a nice starting point for customizations but can also be used # directly. # # There can be the following two methods for each element type: render_TYPE(el, opts) and # TYPE_options(el, opts) where +el+ is a kramdown element and +opts+ an hash with rendering # options. # # The render_TYPE(el, opts) is used for rendering the specific element. If the element is a span # element, it should return a hash or an array of hashes that can be used by the #formatted_text # method of Prawn::Document. This method can then be used in block elements to actually render # the span elements. # # The rendering options are passed from the parent to its child elements. This allows one to # define general options at the top of the tree (the root element) that can later be changed or # amended. # # # Currently supports the conversion of all elements except those of the following types: # # :html_element, :img, :footnote # # class Pdf < Base include Prawn::Measurements def initialize(root, options) super @stack = [] @dests = {} end # PDF templates are applied before conversion. They should contain code to augment the # converter object (i.e. to override the methods). def apply_template_before? true end # Returns +false+. def apply_template_after? false end DISPATCHER_RENDER = Hash.new {|h,k| h[k] = "render_#{k}"} #:nodoc: DISPATCHER_OPTIONS = Hash.new {|h,k| h[k] = "#{k}_options"} #:nodoc: # Invoke the special rendering method for the given element +el+. # # A PDF destination is also added at the current location if th element has an ID or if the # element is of type :header and the :auto_ids option is set. def convert(el, opts = {}) id = el.attr['id'] id = generate_id(el.options[:raw_text]) if !id && @options[:auto_ids] && el.type == :header if !id.to_s.empty? && !@dests.has_key?(id) @pdf.add_dest(id, @pdf.dest_xyz(0, @pdf.y)) @dests[id] = @pdf.dest_xyz(0, @pdf.y) end send(DISPATCHER_RENDER[el.type], el, opts) end protected # Render the children of this element with the given options and return the results as array. # # Each time a child is rendered, the +TYPE_options+ method is invoked (if it exists) to get # the specific options for the element with which the given options are updated. def inner(el, opts) @stack.push([el, opts]) result = el.children.map do |inner_el| options = opts.dup options.update(send(DISPATCHER_OPTIONS[inner_el.type], inner_el, options)) convert(inner_el, options) end.flatten.compact @stack.pop result end # ---------------------------- # :section: Element rendering methods # ---------------------------- def root_options(root, opts) {:font => 'Times-Roman', :size => 12, :leading => 2} end def render_root(root, opts) @pdf = setup_document(root) inner(root, root_options(root, opts)) create_outline(root) finish_document(root) @pdf.render end def header_options(el, opts) size = opts[:size] * 1.15**(6 - el.options[:level]) { :font => "Helvetica", :styles => (opts[:styles] || []) + [:bold], :size => size, :bottom_padding => opts[:size], :top_padding => opts[:size] } end def render_header(el, opts) render_padded_and_formatted_text(el, opts) end def p_options(el, opts) bpad = (el.options[:transparent] ? opts[:leading] : opts[:size]) {:align => :justify, :bottom_padding => bpad} end def render_p(el, opts) if el.children.size == 1 && el.children.first.type == :img render_standalone_image(el, opts) else render_padded_and_formatted_text(el, opts) end end def render_standalone_image(el, opts) img = el.children.first line = img.options[:location] if img.attr['src'].empty? warning("Rendering an image without a source is not possible#{line ? " (line #{line})" : ''}") return nil elsif img.attr['src'] !~ /\.jpe?g$|\.png$/ warning("Cannot render images other than JPEG or PNG, got #{img.attr['src']}#{line ? " on line #{line}" : ''}") return nil end img_dirs = (@options[:image_directories] || ['.']).dup begin img_path = File.join(img_dirs.shift, img.attr['src']) image_obj, image_info = @pdf.build_image_object(open(img_path)) rescue img_dirs.empty? ? raise : retry end options = {:position => :center} if img.attr['height'] && img.attr['height'] =~ /px$/ options[:height] = img.attr['height'].to_i / (@options[:image_dpi] || 150.0) * 72 elsif img.attr['width'] && img.attr['width'] =~ /px$/ options[:width] = img.attr['width'].to_i / (@options[:image_dpi] || 150.0) * 72 else options[:scale] =[(@pdf.bounds.width - mm2pt(20)) / image_info.width.to_f, 1].min end if img.attr['class'] =~ /\bright\b/ options[:position] = :right @pdf.float { @pdf.embed_image(image_obj, image_info, options) } else with_block_padding(el, opts) do @pdf.embed_image(image_obj, image_info, options) end end end def blockquote_options(el, opts) {:styles => [:italic]} end def render_blockquote(el, opts) @pdf.indent(mm2pt(10), mm2pt(10)) { inner(el, opts) } end def ul_options(el, opts) {:bottom_padding => opts[:size]} end def render_ul(el, opts) with_block_padding(el, opts) do el.children.each do |li| @pdf.float { @pdf.formatted_text([text_hash("•", opts)]) } @pdf.indent(mm2pt(6)) { convert(li, opts) } end end end def ol_options(el, opts) {:bottom_padding => opts[:size]} end def render_ol(el, opts) with_block_padding(el, opts) do el.children.each_with_index do |li, index| @pdf.float { @pdf.formatted_text([text_hash("#{index+1}.", opts)]) } @pdf.indent(mm2pt(6)) { convert(li, opts) } end end end def li_options(el, opts) {} end def render_li(el, opts) inner(el, opts) end def dl_options(el, opts) {} end def render_dl(el, opts) inner(el, opts) end def dt_options(el, opts) {:styles => (opts[:styles] || []) + [:bold], :bottom_padding => 0} end def render_dt(el, opts) render_padded_and_formatted_text(el, opts) end def dd_options(el, opts) {} end def render_dd(el, opts) @pdf.indent(mm2pt(10)) { inner(el, opts) } end def math_options(el, opts) {} end def render_math(el, opts) if el.options[:category] == :block @pdf.formatted_text([{:text => el.value}], block_hash(opts)) else {:text => el.value} end end def hr_options(el, opts) {:top_padding => opts[:size], :bottom_padding => opts[:size]} end def render_hr(el, opts) with_block_padding(el, opts) do @pdf.stroke_horizontal_line(@pdf.bounds.left + mm2pt(5), @pdf.bounds.right - mm2pt(5)) end end def codeblock_options(el, opts) { :font => 'Courier', :color => '880000', :bottom_padding => opts[:size] } end def render_codeblock(el, opts) with_block_padding(el, opts) do @pdf.formatted_text([text_hash(el.value, opts, false)], block_hash(opts)) end end def table_options(el, opts) {:bottom_padding => opts[:size]} end def render_table(el, opts) data = [] el.children.each do |container| container.children.each do |row| data << [] row.children.each do |cell| if cell.children.any? {|child| child.options[:category] == :block} line = el.options[:location] warning("Can't render tables with cells containing block elements#{line ? " (line #{line})" : ''}") return end cell_data = inner(cell, opts) data.last << cell_data.map {|c| c[:text]}.join('') end end end with_block_padding(el, opts) do @pdf.table(data, :width => @pdf.bounds.right) do el.options[:alignment].each_with_index do |alignment, index| columns(index).align = alignment unless alignment == :default end end end end def text_options(el, opts) {} end def render_text(el, opts) text_hash(el.value.to_s, opts) end def em_options(el, opts) if opts[:styles] && opts[:styles].include?(:italic) {:styles => opts[:styles].reject {|i| i == :italic}} else {:styles => (opts[:styles] || []) << :italic} end end def strong_options(el, opts) {:styles => (opts[:styles] || []) + [:bold]} end def a_options(el, opts) hash = {:color => '000088'} if el.attr['href'].start_with?('#') hash[:anchor] = el.attr['href'].sub(/\A#/, '') else hash[:link] = el.attr['href'] end hash end def render_em(el, opts) inner(el, opts) end alias_method :render_strong, :render_em alias_method :render_a, :render_em def codespan_options(el, opts) {:font => 'Courier', :color => '880000'} end def render_codespan(el, opts) text_hash(el.value, opts) end def br_options(el, opts) {} end def render_br(el, opts) text_hash("\n", opts, false) end def smart_quote_options(el, opts) {} end def render_smart_quote(el, opts) text_hash(smart_quote_entity(el).char, opts) end def typographic_sym_options(el, opts) {} end def render_typographic_sym(el, opts) str = if el.value == :laquo_space ::Kramdown::Utils::Entities.entity('laquo').char + ::Kramdown::Utils::Entities.entity('nbsp').char elsif el.value == :raquo_space ::Kramdown::Utils::Entities.entity('raquo').char + ::Kramdown::Utils::Entities.entity('nbsp').char else ::Kramdown::Utils::Entities.entity(el.value.to_s).char end text_hash(str, opts) end def entity_options(el, opts) {} end def render_entity(el, opts) text_hash(el.value.char, opts) end def abbreviation_options(el, opts) {} end def render_abbreviation(el, opts) text_hash(el.value, opts) end def img_options(el, opts) {} end def render_img(el, *args) #:nodoc: line = el.options[:location] warning("Rendering span images is not supported for PDF converter#{line ? " (line #{line})" : ''}") nil end def xml_comment_options(el, opts) #:nodoc: {} end alias_method :xml_pi_options, :xml_comment_options alias_method :comment_options, :xml_comment_options alias_method :blank_options, :xml_comment_options alias_method :footnote_options, :xml_comment_options alias_method :raw_options, :xml_comment_options alias_method :html_element_options, :xml_comment_options def render_xml_comment(el, opts) #:nodoc: # noop end alias_method :render_xml_pi, :render_xml_comment alias_method :render_comment, :render_xml_comment alias_method :render_blank, :render_xml_comment def render_footnote(el, *args) #:nodoc: line = el.options[:location] warning("Rendering #{el.type} not supported for PDF converter#{line ? " (line #{line})" : ''}") nil end alias_method :render_raw, :render_footnote alias_method :render_html_element, :render_footnote # ---------------------------- # :section: Organizational methods # # These methods are used, for example, to up the needed Prawn::Document instance or to create # a PDF outline. # ---------------------------- # This module gets mixed into the Prawn::Document instance. module PrawnDocumentExtension # Extension for the formatted box class to recognize images and move text around them. module CustomBox def available_width return super unless @document.respond_to?(:converter) && @document.converter @document.image_floats.each do |pn, x, y, w, h| next if @document.page_number != pn if @at[1] + @baseline_y <= y - @document.bounds.absolute_bottom && (@at[1] + @baseline_y + @arranger.max_line_height + @leading >= y - h - @document.bounds.absolute_bottom) return @width - w end end return super end end Prawn::Text::Formatted::Box.extensions << CustomBox # Access the converter instance from within Prawn attr_accessor :converter def image_floats @image_floats ||= [] end # Override image embedding method for adding image positions to #image_floats. def embed_image(pdf_obj, info, options) # find where the image will be placed and how big it will be w,h = info.calc_image_dimensions(options) if options[:at] x,y = map_to_absolute(options[:at]) else x,y = image_position(w,h,options) move_text_position h end #--> This part is new if options[:position] == :right image_floats << [page_number, x - 15, y, w + 15, h + 15] end # add a reference to the image object to the current page # resource list and give it a label label = "I#{next_image_id}" state.page.xobjects.merge!(label => pdf_obj) # add the image to the current page instruct = "\nq\n%.3f 0 0 %.3f %.3f %.3f cm\n/%s Do\nQ" add_content instruct % [ w, h, x, y - h, label ] end end # Return a hash with options that are suitable for Prawn::Document.new. # # Used in #setup_document. def document_options(root) { :page_size => 'A4', :page_layout => :portrait, :margin => mm2pt(20), :info => { :Creator => 'kramdown PDF converter', :CreationDate => Time.now }, :compress => true, :optimize_objects => true } end # Create a Prawn::Document object and return it. # # Can be used to define repeatable content or register fonts. # # Used in #render_root. def setup_document(root) doc = Prawn::Document.new(document_options(root)) doc.extend(PrawnDocumentExtension) doc.converter = self doc end # # # Used in #render_root. def finish_document(root) # no op end # Create the PDF outline from the header elements in the TOC. def create_outline(root) toc = ::Kramdown::Converter::Toc.convert(root).first text_of_header = lambda do |el| if el.type == :text el.value else el.children.map {|c| text_of_header.call(c)}.join('') end end add_section = lambda do |item, parent| text = text_of_header.call(item.value) destination = @dests[item.attr[:id]] if !parent @pdf.outline.page(:title => text, :destination => destination) else @pdf.outline.add_subsection_to(parent) do @pdf.outline.page(:title => text, :destination => destination) end end item.children.each {|c| add_section.call(c, text)} end toc.children.each do |item| add_section.call(item, nil) end end # ---------------------------- # :section: Helper methods # ---------------------------- # Move the prawn document cursor down before and/or after yielding the given block. # # The :top_padding and :bottom_padding options are used for determinig the padding amount. def with_block_padding(el, opts) @pdf.move_down(opts[:top_padding]) if opts.has_key?(:top_padding) yield @pdf.move_down(opts[:bottom_padding]) if opts.has_key?(:bottom_padding) end # Render the children of the given element as formatted text and respect the top/bottom # padding (see #with_block_padding). def render_padded_and_formatted_text(el, opts) with_block_padding(el, opts) { @pdf.formatted_text(inner(el, opts), block_hash(opts)) } end # Helper function that returns a hash with valid "formatted text" options. # # The +text+ parameter is used as value for the :text key and if +squeeze_whitespace+ is # +true+, all whitespace is converted into spaces. def text_hash(text, opts, squeeze_whitespace = true) text = text.gsub(/\s+/, ' ') if squeeze_whitespace hash = {:text => text} [:styles, :size, :character_spacing, :font, :color, :link, :anchor, :draw_text_callback, :callback].each do |key| hash[key] = opts[key] if opts.has_key?(key) end hash end # Helper function that returns a hash with valid options for the prawn #text_box extracted # from the given options. def block_hash(opts) hash = {} [:align, :valign, :mode, :final_gap, :leading, :fallback_fonts, :direction, :indent_paragraphs].each do |key| hash[key] = opts[key] if opts.has_key?(key) end hash end end end end kramdown-1.10.0/lib/kramdown/converter/math_engine/0000755000175000017500000000000012672246616022140 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/converter/math_engine/mathjax.rb0000644000175000017500000000267512672246616024133 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::MathEngine # Uses the MathJax javascript library for displaying math. # # Note that the javascript library itself is not include or linked, this has to be done # separately. Only the math content is marked up correctly. module Mathjax def self.call(converter, el, opts) type = el.options[:category] text = (el.value =~ /<|&/ ? "% " : el.value) text.gsub!(/<\/?script>?/, '') preview = preview_string(converter, el, opts) attr = {:type => "math/tex#{type == :block ? '; mode=display' : ''}"} if type == :block preview << converter.format_as_block_html('script', attr, text, opts[:indent]) else preview << converter.format_as_span_html('script', attr, text) end end def self.preview_string(converter, el, opts) preview = converter.options[:math_engine_opts][:preview] return '' unless preview preview = (preview == true ? converter.escape_html(el.value) : preview.to_s) if el.options[:category] == :block converter.format_as_block_html('div', {'class' => 'MathJax_Preview'}, preview, opts[:indent]) else converter.format_as_span_html('span', {'class' => 'MathJax_Preview'}, preview) end end end end kramdown-1.10.0/lib/kramdown/converter/math_engine/mathjaxnode.rb0000644000175000017500000000304312672246616024767 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::MathEngine # Uses the mathjax-node library for converting math formulas to MathML. module MathjaxNode # MathjaxNode is available if this constant is +true+. AVAILABLE = RUBY_VERSION >= '1.9' && begin %x{node --version}[1..-2] >= '4.0' rescue begin %x{nodejs --version}[1..-2] >= '4.0' rescue false end end && begin npm = %x{npm --global --depth=1 list mathjax-node 2>&1} unless /mathjax-node@/ === npm.lines.drop(1).join("\n") npm = %x{npm --depth=1 list mathjax-node 2>&1} end T2MPATH = File.join(npm.lines.first.strip, "node_modules/mathjax-node/bin/tex2mml") /mathjax-node@/ === npm.lines.drop(1).join("\n") && File.exist?(T2MPATH) rescue false end def self.call(converter, el, opts) type = el.options[:category] cmd = [T2MPATH] cmd << "--inline" unless type == :block cmd << "--semantics" if converter.options[:math_engine_opts][:semantics] == true cmd << "--notexhints" if converter.options[:math_engine_opts][:texhints] == false result = IO.popen(cmd << el.value).read.strip attr = el.attr.dup attr.delete('xmlns') attr.delete('display') result.insert(" # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::MathEngine # Uses the Ritex library for converting math formulas to MathML. module Ritex begin require 'ritex' # Ritex is available if this constant is +true+. AVAILABLE = true rescue LoadError AVAILABLE = false # :nodoc: end def self.call(converter, el, opts) type = el.options[:category] result = ::Ritex::Parser.new.parse(el.value, :display => (type == :block)) attr = el.attr.dup attr.delete('xmlns') attr.delete('display') result.insert(" # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown::Converter::MathEngine # Uses the Itex2MML library for converting math formulas to MathML. module Itex2MML begin require 'itextomml' # Itex2MML is available if this constant is +true+. AVAILABLE = true rescue LoadError AVAILABLE = false # :nodoc: end def self.call(converter, el, opts) type = el.options[:category] parser = ::Itex2MML::Parser.new result = (type == :block ? parser.block_filter(el.value) : parser.inline_filter(el.value)) attr = el.attr.dup attr.delete('xmlns') attr.delete('display') result.insert(" # # This file is part of kramdown which is licensed under the MIT. #++ # require 'set' require 'kramdown/converter' module Kramdown module Converter # Converts an element tree to LaTeX. # # This converter uses ideas from other Markdown-to-LaTeX converters like Pandoc and Maruku. # # You can customize this converter by sub-classing it and overriding the +convert_NAME+ methods. # Each such method takes the following parameters: # # [+el+] The element of type +NAME+ to be converted. # # [+opts+] A hash containing processing options that are passed down from parent elements. The # key :parent is always set and contains the parent element as value. # # The return value of such a method has to be a string containing the element +el+ formatted # correctly as LaTeX markup. class Latex < Base # Initialize the LaTeX converter with the +root+ element and the conversion +options+. def initialize(root, options) super @data[:packages] = Set.new end # Dispatch the conversion of the element +el+ to a +convert_TYPE+ method using the +type+ of # the element. def convert(el, opts = {}) send("convert_#{el.type}", el, opts) end # Return the converted content of the children of +el+ as a string. def inner(el, opts) result = '' options = opts.dup.merge(:parent => el) el.children.each_with_index do |inner_el, index| options[:index] = index options[:result] = result result << send("convert_#{inner_el.type}", inner_el, options) end result end def convert_root(el, opts) inner(el, opts) end def convert_blank(el, opts) opts[:result] =~ /\n\n\Z|\A\Z/ ? "" : "\n" end def convert_text(el, opts) escape(el.value) end def convert_p(el, opts) if el.children.size == 1 && el.children.first.type == :img && !(img = convert_img(el.children.first, opts)).empty? convert_standalone_image(el, opts, img) else "#{latex_link_target(el)}#{inner(el, opts)}\n\n" end end # Helper method used by +convert_p+ to convert a paragraph that only contains a single :img # element. def convert_standalone_image(el, opts, img) attrs = attribute_list(el) "\\begin{figure}#{attrs}\n\\begin{center}\n#{img}\n\\end{center}\n\\caption{#{escape(el.children.first.attr['alt'])}}\n#{latex_link_target(el, true)}\n\\end{figure}#{attrs}\n" end def convert_codeblock(el, opts) show_whitespace = el.attr['class'].to_s =~ /\bshow-whitespaces\b/ lang = extract_code_language(el.attr) if @options[:syntax_highlighter] == :minted && (highlighted_code = highlight_code(el.value, lang, :block)) @data[:packages] << 'minted' "#{latex_link_target(el)}#{highlighted_code}\n" elsif show_whitespace || lang options = [] options << "showspaces=%s,showtabs=%s" % (show_whitespace ? ['true', 'true'] : ['false', 'false']) options << "language=#{lang}" if lang options << "basicstyle=\\ttfamily\\footnotesize,columns=fixed,frame=tlbr" id = el.attr['id'] options << "label=#{id}" if id attrs = attribute_list(el) "#{latex_link_target(el)}\\begin{lstlisting}[#{options.join(',')}]\n#{el.value}\n\\end{lstlisting}#{attrs}\n" else "#{latex_link_target(el)}\\begin{verbatim}#{el.value}\\end{verbatim}\n" end end def convert_blockquote(el, opts) latex_environment(el.children.size > 1 ? 'quotation' : 'quote', el, inner(el, opts)) end def convert_header(el, opts) type = @options[:latex_headers][output_header_level(el.options[:level]) - 1] if ((id = el.attr['id']) || (@options[:auto_ids] && (id = generate_id(el.options[:raw_text])))) && in_toc?(el) "\\#{type}{#{inner(el, opts)}}\\hypertarget{#{id}}{}\\label{#{id}}\n\n" else "\\#{type}*{#{inner(el, opts)}}\n\n" end end def convert_hr(el, opts) attrs = attribute_list(el) "#{latex_link_target(el)}\\begin{center}#{attrs}\n\\rule{3in}{0.4pt}\n\\end{center}#{attrs}\n" end def convert_ul(el, opts) if !@data[:has_toc] && (el.options[:ial][:refs].include?('toc') rescue nil) @data[:has_toc] = true '\tableofcontents' else latex_environment(el.type == :ul ? 'itemize' : 'enumerate', el, inner(el, opts)) end end alias :convert_ol :convert_ul def convert_dl(el, opts) latex_environment('description', el, inner(el, opts)) end def convert_li(el, opts) "\\item #{latex_link_target(el, true)}#{inner(el, opts).sub(/\n+\Z/, '')}\n" end def convert_dt(el, opts) "\\item[#{inner(el, opts)}] " end def convert_dd(el, opts) "#{latex_link_target(el)}#{inner(el, opts)}\n\n" end def convert_html_element(el, opts) if el.value == 'i' || el.value == 'em' "\\emph{#{inner(el, opts)}}" elsif el.value == 'b' || el.value == 'strong' "\\textbf{#{inner(el, opts)}}" else warning("Can't convert HTML element") '' end end def convert_xml_comment(el, opts) el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") + "\n" end def convert_xml_pi(el, opts) warning("Can't convert XML PI") '' end TABLE_ALIGNMENT_CHAR = {:default => 'l', :left => 'l', :center => 'c', :right => 'r'} # :nodoc: def convert_table(el, opts) @data[:packages] << 'longtable' align = el.options[:alignment].map {|a| TABLE_ALIGNMENT_CHAR[a]}.join('|') attrs = attribute_list(el) "#{latex_link_target(el)}\\begin{longtable}{|#{align}|}#{attrs}\n\\hline\n#{inner(el, opts)}\\hline\n\\end{longtable}#{attrs}\n\n" end def convert_thead(el, opts) "#{inner(el, opts)}\\hline\n" end def convert_tbody(el, opts) inner(el, opts) end def convert_tfoot(el, opts) "\\hline \\hline \n#{inner(el, opts)}" end def convert_tr(el, opts) el.children.map {|c| send("convert_#{c.type}", c, opts)}.join(' & ') << "\\\\\n" end def convert_td(el, opts) inner(el, opts) end def convert_comment(el, opts) el.value.split(/\n/).map {|l| "% #{l}"}.join("\n") << "\n" end def convert_br(el, opts) res = "\\newline" res << "\n" if (c = opts[:parent].children[opts[:index]+1]) && (c.type != :text || c.value !~ /^\s*\n/) res end def convert_a(el, opts) url = el.attr['href'] if url.start_with?('#') "\\hyperlink{#{escape(url[1..-1])}}{#{inner(el, opts)}}" else "\\href{#{escape(url)}}{#{inner(el, opts)}}" end end def convert_img(el, opts) line = el.options[:location] if el.attr['src'] =~ /^(https?|ftps?):\/\// warning("Cannot include non-local image#{line ? " (line #{line})" : ''}") '' elsif !el.attr['src'].empty? @data[:packages] << 'graphicx' "#{latex_link_target(el)}\\includegraphics{#{el.attr['src']}}" else warning("Cannot include image with empty path#{line ? " (line #{line})" : ''}") '' end end def convert_codespan(el, opts) lang = extract_code_language(el.attr) if @options[:syntax_highlighter] == :minted && (highlighted_code = highlight_code(el.value, lang, :span)) @data[:packages] << 'minted' "#{latex_link_target(el)}#{highlighted_code}" else "\\texttt{#{latex_link_target(el)}#{escape(el.value)}}" end end def convert_footnote(el, opts) @data[:packages] << 'fancyvrb' "\\footnote{#{inner(el.value, opts).rstrip}}" end def convert_raw(el, opts) if !el.options[:type] || el.options[:type].empty? || el.options[:type].include?('latex') el.value + (el.options[:category] == :block ? "\n" : '') else '' end end def convert_em(el, opts) "\\emph{#{latex_link_target(el)}#{inner(el, opts)}}" end def convert_strong(el, opts) "\\textbf{#{latex_link_target(el)}#{inner(el, opts)}}" end # Inspired by Maruku: entity conversion table based on the one from htmltolatex # (http://sourceforge.net/projects/htmltolatex/), with some small adjustments/additions ENTITY_CONV_TABLE = { 913 => ['$A$'], 914 => ['$B$'], 915 => ['$\Gamma$'], 916 => ['$\Delta$'], 917 => ['$E$'], 918 => ['$Z$'], 919 => ['$H$'], 920 => ['$\Theta$'], 921 => ['$I$'], 922 => ['$K$'], 923 => ['$\Lambda$'], 924 => ['$M$'], 925 => ['$N$'], 926 => ['$\Xi$'], 927 => ['$O$'], 928 => ['$\Pi$'], 929 => ['$P$'], 931 => ['$\Sigma$'], 932 => ['$T$'], 933 => ['$Y$'], 934 => ['$\Phi$'], 935 => ['$X$'], 936 => ['$\Psi$'], 937 => ['$\Omega$'], 945 => ['$\alpha$'], 946 => ['$\beta$'], 947 => ['$\gamma$'], 948 => ['$\delta$'], 949 => ['$\epsilon$'], 950 => ['$\zeta$'], 951 => ['$\eta$'], 952 => ['$\theta$'], 953 => ['$\iota$'], 954 => ['$\kappa$'], 955 => ['$\lambda$'], 956 => ['$\mu$'], 957 => ['$\nu$'], 958 => ['$\xi$'], 959 => ['$o$'], 960 => ['$\pi$'], 961 => ['$\rho$'], 963 => ['$\sigma$'], 964 => ['$\tau$'], 965 => ['$\upsilon$'], 966 => ['$\phi$'], 967 => ['$\chi$'], 968 => ['$\psi$'], 969 => ['$\omega$'], 962 => ['$\varsigma$'], 977 => ['$\vartheta$'], 982 => ['$\varpi$'], 8230 => ['\ldots'], 8242 => ['$\prime$'], 8254 => ['-'], 8260 => ['/'], 8472 => ['$\wp$'], 8465 => ['$\Im$'], 8476 => ['$\Re$'], 8501 => ['$\aleph$'], 8226 => ['$\bullet$'], 8482 => ['$^{\rm TM}$'], 8592 => ['$\leftarrow$'], 8594 => ['$\rightarrow$'], 8593 => ['$\uparrow$'], 8595 => ['$\downarrow$'], 8596 => ['$\leftrightarrow$'], 8629 => ['$\hookleftarrow$'], 8657 => ['$\Uparrow$'], 8659 => ['$\Downarrow$'], 8656 => ['$\Leftarrow$'], 8658 => ['$\Rightarrow$'], 8660 => ['$\Leftrightarrow$'], 8704 => ['$\forall$'], 8706 => ['$\partial$'], 8707 => ['$\exists$'], 8709 => ['$\emptyset$'], 8711 => ['$\nabla$'], 8712 => ['$\in$'], 8715 => ['$\ni$'], 8713 => ['$\notin$'], 8721 => ['$\sum$'], 8719 => ['$\prod$'], 8722 => ['$-$'], 8727 => ['$\ast$'], 8730 => ['$\surd$'], 8733 => ['$\propto$'], 8734 => ['$\infty$'], 8736 => ['$\angle$'], 8743 => ['$\wedge$'], 8744 => ['$\vee$'], 8745 => ['$\cup$'], 8746 => ['$\cap$'], 8747 => ['$\int$'], 8756 => ['$\therefore$', 'amssymb'], 8764 => ['$\sim$'], 8776 => ['$\approx$'], 8773 => ['$\cong$'], 8800 => ['$\neq$'], 8801 => ['$\equiv$'], 8804 => ['$\leq$'], 8805 => ['$\geq$'], 8834 => ['$\subset$'], 8835 => ['$\supset$'], 8838 => ['$\subseteq$'], 8839 => ['$\supseteq$'], 8836 => ['$\nsubset$', 'amssymb'], 8853 => ['$\oplus$'], 8855 => ['$\otimes$'], 8869 => ['$\perp$'], 8901 => ['$\cdot$'], 8968 => ['$\rceil$'], 8969 => ['$\lceil$'], 8970 => ['$\lfloor$'], 8971 => ['$\rfloor$'], 9001 => ['$\rangle$'], 9002 => ['$\langle$'], 9674 => ['$\lozenge$', 'amssymb'], 9824 => ['$\spadesuit$'], 9827 => ['$\clubsuit$'], 9829 => ['$\heartsuit$'], 9830 => ['$\diamondsuit$'], 38 => ['\&'], 34 => ['"'], 39 => ['\''], 169 => ['\copyright'], 60 => ['\textless'], 62 => ['\textgreater'], 338 => ['\OE'], 339 => ['\oe'], 352 => ['\v{S}'], 353 => ['\v{s}'], 376 => ['\"Y'], 710 => ['\textasciicircum'], 732 => ['\textasciitilde'], 8211 => ['--'], 8212 => ['---'], 8216 => ['`'], 8217 => ['\''], 8220 => ['``'], 8221 => ['\'\''], 8224 => ['\dag'], 8225 => ['\ddag'], 8240 => ['\permil', 'wasysym'], 8364 => ['\euro', 'eurosym'], 8249 => ['\guilsinglleft'], 8250 => ['\guilsinglright'], 8218 => ['\quotesinglbase', 'mathcomp'], 8222 => ['\quotedblbase', 'mathcomp'], 402 => ['\textflorin', 'mathcomp'], 381 => ['\v{Z}'], 382 => ['\v{z}'], 160 => ['~'], 161 => ['\textexclamdown'], 163 => ['\pounds'], 164 => ['\currency', 'wasysym'], 165 => ['\textyen', 'textcomp'], 166 => ['\brokenvert', 'wasysym'], 167 => ['\S'], 171 => ['\guillemotleft'], 187 => ['\guillemotright'], 174 => ['\textregistered'], 170 => ['\textordfeminine'], 172 => ['$\neg$'], 173 => ['\-'], 176 => ['$\degree$', 'mathabx'], 177 => ['$\pm$'], 180 => ['\''], 181 => ['$\mu$'], 182 => ['\P'], 183 => ['$\cdot$'], 186 => ['\textordmasculine'], 162 => ['\cent', 'wasysym'], 185 => ['$^1$'], 178 => ['$^2$'], 179 => ['$^3$'], 189 => ['$\frac{1}{2}$'], 188 => ['$\frac{1}{4}$'], 190 => ['$\frac{3}{4}'], 192 => ['\`A'], 193 => ['\\\'A'], 194 => ['\^A'], 195 => ['\~A'], 196 => ['\"A'], 197 => ['\AA'], 198 => ['\AE'], 199 => ['\cC'], 200 => ['\`E'], 201 => ['\\\'E'], 202 => ['\^E'], 203 => ['\"E'], 204 => ['\`I'], 205 => ['\\\'I'], 206 => ['\^I'], 207 => ['\"I'], 208 => ['$\eth$', 'amssymb'], 209 => ['\~N'], 210 => ['\`O'], 211 => ['\\\'O'], 212 => ['\^O'], 213 => ['\~O'], 214 => ['\"O'], 215 => ['$\times$'], 216 => ['\O'], 217 => ['\`U'], 218 => ['\\\'U'], 219 => ['\^U'], 220 => ['\"U'], 221 => ['\\\'Y'], 222 => ['\Thorn', 'wasysym'], 223 => ['\ss'], 224 => ['\`a'], 225 => ['\\\'a'], 226 => ['\^a'], 227 => ['\~a'], 228 => ['\"a'], 229 => ['\aa'], 230 => ['\ae'], 231 => ['\cc'], 232 => ['\`e'], 233 => ['\\\'e'], 234 => ['\^e'], 235 => ['\"e'], 236 => ['\`i'], 237 => ['\\\'i'], 238 => ['\^i'], 239 => ['\"i'], 240 => ['$\eth$'], 241 => ['\~n'], 242 => ['\`o'], 243 => ['\\\'o'], 244 => ['\^o'], 245 => ['\~o'], 246 => ['\"o'], 247 => ['$\divide$'], 248 => ['\o'], 249 => ['\`u'], 250 => ['\\\'u'], 251 => ['\^u'], 252 => ['\"u'], 253 => ['\\\'y'], 254 => ['\thorn', 'wasysym'], 255 => ['\"y'], 8201 => ['\thinspace'], 8194 => ['\hskip .5em\relax'], 8195 => ['\quad'], } # :nodoc: ENTITY_CONV_TABLE.each {|k,v| ENTITY_CONV_TABLE[k][0].insert(-1, '{}')} def entity_to_latex(entity) text, package = ENTITY_CONV_TABLE[entity.code_point] if text @data[:packages] << package if package text else warning("Couldn't find entity with code #{entity.code_point} in substitution table!") '' end end def convert_entity(el, opts) entity_to_latex(el.value) end TYPOGRAPHIC_SYMS = { :mdash => '---', :ndash => '--', :hellip => '\ldots{}', :laquo_space => '\guillemotleft{}~', :raquo_space => '~\guillemotright{}', :laquo => '\guillemotleft{}', :raquo => '\guillemotright{}' } # :nodoc: def convert_typographic_sym(el, opts) TYPOGRAPHIC_SYMS[el.value] end def convert_smart_quote(el, opts) res = entity_to_latex(smart_quote_entity(el)).chomp('{}') res << "{}" if ((nel = opts[:parent].children[opts[:index]+1]) && nel.type == :smart_quote) || res =~ /\w$/ res end def convert_math(el, opts) @data[:packages] += %w[amssymb amsmath amsthm amsfonts] if el.options[:category] == :block if el.value =~ /\A\s*\\begin\{/ el.value else latex_environment('displaymath', el, el.value) end else "$#{el.value}$" end end def convert_abbreviation(el, opts) @data[:packages] += %w[acronym] "\\ac{#{normalize_abbreviation_key(el.value)}}" end # Normalize the abbreviation key so that it only contains allowed ASCII character def normalize_abbreviation_key(key) key.gsub(/\W/) {|m| m.unpack('H*').first} end # Wrap the +text+ inside a LaTeX environment of type +type+. The element +el+ is passed on to # the method #attribute_list -- the resulting string is appended to both the \\begin and the # \\end lines of the LaTeX environment for easier post-processing of LaTeX environments. def latex_environment(type, el, text) attrs = attribute_list(el) "\\begin{#{type}}#{latex_link_target(el)}#{attrs}\n#{text.rstrip}\n\\end{#{type}}#{attrs}\n" end # Return a string containing a valid \hypertarget command if the element has an ID defined, or # +nil+ otherwise. If the parameter +add_label+ is +true+, a \label command will also be used # additionally to the \hypertarget command. def latex_link_target(el, add_label = false) if (id = el.attr['id']) "\\hypertarget{#{id}}{}" << (add_label ? "\\label{#{id}}" : '') else nil end end # Return a LaTeX comment containing all attributes as 'key="value"' pairs. def attribute_list(el) attrs = el.attr.map {|k,v| v.nil? ? '' : " #{k}=\"#{v.to_s}\""}.compact.sort.join('') attrs = " % #{attrs}" if !attrs.empty? attrs end ESCAPE_MAP = { "^" => "\\^{}", "\\" => "\\textbackslash{}", "~" => "\\ensuremath{\\sim}", "|" => "\\textbar{}", "<" => "\\textless{}", ">" => "\\textgreater{}" }.merge(Hash[*("{}$%&_#".scan(/./).map {|c| [c, "\\#{c}"]}.flatten)]) # :nodoc: ESCAPE_RE = Regexp.union(*ESCAPE_MAP.collect {|k,v| k}) # :nodoc: # Escape the special LaTeX characters in the string +str+. def escape(str) str.gsub(ESCAPE_RE) {|m| ESCAPE_MAP[m]} end end end end kramdown-1.10.0/lib/kramdown/parser/0000755000175000017500000000000012672246616017147 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/parser/kramdown.rb0000644000175000017500000003110012672246616021311 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'strscan' require 'stringio' require 'kramdown/parser' #TODO: use [[:alpha:]] in all regexp to allow parsing of international values in 1.9.1 #NOTE: use @src.pre_match only before other check/match?/... operations, otherwise the content is changed module Kramdown module Parser # Used for parsing a document in kramdown format. # # If you want to extend the functionality of the parser, you need to do the following: # # * Create a new subclass # * add the needed parser methods # * modify the @block_parsers and @span_parsers variables and add the names of your parser # methods # # Here is a small example for an extended parser class that parses ERB style tags as raw text if # they are used as span-level elements (an equivalent block-level parser should probably also be # made to handle the block case): # # require 'kramdown/parser/kramdown' # # class Kramdown::Parser::ERBKramdown < Kramdown::Parser::Kramdown # # def initialize(source, options) # super # @span_parsers.unshift(:erb_tags) # end # # ERB_TAGS_START = /<%.*?%>/ # # def parse_erb_tags # @src.pos += @src.matched_size # @tree.children << Element.new(:raw, @src.matched) # end # define_parser(:erb_tags, ERB_TAGS_START, '<%') # # end # # The new parser can be used like this: # # require 'kramdown/document' # # require the file with the above parser class # # Kramdown::Document.new(input_text, :input => 'ERBKramdown').to_html # class Kramdown < Base include ::Kramdown # Create a new Kramdown parser object with the given +options+. def initialize(source, options) super reset_env @alds = {} @footnotes = {} @link_defs = {} update_link_definitions(@options[:link_defs]) @block_parsers = [:blank_line, :codeblock, :codeblock_fenced, :blockquote, :atx_header, :horizontal_rule, :list, :definition_list, :block_html, :setext_header, :block_math, :table, :footnote_definition, :link_definition, :abbrev_definition, :block_extensions, :eob_marker, :paragraph] @span_parsers = [:emphasis, :codespan, :autolink, :span_html, :footnote_marker, :link, :smart_quotes, :inline_math, :span_extensions, :html_entity, :typographic_syms, :line_break, :escaped_chars] end private_class_method(:new, :allocate) # The source string provided on initialization is parsed into the @root element. def parse configure_parser parse_blocks(@root, adapt_source(source)) update_tree(@root) correct_abbreviations_attributes replace_abbreviations(@root) @footnotes.each {|name,data| update_tree(data[:content])} end ####### protected ####### # :doc: # # Update the parser specific link definitions with the data from +link_defs+ (the value of the # :link_defs option). # # The parameter +link_defs+ is a hash where the keys are possibly unnormalized link IDs and # the values are two element arrays consisting of the link target and a title (can be +nil+). def update_link_definitions(link_defs) link_defs.each {|k,v| @link_defs[normalize_link_id(k)] = v} end # Adapt the object to allow parsing like specified in the options. def configure_parser @parsers = {} (@block_parsers + @span_parsers).each do |name| if self.class.has_parser?(name) @parsers[name] = self.class.parser(name) else raise Kramdown::Error, "Unknown parser: #{name}" end end @span_start, @span_start_re = span_parser_regexps end # Create the needed span parser regexps. def span_parser_regexps(parsers = @span_parsers) span_start = /#{parsers.map {|name| @parsers[name].span_start}.join('|')}/ [span_start, /(?=#{span_start})/] end # Parse all block-level elements in +text+ into the element +el+. def parse_blocks(el, text = nil) @stack.push([@tree, @src, @block_ial]) @tree, @block_ial = el, nil @src = (text.nil? ? @src : ::Kramdown::Utils::StringScanner.new(text, el.options[:location])) status = catch(:stop_block_parsing) do while !@src.eos? @block_parsers.any? do |name| if @src.check(@parsers[name].start_re) send(@parsers[name].method) else false end end || begin warning('Warning: this should not occur - no block parser handled the line') add_text(@src.scan(/.*\n/)) end end end @tree, @src, @block_ial = *@stack.pop status end # Update the tree by parsing all :+raw_text+ elements with the span-level parser (resets the # environment) and by updating the attributes from the IALs. def update_tree(element) last_blank = nil element.children.map! do |child| if child.type == :raw_text last_blank = nil reset_env(:src => ::Kramdown::Utils::StringScanner.new(child.value, element.options[:location]), :text_type => :text) parse_spans(child) child.children elsif child.type == :eob update_attr_with_ial(child.attr, child.options[:ial]) if child.options[:ial] [] elsif child.type == :blank if last_blank last_blank.value << child.value [] else last_blank = child child end else last_blank = nil update_tree(child) update_attr_with_ial(child.attr, child.options[:ial]) if child.options[:ial] update_raw_header_text(child) if child.type == :header child end end.flatten! end # Parse all span-level elements in the source string of @src into +el+. # # If the parameter +stop_re+ (a regexp) is used, parsing is immediately stopped if the regexp # matches and if no block is given or if a block is given and it returns +true+. # # The parameter +parsers+ can be used to specify the (span-level) parsing methods that should # be used for parsing. # # The parameter +text_type+ specifies the type which should be used for created text nodes. def parse_spans(el, stop_re = nil, parsers = nil, text_type = @text_type) @stack.push([@tree, @text_type]) unless @tree.nil? @tree, @text_type = el, text_type span_start = @span_start span_start_re = @span_start_re span_start, span_start_re = span_parser_regexps(parsers) if parsers parsers = parsers || @span_parsers used_re = (stop_re.nil? ? span_start_re : /(?=#{Regexp.union(stop_re, span_start)})/) stop_re_found = false while !@src.eos? && !stop_re_found if result = @src.scan_until(used_re) add_text(result) if stop_re && @src.check(stop_re) stop_re_found = (block_given? ? yield : true) end processed = parsers.any? do |name| if @src.check(@parsers[name].start_re) send(@parsers[name].method) true else false end end unless stop_re_found add_text(@src.getch) if !processed && !stop_re_found else (add_text(@src.rest); @src.terminate) unless stop_re break end end @tree, @text_type = @stack.pop stop_re_found end # Reset the current parsing environment. The parameter +env+ can be used to set initial # values for one or more environment variables. def reset_env(opts = {}) opts = {:text_type => :raw_text, :stack => []}.merge(opts) @src = opts[:src] @tree = opts[:tree] @block_ial = opts[:block_ial] @stack = opts[:stack] @text_type = opts[:text_type] end # Return the current parsing environment. def save_env [@src, @tree, @block_ial, @stack, @text_type] end # Restore the current parsing environment. def restore_env(env) @src, @tree, @block_ial, @stack, @text_type = *env end # Update the given attributes hash +attr+ with the information from the inline attribute list # +ial+ and all referenced ALDs. def update_attr_with_ial(attr, ial) ial[:refs].each do |ref| update_attr_with_ial(attr, ref) if ref = @alds[ref] end if ial[:refs] ial.each do |k,v| if k == IAL_CLASS_ATTR attr[k] = (attr[k] || '') << " #{v}" attr[k].lstrip! elsif k.kind_of?(String) attr[k] = v end end end # Update the raw header text for automatic ID generation. def update_raw_header_text(header) # DEPRECATED: option auto_id_stripping will be removed in 2.0 because then this will be the # default behaviour return unless @options[:auto_id_stripping] raw_text = '' append_text = lambda do |child| if child.type == :text raw_text << child.value else child.children.each {|c| append_text.call(c)} end end append_text.call(header) header.options[:raw_text] = raw_text end # Create a new block-level element, taking care of applying a preceding block IAL if it # exists. This method should always be used for creating a block-level element! def new_block_el(*args) el = Element.new(*args) if @block_ial el.options[:ial] = @block_ial @block_ial = nil end el end @@parsers = {} # Struct class holding all the needed data for one block/span-level parser method. Data = Struct.new(:name, :start_re, :span_start, :method) # Add a parser method # # * with the given +name+, # * using +start_re+ as start regexp # * and, for span parsers, +span_start+ as a String that can be used in a regexp and # which identifies the starting character(s) # # to the registry. The method name is automatically derived from the +name+ or can explicitly # be set by using the +meth_name+ parameter. def self.define_parser(name, start_re, span_start = nil, meth_name = "parse_#{name}") raise "A parser with the name #{name} already exists!" if @@parsers.has_key?(name) @@parsers[name] = Data.new(name, start_re, span_start, meth_name) end # Return the Data structure for the parser +name+. def self.parser(name = nil) @@parsers[name] end # Return +true+ if there is a parser called +name+. def self.has_parser?(name) @@parsers.has_key?(name) end # Regexp for matching indentation (one tab or four spaces) INDENT = /^(?:\t| {4})/ # Regexp for matching the optional space (zero or up to three spaces) OPT_SPACE = / {0,3}/ require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/eob' require 'kramdown/parser/kramdown/paragraph' require 'kramdown/parser/kramdown/header' require 'kramdown/parser/kramdown/blockquote' require 'kramdown/parser/kramdown/table' require 'kramdown/parser/kramdown/codeblock' require 'kramdown/parser/kramdown/horizontal_rule' require 'kramdown/parser/kramdown/list' require 'kramdown/parser/kramdown/link' require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/footnote' require 'kramdown/parser/kramdown/html' require 'kramdown/parser/kramdown/escaped_chars' require 'kramdown/parser/kramdown/html_entity' require 'kramdown/parser/kramdown/line_break' require 'kramdown/parser/kramdown/typographic_symbol' require 'kramdown/parser/kramdown/autolink' require 'kramdown/parser/kramdown/codespan' require 'kramdown/parser/kramdown/emphasis' require 'kramdown/parser/kramdown/smart_quotes' require 'kramdown/parser/kramdown/math' require 'kramdown/parser/kramdown/abbreviation' end end end kramdown-1.10.0/lib/kramdown/parser/base.rb0000644000175000017500000001134212672246616020407 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/utils' require 'kramdown/parser' module Kramdown module Parser # == \Base class for parsers # # This class serves as base class for parsers. It provides common methods that can/should be # used by all parsers, especially by those using StringScanner(Kramdown) for parsing. # # A parser object is used as a throw-away object, i.e. it is only used for storing the needed # state information during parsing. Therefore one can't instantiate a parser object directly but # only use the Base::parse method. # # == Implementing a parser # # Implementing a new parser is rather easy: just derive a new class from this class and put it # in the Kramdown::Parser module -- the latter is needed so that the auto-detection of the new # parser works correctly. Then you need to implement the +#parse+ method which has to contain # the parsing code. # # Have a look at the Base::parse, Base::new and Base#parse methods for additional information! class Base # The hash with the parsing options. attr_reader :options # The array with the parser warnings. attr_reader :warnings # The original source string. attr_reader :source # The root element of element tree that is created from the source string. attr_reader :root # Initialize the parser object with the +source+ string and the parsing +options+. # # The @root element, the @warnings array and @text_type (specifies the default type for newly # created text nodes) are automatically initialized. def initialize(source, options) @source = source @options = Kramdown::Options.merge(options) @root = Element.new(:root, nil, nil, :encoding => (source.encoding rescue nil), :location => 1, :options => {}, :abbrev_defs => {}, :abbrev_attr => {}) @warnings = [] @text_type = :text end private_class_method(:new, :allocate) # Parse the +source+ string into an element tree, possibly using the parsing +options+, and # return the root element of the element tree and an array with warning messages. # # Initializes a new instance of the calling class and then calls the +#parse+ method that must # be implemented by each subclass. def self.parse(source, options = {}) parser = new(source, options) parser.parse [parser.root, parser.warnings] end # Parse the source string into an element tree. # # The parsing code should parse the source provided in @source and build an element tree the # root of which should be @root. # # This is the only method that has to be implemented by sub-classes! def parse raise NotImplementedError end # Add the given warning +text+ to the warning array. def warning(text) @warnings << text #TODO: add position information end # Modify the string +source+ to be usable by the parser (unifies line ending characters to # +\n+ and makes sure +source+ ends with a new line character). def adapt_source(source) if source.respond_to?(:encode) if !source.valid_encoding? raise "The source text contains invalid characters for the used encoding #{source.encoding}" end source = source.encode('UTF-8') end source.gsub(/\r\n?/, "\n").chomp + "\n" end # This helper method adds the given +text+ either to the last element in the +tree+ if it is a # +type+ element or creates a new text element with the given +type+. def add_text(text, tree = @tree, type = @text_type) last = tree.children.last if last && last.type == type last.value << text elsif !text.empty? tree.children << Element.new(type, text, nil, :location => (last && last.options[:location] || tree.options[:location])) end end # Extract the part of the StringScanner +strscan+ backed string specified by the +range+. This # method works correctly under Ruby 1.8 and Ruby 1.9. def extract_string(range, strscan) result = nil if strscan.string.respond_to?(:encoding) begin enc = strscan.string.encoding strscan.string.force_encoding('ASCII-8BIT') result = strscan.string[range].force_encoding(enc) ensure strscan.string.force_encoding(enc) end else result = strscan.string[range] end result end end end end kramdown-1.10.0/lib/kramdown/parser/gfm.rb0000644000175000017500000000575712672246616020263 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser' module Kramdown module Parser class GFM < Kramdown::Parser::Kramdown def initialize(source, options) super @span_parsers.delete(:line_break) if @options[:hard_wrap] {:codeblock_fenced => :codeblock_fenced_gfm, :atx_header => :atx_header_gfm}.each do |current, replacement| i = @block_parsers.index(current) @block_parsers.delete(current) @block_parsers.insert(i, replacement) end i = @span_parsers.index(:escaped_chars) @span_parsers[i] = :escaped_chars_gfm if i @span_parsers << :strikethrough_gfm end def parse super add_hard_line_breaks(@root) if @options[:hard_wrap] end def add_hard_line_breaks(element) element.children.map! do |child| if child.type == :text && child.value =~ /\n/ children = [] lines = child.value.split(/\n/, -1) omit_trailing_br = (Kramdown::Element.category(element) == :block && element.children[-1] == child && lines[-1].empty?) lines.each_with_index do |line, index| new_element_options = { :location => child.options[:location] + index } children << Element.new(:text, (index > 0 ? "\n#{line}" : line), nil, new_element_options) children << Element.new(:br, nil, nil, new_element_options) if index < lines.size - 2 || (index == lines.size - 2 && !omit_trailing_br) end children elsif child.type == :html_element child else add_hard_line_breaks(child) child end end.flatten! end ATX_HEADER_START = /^\#{1,6}\s/ define_parser(:atx_header_gfm, ATX_HEADER_START, nil, 'parse_atx_header') FENCED_CODEBLOCK_MATCH = /^(([~`]){3,})\s*?((\S+)(?:\?\S*)?)?\s*?\n(.*?)^\1\2*\s*?\n/m define_parser(:codeblock_fenced_gfm, /^[~`]{3,}/, nil, 'parse_codeblock_fenced') STRIKETHROUGH_DELIM = /~~/ STRIKETHROUGH_MATCH = /#{STRIKETHROUGH_DELIM}[^\s~](.*?)[^\s~]#{STRIKETHROUGH_DELIM}/m define_parser(:strikethrough_gfm, STRIKETHROUGH_MATCH, '~~') def parse_strikethrough_gfm line_number = @src.current_line_number @src.pos += @src.matched_size el = Element.new(:html_element, 'del', {}, :category => :span, :line => line_number) @tree.children << el env = save_env reset_env(:src => Kramdown::Utils::StringScanner.new(@src.matched[2..-3], line_number), :text_type => :text) parse_spans(el) restore_env(env) el end ESCAPED_CHARS_GFM = /\\([\\.*_+`<>()\[\]{}#!:\|"'\$=\-~])/ define_parser(:escaped_chars_gfm, ESCAPED_CHARS_GFM, '\\\\', :parse_escaped_chars) end end end kramdown-1.10.0/lib/kramdown/parser/markdown.rb0000644000175000017500000000364012672246616021321 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser' module Kramdown module Parser # Used for parsing a document in Markdown format. # # This parser is based on the kramdown parser and removes the parser methods for the additional # non-Markdown features. However, since some things are handled differently by the kramdown # parser methods (like deciding when a list item contains just text), this parser differs from # real Markdown parsers in some respects. # # Note, though, that the parser basically fails just one of the Markdown test cases (some others # also fail but those failures are negligible). class Markdown < Kramdown # Array with all the parsing methods that should be removed from the standard kramdown parser. EXTENDED = [:codeblock_fenced, :table, :definition_list, :footnote_definition, :abbrev_definition, :block_math, :block_extensions, :footnote_marker, :smart_quotes, :inline_math, :span_extensions, :typographic_syms] def initialize(source, options) # :nodoc: super @block_parsers.delete_if {|i| EXTENDED.include?(i)} @span_parsers.delete_if {|i| EXTENDED.include?(i)} end # :stopdoc: BLOCK_BOUNDARY = /#{BLANK_LINE}|#{EOB_MARKER}|\Z/ LAZY_END = /#{BLANK_LINE}|#{EOB_MARKER}|^#{OPT_SPACE}#{LAZY_END_HTML_STOP}|^#{OPT_SPACE}#{LAZY_END_HTML_START}|\Z/ CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:#{INDENT}[ \t]*\S.*\n)+)*/ PARAGRAPH_END = LAZY_END IAL_RAND_CHARS = (('a'..'z').to_a + ('0'..'9').to_a) IAL_RAND_STRING = (1..20).collect {|a| IAL_RAND_CHARS[rand(IAL_RAND_CHARS.size)]}.join LIST_ITEM_IAL = /^\s*(#{IAL_RAND_STRING})?\s*\n/ IAL_SPAN_START = LIST_ITEM_IAL # :startdoc: end end end kramdown-1.10.0/lib/kramdown/parser/html.rb0000644000175000017500000005412112672246616020443 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'rexml/parsers/baseparser' require 'strscan' require 'kramdown/utils' require 'kramdown/parser' module Kramdown module Parser # Used for parsing a HTML document. # # The parsing code is in the Parser module that can also be used by other parsers. class Html < Base # Contains all constants that are used when parsing. module Constants #:stopdoc: # The following regexps are based on the ones used by REXML, with some slight modifications. HTML_DOCTYPE_RE = //im HTML_COMMENT_RE = //m HTML_INSTRUCTION_RE = /<\?(.*?)\?>/m HTML_ATTRIBUTE_RE = /\s*(#{REXML::Parsers::BaseParser::UNAME_STR})(?:\s*=\s*(["'])(.*?)\2)?/m HTML_TAG_RE = /<((?>#{REXML::Parsers::BaseParser::UNAME_STR}))\s*((?>\s+#{REXML::Parsers::BaseParser::UNAME_STR}(?:\s*=\s*(["']).*?\3)?)*)\s*(\/)?>/m HTML_TAG_CLOSE_RE = /<\/(#{REXML::Parsers::BaseParser::UNAME_STR})\s*>/m HTML_ENTITY_RE = /&([\w:][\-\w\.:]*);|&#(\d+);|&\#x([0-9a-fA-F]+);/ HTML_CONTENT_MODEL_BLOCK = %w{address applet article aside blockquote body dd details div dl fieldset figure figcaption footer form header hgroup iframe li map menu nav noscript object section summary td} HTML_CONTENT_MODEL_SPAN = %w{a abbr acronym b bdo big button cite caption del dfn dt em h1 h2 h3 h4 h5 h6 i ins label legend optgroup p q rb rbc rp rt rtc ruby select small span strong sub sup th tt} HTML_CONTENT_MODEL_RAW = %w{script style math option textarea pre code kbd samp var} # The following elements are also parsed as raw since they need child elements that cannot # be expressed using kramdown syntax: colgroup table tbody thead tfoot tr ul ol HTML_CONTENT_MODEL = Hash.new {|h,k| h[k] = :raw} HTML_CONTENT_MODEL_BLOCK.each {|i| HTML_CONTENT_MODEL[i] = :block} HTML_CONTENT_MODEL_SPAN.each {|i| HTML_CONTENT_MODEL[i] = :span} HTML_CONTENT_MODEL_RAW.each {|i| HTML_CONTENT_MODEL[i] = :raw} # Some HTML elements like script belong to both categories (i.e. are valid in block and # span HTML) and don't appear therefore! # script, textarea HTML_SPAN_ELEMENTS = %w{a abbr acronym b big bdo br button cite code del dfn em i img input ins kbd label mark option q rb rbc rp rt rtc ruby samp select small span strong sub sup tt u var} HTML_BLOCK_ELEMENTS = %w{address article aside applet body blockquote caption col colgroup dd div dl dt fieldset figcaption footer form h1 h2 h3 h4 h5 h6 header hgroup hr html head iframe legend menu li map nav ol optgroup p pre section summary table tbody td th thead tfoot tr ul} HTML_ELEMENTS_WITHOUT_BODY = %w{area base br col command embed hr img input keygen link meta param source track wbr} end # Contains the parsing methods. This module can be mixed into any parser to get HTML parsing # functionality. The only thing that must be provided by the class are instance variable # @stack for storing the needed state and @src (instance of StringScanner) for the actual # parsing. module Parser include Constants # Process the HTML start tag that has already be scanned/checked via @src. # # Does the common processing steps and then yields to the caller for further processing # (first parameter is the created element; the second parameter is +true+ if the HTML # element is already closed, ie. contains no body; the third parameter specifies whether the # body - and the end tag - need to be handled in case closed=false). def handle_html_start_tag(line = nil) # :yields: el, closed, handle_body name = @src[1].downcase closed = !@src[4].nil? attrs = parse_html_attributes(@src[2], line) el = Element.new(:html_element, name, attrs, :category => :block) el.options[:location] = line if line @tree.children << el if !closed && HTML_ELEMENTS_WITHOUT_BODY.include?(el.value) closed = true end if name == 'script' || name == 'style' handle_raw_html_tag(name) yield(el, false, false) else yield(el, closed, true) end end # Parses the given string for HTML attributes and returns the resulting hash. # # If the optional +line+ parameter is supplied, it is used in warning messages. def parse_html_attributes(str, line = nil) attrs = Utils::OrderedHash.new str.scan(HTML_ATTRIBUTE_RE).each do |attr, sep, val| attr.downcase! if attrs.has_key?(attr) warning("Duplicate HTML attribute '#{attr}' on line #{line || '?'} - overwriting previous one") end attrs[attr] = val || "" end attrs end # Handle the raw HTML tag at the current position. def handle_raw_html_tag(name) curpos = @src.pos if @src.scan_until(/(?=<\/#{name}\s*>)/mi) add_text(extract_string(curpos...@src.pos, @src), @tree.children.last, :raw) @src.scan(HTML_TAG_CLOSE_RE) else add_text(@src.rest, @tree.children.last, :raw) @src.terminate warning("Found no end tag for '#{name}' - auto-closing it") end end HTML_RAW_START = /(?=<(#{REXML::Parsers::BaseParser::UNAME_STR}|\/|!--|\?))/ # :nodoc: # Parse raw HTML from the current source position, storing the found elements in +el+. # Parsing continues until one of the following criteria are fulfilled: # # - The end of the document is reached. # - The matching end tag for the element +el+ is found (only used if +el+ is an HTML # element). # # When an HTML start tag is found, processing is deferred to #handle_html_start_tag, # providing the block given to this method. def parse_raw_html(el, &block) @stack.push(@tree) @tree = el done = false while !@src.eos? && !done if result = @src.scan_until(HTML_RAW_START) add_text(result, @tree, :text) line = @src.current_line_number if result = @src.scan(HTML_COMMENT_RE) @tree.children << Element.new(:xml_comment, result, nil, :category => :block, :location => line) elsif result = @src.scan(HTML_INSTRUCTION_RE) @tree.children << Element.new(:xml_pi, result, nil, :category => :block, :location => line) elsif @src.scan(HTML_TAG_RE) if method(:handle_html_start_tag).arity.abs >= 1 handle_html_start_tag(line, &block) else handle_html_start_tag(&block) # DEPRECATED: method needs to accept line number in 2.0 end elsif @src.scan(HTML_TAG_CLOSE_RE) if @tree.value == @src[1].downcase done = true else warning("Found invalidly used HTML closing tag for '#{@src[1].downcase}' on line #{line} - ignoring it") end else add_text(@src.getch, @tree, :text) end else add_text(@src.rest, @tree, :text) @src.terminate warning("Found no end tag for '#{@tree.value}' on line #{@tree.options[:location]} - auto-closing it") if @tree.type == :html_element done = true end end @tree = @stack.pop end end # Converts HTML elements to native elements if possible. class ElementConverter # :stopdoc: include Constants include ::Kramdown::Utils::Entities REMOVE_TEXT_CHILDREN = %w{html head hgroup ol ul dl table colgroup tbody thead tfoot tr select optgroup} WRAP_TEXT_CHILDREN = %w{body section nav article aside header footer address div li dd blockquote figure figcaption fieldset form} REMOVE_WHITESPACE_CHILDREN = %w{body section nav article aside header footer address div li dd blockquote figure figcaption td th fieldset form} STRIP_WHITESPACE = %w{address article aside blockquote body caption dd div dl dt fieldset figcaption form footer header h1 h2 h3 h4 h5 h6 legend li nav p section td th} SIMPLE_ELEMENTS = %w{em strong blockquote hr br img p thead tbody tfoot tr td th ul ol dl li dl dt dd} def initialize(root) @root = root end def self.convert(root, el = root) new(root).process(el) end # Convert the element +el+ and its children. def process(el, do_conversion = true, preserve_text = false, parent = nil) case el.type when :xml_comment, :xml_pi ptype = if parent.nil? 'div' else case parent.type when :html_element then parent.value when :code_span then 'code' when :code_block then 'pre' when :header then 'h1' else parent.type.to_s end end el.options.replace({:category => (HTML_CONTENT_MODEL[ptype] == :span ? :span : :block)}) return when :html_element when :root el.children.each {|c| process(c)} remove_whitespace_children(el) return else return end mname = "convert_#{el.value}" if do_conversion && self.class.method_defined?(mname) send(mname, el) else type = el.value remove_text_children(el) if do_conversion && REMOVE_TEXT_CHILDREN.include?(type) if do_conversion && SIMPLE_ELEMENTS.include?(type) set_basics(el, type.intern) process_children(el, do_conversion, preserve_text) else process_html_element(el, do_conversion, preserve_text) end if do_conversion strip_whitespace(el) if STRIP_WHITESPACE.include?(type) remove_whitespace_children(el) if REMOVE_WHITESPACE_CHILDREN.include?(type) wrap_text_children(el) if WRAP_TEXT_CHILDREN.include?(type) end end end def process_children(el, do_conversion = true, preserve_text = false) el.children.map! do |c| if c.type == :text process_text(c.value, preserve_text || !do_conversion) else process(c, do_conversion, preserve_text, el) c end end.flatten! end # Process the HTML text +raw+: compress whitespace (if +preserve+ is +false+) and convert # entities in entity elements. def process_text(raw, preserve = false) raw.gsub!(/\s+/, ' ') unless preserve src = Kramdown::Utils::StringScanner.new(raw) result = [] while !src.eos? if tmp = src.scan_until(/(?=#{HTML_ENTITY_RE})/) result << Element.new(:text, tmp) src.scan(HTML_ENTITY_RE) val = src[1] || (src[2] && src[2].to_i) || src[3].hex result << if %w{lsquo rsquo ldquo rdquo}.include?(val) Element.new(:smart_quote, val.intern) elsif %w{mdash ndash hellip laquo raquo}.include?(val) Element.new(:typographic_sym, val.intern) else begin Element.new(:entity, entity(val), nil, :original => src.matched) rescue ::Kramdown::Error src.pos -= src.matched_size - 1 Element.new(:entity, ::Kramdown::Utils::Entities.entity('amp')) end end else result << Element.new(:text, src.rest) src.terminate end end result end def process_html_element(el, do_conversion = true, preserve_text = false) el.options.replace(:category => HTML_SPAN_ELEMENTS.include?(el.value) ? :span : :block, :content_model => (do_conversion ? HTML_CONTENT_MODEL[el.value] : :raw)) process_children(el, do_conversion, preserve_text) end def remove_text_children(el) el.children.delete_if {|c| c.type == :text} end def wrap_text_children(el) tmp = [] last_is_p = false el.children.each do |c| if Element.category(c) != :block || c.type == :text if !last_is_p tmp << Element.new(:p, nil, nil, :transparent => true) last_is_p = true end tmp.last.children << c tmp else tmp << c last_is_p = false end end el.children = tmp end def strip_whitespace(el) return if el.children.empty? if el.children.first.type == :text el.children.first.value.lstrip! end if el.children.last.type == :text el.children.last.value.rstrip! end end def remove_whitespace_children(el) i = -1 el.children = el.children.reject do |c| i += 1 c.type == :text && c.value.strip.empty? && (i == 0 || i == el.children.length - 1 || (Element.category(el.children[i-1]) == :block && Element.category(el.children[i+1]) == :block)) end end def set_basics(el, type, opts = {}) el.type = type el.options.replace(opts) el.value = nil end def extract_text(el, raw) raw << el.value.to_s if el.type == :text el.children.each {|c| extract_text(c, raw)} end def convert_textarea(el) process_html_element(el, true, true) end def convert_a(el) if el.attr['href'] set_basics(el, :a) process_children(el) else process_html_element(el, false) end end EMPHASIS_TYPE_MAP = {'em' => :em, 'i' => :em, 'strong' => :strong, 'b' => :strong} def convert_em(el) text = '' extract_text(el, text) if text =~ /\A\s/ || text =~ /\s\z/ process_html_element(el, false) else set_basics(el, EMPHASIS_TYPE_MAP[el.value]) process_children(el) end end %w{b strong i}.each do |i| alias_method("convert_#{i}".to_sym, :convert_em) end def convert_h1(el) set_basics(el, :header, :level => el.value[1..1].to_i) extract_text(el, el.options[:raw_text] = '') process_children(el) end %w{h2 h3 h4 h5 h6}.each do |i| alias_method("convert_#{i}".to_sym, :convert_h1) end def convert_code(el) raw = '' extract_text(el, raw) result = process_text(raw, true) begin str = result.inject('') do |mem, c| if c.type == :text mem << c.value elsif c.type == :entity if [60, 62, 34, 38].include?(c.value.code_point) mem << c.value.code_point.chr else mem << c.value.char end elsif c.type == :smart_quote || c.type == :typographic_sym mem << entity(c.value.to_s).char else raise "Bug - please report" end end result.clear result << Element.new(:text, str) rescue end if result.length > 1 || result.first.type != :text process_html_element(el, false, true) else if el.value == 'code' set_basics(el, :codespan) el.attr['class'].gsub!(/\s+\bhighlighter-\w+\b|\bhighlighter-\w+\b\s*/, '') if el.attr['class'] else set_basics(el, :codeblock) if el.children.size == 1 && el.children.first.value == 'code' value = (el.children.first.attr['class'] || '').scan(/\blanguage-\S+/).first el.attr['class'] = "#{value} #{el.attr['class']}".rstrip if value end end el.value = result.first.value el.children.clear end end alias :convert_pre :convert_code def convert_table(el) if !is_simple_table?(el) process_html_element(el, false) return end remove_text_children(el) process_children(el) set_basics(el, :table) calc_alignment = lambda do |c| if c.type == :tr el.options[:alignment] = c.children.map do |td| if td.attr['style'] td.attr['style'].slice!(/(?:;\s*)?text-align:\s+(center|left|right)/) td.attr.delete('style') if td.attr['style'].strip.empty? $1 ? $1.to_sym : :default else :default end end else c.children.each {|cc| calc_alignment.call(cc)} end end calc_alignment.call(el) el.children.delete_if {|c| c.type == :html_element} change_th_type = lambda do |c| if c.type == :th c.type = :td else c.children.each {|cc| change_th_type.call(cc)} end end change_th_type.call(el) if el.children.first.type == :tr tbody = Element.new(:tbody) tbody.children = el.children el.children = [tbody] end end def is_simple_table?(el) only_phrasing_content = lambda do |c| c.children.all? do |cc| (cc.type == :text || !HTML_BLOCK_ELEMENTS.include?(cc.value)) && only_phrasing_content.call(cc) end end check_cells = Proc.new do |c| if c.value == 'th' || c.value == 'td' return false if !only_phrasing_content.call(c) else c.children.each {|cc| check_cells.call(cc)} end end check_cells.call(el) nr_cells = 0 check_nr_cells = lambda do |t| if t.value == 'tr' count = t.children.select {|cc| cc.value == 'th' || cc.value == 'td'}.length if count != nr_cells if nr_cells == 0 nr_cells = count else nr_cells = -1 break end end else t.children.each {|cc| check_nr_cells.call(cc)} end end check_nr_cells.call(el) return false if nr_cells == -1 alignment = nil check_alignment = Proc.new do |t| if t.value == 'tr' cur_alignment = t.children.select {|cc| cc.value == 'th' || cc.value == 'td'}.map do |cell| md = /text-align:\s+(center|left|right|justify|inherit)/.match(cell.attr['style'].to_s) return false if md && (md[1] == 'justify' || md[1] == 'inherit') md.nil? ? :default : md[1] end alignment = cur_alignment if alignment.nil? return false if alignment != cur_alignment else t.children.each {|cc| check_alignment.call(cc)} end end check_alignment.call(el) check_rows = lambda do |t, type| t.children.all? {|r| (r.value == 'tr' || r.type == :text) && r.children.all? {|c| c.value == type || c.type == :text}} end check_rows.call(el, 'td') || (el.children.all? do |t| t.type == :text || (t.value == 'thead' && check_rows.call(t, 'th')) || ((t.value == 'tfoot' || t.value == 'tbody') && check_rows.call(t, 'td')) end && el.children.any? {|t| t.value == 'tbody'}) end def convert_script(el) if !is_math_tag?(el) process_html_element(el) else handle_math_tag(el) end end def is_math_tag?(el) el.attr['type'].to_s =~ /\bmath\/tex\b/ end def handle_math_tag(el) set_basics(el, :math, :category => (el.attr['type'] =~ /mode=display/ ? :block : :span)) el.value = el.children.shift.value.sub(/\A(?:%\s*)?\z/m, '\1') el.attr.delete('type') end end include Parser # Parse the source string provided on initialization as HTML document. def parse @stack, @tree = [], @root @src = Kramdown::Utils::StringScanner.new(adapt_source(source)) while true if result = @src.scan(/\s*#{HTML_INSTRUCTION_RE}/) @tree.children << Element.new(:xml_pi, result.strip, nil, :category => :block) elsif result = @src.scan(/\s*#{HTML_DOCTYPE_RE}/) # ignore the doctype elsif result = @src.scan(/\s*#{HTML_COMMENT_RE}/) @tree.children << Element.new(:xml_comment, result.strip, nil, :category => :block) else break end end tag_handler = lambda do |c, closed, handle_body| parse_raw_html(c, &tag_handler) if !closed && handle_body end parse_raw_html(@tree, &tag_handler) ElementConverter.convert(@tree) end end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/0000755000175000017500000000000012672246616020771 5ustar uwabamiuwabamikramdown-1.10.0/lib/kramdown/parser/kramdown/block_boundary.rb0000644000175000017500000000152412672246616024315 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/eob' module Kramdown module Parser class Kramdown BLOCK_BOUNDARY = /#{BLANK_LINE}|#{EOB_MARKER}|#{IAL_BLOCK_START}|\Z/ # Return +true+ if we are after a block boundary. def after_block_boundary? !@tree.children.last || @tree.children.last.type == :blank || (@tree.children.last.type == :eob && @tree.children.last.value.nil?) || @block_ial end # Return +true+ if we are before a block boundary. def before_block_boundary? @src.check(self.class::BLOCK_BOUNDARY) end end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/line_break.rb0000644000175000017500000000105612672246616023413 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown LINE_BREAK = /( |\\\\)(?=\n)/ # Parse the line break at the current location. def parse_line_break @tree.children << Element.new(:br, nil, nil, :location => @src.current_line_number) @src.pos += @src.matched_size end define_parser(:line_break, LINE_BREAK, '( |\\\\)(?=\n)') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/eob.rb0000644000175000017500000000076312672246616022071 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown EOB_MARKER = /^\^\s*?\n/ # Parse the EOB marker at the current location. def parse_eob_marker @src.pos += @src.matched_size @tree.children << new_block_el(:eob) true end define_parser(:eob_marker, EOB_MARKER) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/autolink.rb0000644000175000017500000000200512672246616023141 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown if RUBY_VERSION == '1.8.5' ACHARS = '\w\x80-\xFF' elsif RUBY_VERSION < '1.9.0' ACHARS = '\w' else ACHARS = '[[:alnum:]]_' end AUTOLINK_START_STR = "<((mailto|https?|ftps?):.+?|[-.#{ACHARS}]+@[-#{ACHARS}]+(?:\.[-#{ACHARS}]+)*\.[a-z]+)>" AUTOLINK_START = /#{AUTOLINK_START_STR}/u # Parse the autolink at the current location. def parse_autolink start_line_number = @src.current_line_number @src.pos += @src.matched_size href = (@src[2].nil? ? "mailto:#{@src[1]}" : @src[1]) el = Element.new(:a, nil, {'href' => href}, :location => start_line_number) add_text(@src[1].sub(/^mailto:/, ''), el) @tree.children << el end define_parser(:autolink, AUTOLINK_START, '<') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/paragraph.rb0000644000175000017500000000334012672246616023263 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/eob' require 'kramdown/parser/kramdown/list' require 'kramdown/parser/kramdown/html' module Kramdown module Parser class Kramdown LAZY_END_HTML_SPAN_ELEMENTS = HTML_SPAN_ELEMENTS + %w{script} LAZY_END_HTML_START = /<(?>(?!(?:#{LAZY_END_HTML_SPAN_ELEMENTS.join('|')})\b)#{REXML::Parsers::BaseParser::UNAME_STR})/ LAZY_END_HTML_STOP = /<\/(?!(?:#{LAZY_END_HTML_SPAN_ELEMENTS.join('|')})\b)#{REXML::Parsers::BaseParser::UNAME_STR}\s*>/m LAZY_END = /#{BLANK_LINE}|#{IAL_BLOCK_START}|#{EOB_MARKER}|^#{OPT_SPACE}#{LAZY_END_HTML_STOP}|^#{OPT_SPACE}#{LAZY_END_HTML_START}|\Z/ PARAGRAPH_START = /^#{OPT_SPACE}[^ \t].*?\n/ PARAGRAPH_MATCH = /^.*?\n/ PARAGRAPH_END = /#{LAZY_END}|#{DEFINITION_LIST_START}/ # Parse the paragraph at the current location. def parse_paragraph start_line_number = @src.current_line_number result = @src.scan(PARAGRAPH_MATCH) while !@src.match?(self.class::PARAGRAPH_END) result << @src.scan(PARAGRAPH_MATCH) end result.rstrip! if @tree.children.last && @tree.children.last.type == :p @tree.children.last.children.first.value << "\n" << result else @tree.children << new_block_el(:p, nil, nil, :location => start_line_number) result.lstrip! add_text(result, @tree.children.last) end true end define_parser(:paragraph, PARAGRAPH_START) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/codespan.rb0000644000175000017500000000214612672246616023115 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown CODESPAN_DELIMITER = /`+/ # Parse the codespan at the current scanner location. def parse_codespan start_line_number = @src.current_line_number result = @src.scan(CODESPAN_DELIMITER) simple = (result.length == 1) saved_pos = @src.save_pos if simple && @src.pre_match =~ /\s\Z/ && @src.match?(/\s/) add_text(result) return end if text = @src.scan_until(/#{result}/) text.sub!(/#{result}\Z/, '') if !simple text = text[1..-1] if text[0..0] == ' ' text = text[0..-2] if text[-1..-1] == ' ' end @tree.children << Element.new(:codespan, text, nil, :location => start_line_number) else @src.revert_pos(saved_pos) add_text(result) end end define_parser(:codespan, CODESPAN_DELIMITER, '`') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/horizontal_rule.rb0000644000175000017500000000120512672246616024534 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown HR_START = /^#{OPT_SPACE}(\*|-|_)[ \t]*\1[ \t]*\1(\1|[ \t])*\n/ # Parse the horizontal rule at the current location. def parse_horizontal_rule start_line_number = @src.current_line_number @src.pos += @src.matched_size @tree.children << new_block_el(:hr, nil, nil, :location => start_line_number) true end define_parser(:horizontal_rule, HR_START) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/html_entity.rb0000644000175000017500000000203312672246616023654 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/html' module Kramdown module Parser class Kramdown # Parse the HTML entity at the current location. def parse_html_entity start_line_number = @src.current_line_number @src.pos += @src.matched_size begin @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity(@src[1] || (@src[2] && @src[2].to_i) || @src[3].hex), nil, :original => @src.matched, :location => start_line_number) rescue ::Kramdown::Error @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('amp'), nil, :location => start_line_number) add_text(@src.matched[1..-1]) end end define_parser(:html_entity, Kramdown::Parser::Html::Constants::HTML_ENTITY_RE, '&') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/html.rb0000644000175000017500000001454512672246616022273 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/html' module Kramdown module Parser class Kramdown include Kramdown::Parser::Html::Parser # Mapping of markdown attribute value to content model. I.e. :raw when "0", :default when "1" # (use default content model for the HTML element), :span when "span", :block when block and # for everything else +nil+ is returned. HTML_MARKDOWN_ATTR_MAP = {"0" => :raw, "1" => :default, "span" => :span, "block" => :block} TRAILING_WHITESPACE = /[ \t]*\n/ def handle_kramdown_html_tag(el, closed, handle_body) if @block_ial el.options[:ial] = @block_ial @block_ial = nil end content_model = if @tree.type != :html_element || @tree.options[:content_model] != :raw (@options[:parse_block_html] ? HTML_CONTENT_MODEL[el.value] : :raw) else :raw end if val = HTML_MARKDOWN_ATTR_MAP[el.attr.delete('markdown')] content_model = (val == :default ? HTML_CONTENT_MODEL[el.value] : val) end @src.scan(TRAILING_WHITESPACE) if content_model == :block el.options[:content_model] = content_model el.options[:is_closed] = closed if !closed && handle_body if content_model == :block if !parse_blocks(el) warning("Found no end tag for '#{el.value}' (line #{el.options[:location]}) - auto-closing it") end elsif content_model == :span curpos = @src.pos if @src.scan_until(/(?=<\/#{el.value}\s*>)/mi) add_text(extract_string(curpos...@src.pos, @src), el) @src.scan(HTML_TAG_CLOSE_RE) else add_text(@src.rest, el) @src.terminate warning("Found no end tag for '#{el.value}' (line #{el.options[:location]}) - auto-closing it") end else parse_raw_html(el, &method(:handle_kramdown_html_tag)) end @src.scan(TRAILING_WHITESPACE) unless (@tree.type == :html_element && @tree.options[:content_model] == :raw) end end HTML_BLOCK_START = /^#{OPT_SPACE}<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/ # Parse the HTML at the current position as block-level HTML. def parse_block_html line = @src.current_line_number if result = @src.scan(HTML_COMMENT_RE) @tree.children << Element.new(:xml_comment, result, nil, :category => :block, :location => line) @src.scan(TRAILING_WHITESPACE) true elsif result = @src.scan(HTML_INSTRUCTION_RE) @tree.children << Element.new(:xml_pi, result, nil, :category => :block, :location => line) @src.scan(TRAILING_WHITESPACE) true else if result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase) @src.pos += @src.matched_size handle_html_start_tag(line, &method(:handle_kramdown_html_tag)) Kramdown::Parser::Html::ElementConverter.convert(@root, @tree.children.last) if @options[:html_to_native] true elsif result = @src.check(/^#{OPT_SPACE}#{HTML_TAG_CLOSE_RE}/) && !HTML_SPAN_ELEMENTS.include?(@src[1].downcase) name = @src[1].downcase if @tree.type == :html_element && @tree.value == name @src.pos += @src.matched_size throw :stop_block_parsing, :found else false end else false end end end define_parser(:block_html, HTML_BLOCK_START) HTML_SPAN_START = /<(#{REXML::Parsers::BaseParser::UNAME_STR}|\?|!--|\/)/ # Parse the HTML at the current position as span-level HTML. def parse_span_html line = @src.current_line_number if result = @src.scan(HTML_COMMENT_RE) @tree.children << Element.new(:xml_comment, result, nil, :category => :span, :location => line) elsif result = @src.scan(HTML_INSTRUCTION_RE) @tree.children << Element.new(:xml_pi, result, nil, :category => :span, :location => line) elsif result = @src.scan(HTML_TAG_CLOSE_RE) warning("Found invalidly used HTML closing tag for '#{@src[1]}' on line #{line}") add_text(result) elsif result = @src.scan(HTML_TAG_RE) tag_name = @src[1].downcase if HTML_BLOCK_ELEMENTS.include?(tag_name) warning("Found block HTML tag '#{tag_name}' in span-level text on line #{line}") add_text(result) return end attrs = parse_html_attributes(@src[2], line) attrs.each {|name, value| value.gsub!(/\n+/, ' ')} do_parsing = (HTML_CONTENT_MODEL[tag_name] == :raw || @tree.options[:content_model] == :raw ? false : @options[:parse_span_html]) if val = HTML_MARKDOWN_ATTR_MAP[attrs.delete('markdown')] if val == :block warning("Cannot use block-level parsing in span-level HTML tag (line #{line}) - using default mode") elsif val == :span do_parsing = true elsif val == :default do_parsing = HTML_CONTENT_MODEL[tag_name] != :raw elsif val == :raw do_parsing = false end end el = Element.new(:html_element, tag_name, attrs, :category => :span, :location => line, :content_model => (do_parsing ? :span : :raw), :is_closed => !!@src[4]) @tree.children << el stop_re = /<\/#{Regexp.escape(tag_name)}\s*>/i if !@src[4] && !HTML_ELEMENTS_WITHOUT_BODY.include?(el.value) if parse_spans(el, stop_re, (do_parsing ? nil : [:span_html])) @src.scan(stop_re) else warning("Found no end tag for '#{el.value}' (line #{line}) - auto-closing it") add_text(@src.rest, el) @src.terminate end end Kramdown::Parser::Html::ElementConverter.convert(@root, el) if @options[:html_to_native] else add_text(@src.getch) end end define_parser(:span_html, HTML_SPAN_START, '<') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/list.rb0000644000175000017500000002215112672246616022272 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # 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 } result.sub!(indent_re, '') if !nested_list_found && result =~ LIST_START item.value << '' nested_list_found = true 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) 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 kramdown-1.10.0/lib/kramdown/parser/kramdown/table.rb0000644000175000017500000001452112672246616022410 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/block_boundary' module Kramdown module Parser class Kramdown TABLE_SEP_LINE = /^([+|: -]*?-[+|: -]*?)[ \t]*\n/ TABLE_HSEP_ALIGN = /[ ]?(:?)-+(:?)[ ]?/ TABLE_FSEP_LINE = /^[+|: =]*?=[+|: =]*?[ \t]*\n/ TABLE_ROW_LINE = /^(.*?)[ \t]*\n/ TABLE_PIPE_CHECK = /(?:\||.*?[^\\\n]\|)/ TABLE_LINE = /#{TABLE_PIPE_CHECK}.*?\n/ TABLE_START = /^#{OPT_SPACE}(?=\S)#{TABLE_LINE}/ # Parse the table at the current location. def parse_table return false if !after_block_boundary? saved_pos = @src.save_pos orig_pos = @src.pos table = new_block_el(:table, nil, nil, :alignment => [], :location => @src.current_line_number) leading_pipe = (@src.check(TABLE_LINE) =~ /^\s*\|/) @src.scan(TABLE_SEP_LINE) rows = [] has_footer = false columns = 0 add_container = lambda do |type, force| if !has_footer || type != :tbody || force cont = Element.new(type) cont.children, rows = rows, [] table.children << cont end end while !@src.eos? break if !@src.check(TABLE_LINE) if @src.scan(TABLE_SEP_LINE) if rows.empty? # nothing to do, ignoring multiple consecutive separator lines elsif table.options[:alignment].empty? && !has_footer add_container.call(:thead, false) table.options[:alignment] = @src[1].scan(TABLE_HSEP_ALIGN).map do |left, right| (left.empty? && right.empty? && :default) || (right.empty? && :left) || (left.empty? && :right) || :center end else # treat as normal separator line add_container.call(:tbody, false) end elsif @src.scan(TABLE_FSEP_LINE) add_container.call(:tbody, true) if !rows.empty? has_footer = true elsif @src.scan(TABLE_ROW_LINE) trow = Element.new(:tr) # parse possible code spans on the line and correctly split the line into cells env = save_env cells = [] @src[1].split(/(.*?<\/code>)/).each_with_index do |str, i| if i % 2 == 1 (cells.empty? ? cells : cells.last) << str else reset_env(:src => Kramdown::Utils::StringScanner.new(str, @src.current_line_number)) root = Element.new(:root) parse_spans(root, nil, [:codespan]) root.children.each do |c| if c.type == :raw_text # Only on Ruby 1.9: f, *l = c.value.split(/(? 0 memo.concat(t) end (cells.empty? ? cells : cells.last) << f cells.concat(l) else delim = (c.value.scan(/`+/).max || '') + '`' tmp = "#{delim}#{' ' if delim.size > 1}#{c.value}#{' ' if delim.size > 1}#{delim}" (cells.empty? ? cells : cells.last) << tmp end end end end restore_env(env) cells.shift if leading_pipe && cells.first.strip.empty? cells.pop if cells.last.strip.empty? cells.each do |cell_text| tcell = Element.new(:td) tcell.children << Element.new(:raw_text, cell_text.strip) trow.children << tcell end columns = [columns, cells.length].max rows << trow else break end end if !before_block_boundary? @src.revert_pos(saved_pos) return false end # Parse all lines of the table with the code span parser env = save_env l_src = ::Kramdown::Utils::StringScanner.new(extract_string(orig_pos...(@src.pos-1), @src), @src.current_line_number) reset_env(:src => l_src) root = Element.new(:root) parse_spans(root, nil, [:codespan, :span_html]) restore_env(env) # Check if each line has at least one unescaped pipe that is not inside a code span/code # HTML element # Note: It doesn't matter that we parse *all* span HTML elements because the row splitting # algorithm above only takes elements into account! pipe_on_line = false while (c = root.children.shift) lines = c.value.split(/\n/) if c.type == :codespan if lines.size > 2 || (lines.size == 2 && !pipe_on_line) break elsif lines.size == 2 && pipe_on_line pipe_on_line = false end else break if lines.size > 1 && !pipe_on_line && lines.first !~ /^#{TABLE_PIPE_CHECK}/ pipe_on_line = (lines.size > 1 ? false : pipe_on_line) || (lines.last =~ /^#{TABLE_PIPE_CHECK}/) end end @src.revert_pos(saved_pos) and return false if !pipe_on_line add_container.call(has_footer ? :tfoot : :tbody, false) if !rows.empty? if !table.children.any? {|el| el.type == :tbody} warning("Found table without body on line #{table.options[:location]} - ignoring it") @src.revert_pos(saved_pos) return false end # adjust all table rows to have equal number of columns, same for alignment defs table.children.each do |kind| kind.children.each do |row| (columns - row.children.length).times do row.children << Element.new(:td) end end end if table.options[:alignment].length > columns table.options[:alignment] = table.options[:alignment][0...columns] else table.options[:alignment] += [:default] * (columns - table.options[:alignment].length) end @tree.children << table true end define_parser(:table, TABLE_START) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/typographic_symbol.rb0000644000175000017500000000352412672246616025240 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown TYPOGRAPHIC_SYMS = [['---', :mdash], ['--', :ndash], ['...', :hellip], ['\\<<', '<<'], ['\\>>', '>>'], ['<< ', :laquo_space], [' >>', :raquo_space], ['<<', :laquo], ['>>', :raquo]] TYPOGRAPHIC_SYMS_SUBST = Hash[*TYPOGRAPHIC_SYMS.flatten] TYPOGRAPHIC_SYMS_RE = /#{TYPOGRAPHIC_SYMS.map {|k,v| Regexp.escape(k)}.join('|')}/ # Parse the typographic symbols at the current location. def parse_typographic_syms start_line_number = @src.current_line_number @src.pos += @src.matched_size val = TYPOGRAPHIC_SYMS_SUBST[@src.matched] if val.kind_of?(Symbol) @tree.children << Element.new(:typographic_sym, val, nil, :location => start_line_number) elsif @src.matched == '\\<<' @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'), nil, :location => start_line_number) @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('lt'), nil, :location => start_line_number) else @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'), nil, :location => start_line_number) @tree.children << Element.new(:entity, ::Kramdown::Utils::Entities.entity('gt'), nil, :location => start_line_number) end end define_parser(:typographic_syms, TYPOGRAPHIC_SYMS_RE, '--|\\.\\.\\.|(?:\\\\| )?(?:<<|>>)') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/blockquote.rb0000644000175000017500000000170012672246616023464 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/eob' module Kramdown module Parser class Kramdown BLOCKQUOTE_START = /^#{OPT_SPACE}> ?/ # Parse the blockquote at the current location. def parse_blockquote start_line_number = @src.current_line_number result = @src.scan(PARAGRAPH_MATCH) while !@src.match?(self.class::LAZY_END) result << @src.scan(PARAGRAPH_MATCH) end result.gsub!(BLOCKQUOTE_START, '') el = new_block_el(:blockquote, nil, nil, :location => start_line_number) @tree.children << el parse_blocks(el, result) true end define_parser(:blockquote, BLOCKQUOTE_START) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/header.rb0000644000175000017500000000336212672246616022552 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/block_boundary' module Kramdown module Parser class Kramdown HEADER_ID=/(?:[ \t]+\{#([A-Za-z][\w:-]*)\})?/ SETEXT_HEADER_START = /^(#{OPT_SPACE}[^ \t].*?)#{HEADER_ID}[ \t]*?\n(-|=)+\s*?\n/ # Parse the Setext header at the current location. def parse_setext_header return false if !after_block_boundary? start_line_number = @src.current_line_number @src.pos += @src.matched_size text, id, level = @src[1], @src[2], @src[3] text.strip! el = new_block_el(:header, nil, nil, :level => (level == '-' ? 2 : 1), :raw_text => text, :location => start_line_number) add_text(text, el) el.attr['id'] = id if id @tree.children << el true end define_parser(:setext_header, SETEXT_HEADER_START) ATX_HEADER_START = /^\#{1,6}/ ATX_HEADER_MATCH = /^(\#{1,6})(.+?(?:\\#)?)\s*?#*#{HEADER_ID}\s*?\n/ # Parse the Atx header at the current location. def parse_atx_header return false if !after_block_boundary? start_line_number = @src.current_line_number @src.check(ATX_HEADER_MATCH) level, text, id = @src[1], @src[2].to_s.strip, @src[3] return false if text.empty? @src.pos += @src.matched_size el = new_block_el(:header, nil, nil, :level => level.length, :raw_text => text, :location => start_line_number) add_text(text, el) el.attr['id'] = id if id @tree.children << el true end define_parser(:atx_header, ATX_HEADER_START) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/link.rb0000644000175000017500000001111012672246616022245 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/escaped_chars' module Kramdown module Parser class Kramdown # Normalize the link identifier. def normalize_link_id(id) id.gsub(/[\s]+/, ' ').downcase end LINK_DEFINITION_START = /^#{OPT_SPACE}\[([^\n\]]+)\]:[ \t]*(?:<(.*?)>|([^\n]*?\S[^\n]*?))(?:(?:[ \t]*?\n|[ \t]+?)[ \t]*?(["'])(.+?)\4)?[ \t]*?\n/ # Parse the link definition at the current location. def parse_link_definition return false if @src[3].to_s =~ /[ \t]+["']/ @src.pos += @src.matched_size link_id, link_url, link_title = normalize_link_id(@src[1]), @src[2] || @src[3], @src[5] warning("Duplicate link ID '#{link_id}' on line #{@src.current_line_number} - overwriting") if @link_defs[link_id] @tree.children << new_block_el(:eob, :link_def) @link_defs[link_id] = [link_url, link_title, @tree.children.last] true end define_parser(:link_definition, LINK_DEFINITION_START) # This helper methods adds the approriate attributes to the element +el+ of type +a+ or +img+ # and the element itself to the @tree. def add_link(el, href, title, alt_text = nil, ial = nil) el.options[:ial] = ial update_attr_with_ial(el.attr, ial) if ial if el.type == :a el.attr['href'] = href else el.attr['src'] = href el.attr['alt'] = alt_text el.children.clear end el.attr['title'] = title if title @tree.children << el end LINK_BRACKET_STOP_RE = /(\])|!?\[/ LINK_PAREN_STOP_RE = /(\()|(\))|\s(?=['"])/ LINK_INLINE_ID_RE = /\s*?\[([^\]]+)?\]/ LINK_INLINE_TITLE_RE = /\s*?(["'])(.+?)\1\s*?\)/m LINK_START = /!?\[(?=[^^])/ # Parse the link at the current scanner position. This method is used to parse normal links as # well as image links. def parse_link start_line_number = @src.current_line_number result = @src.scan(LINK_START) cur_pos = @src.pos saved_pos = @src.save_pos link_type = (result =~ /^!/ ? :img : :a) # no nested links allowed if link_type == :a && (@tree.type == :img || @tree.type == :a || @stack.any? {|t,s| t && (t.type == :img || t.type == :a)}) add_text(result) return end el = Element.new(link_type, nil, nil, :location => start_line_number) count = 1 found = parse_spans(el, LINK_BRACKET_STOP_RE) do count = count + (@src[1] ? -1 : 1) count - el.children.select {|c| c.type == :img}.size == 0 end unless found @src.revert_pos(saved_pos) add_text(result) return end alt_text = extract_string(cur_pos...@src.pos, @src).gsub(ESCAPED_CHARS, '\1') @src.scan(LINK_BRACKET_STOP_RE) # reference style link or no link url if @src.scan(LINK_INLINE_ID_RE) || !@src.check(/\(/) link_id = normalize_link_id(@src[1] || alt_text) if @link_defs.has_key?(link_id) add_link(el, @link_defs[link_id][0], @link_defs[link_id][1], alt_text, @link_defs[link_id][2] && @link_defs[link_id][2].options[:ial]) else warning("No link definition for link ID '#{link_id}' found on line #{start_line_number}") @src.revert_pos(saved_pos) add_text(result) end return end # link url in parentheses if @src.scan(/\(<(.*?)>/) link_url = @src[1] if @src.scan(/\)/) add_link(el, link_url, nil, alt_text) return end else link_url = '' nr_of_brackets = 0 while temp = @src.scan_until(LINK_PAREN_STOP_RE) link_url << temp if @src[2] nr_of_brackets -= 1 break if nr_of_brackets == 0 elsif @src[1] nr_of_brackets += 1 else break end end link_url = link_url[1..-2] link_url.strip! if nr_of_brackets == 0 add_link(el, link_url, nil, alt_text) return end end if @src.scan(LINK_INLINE_TITLE_RE) add_link(el, link_url, @src[2], alt_text) else @src.revert_pos(saved_pos) add_text(result) end end define_parser(:link, LINK_START, '!?\[') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/escaped_chars.rb0000644000175000017500000000102012672246616024073 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown ESCAPED_CHARS = /\\([\\.*_+`<>()\[\]{}#!:|"'\$=-])/ # Parse the backslash-escaped character at the current location. def parse_escaped_chars @src.pos += @src.matched_size add_text(@src[1]) end define_parser(:escaped_chars, ESCAPED_CHARS, '\\\\') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/abbreviation.rb0000644000175000017500000000550012672246616023763 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 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! 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 kramdown-1.10.0/lib/kramdown/parser/kramdown/math.rb0000644000175000017500000000266612672246616022261 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/block_boundary' module Kramdown module Parser class Kramdown BLOCK_MATH_START = /^#{OPT_SPACE}(\\)?\$\$(.*?)\$\$(\s*?\n)?/m # Parse the math block at the current location. def parse_block_math start_line_number = @src.current_line_number if !after_block_boundary? return false elsif @src[1] @src.scan(/^#{OPT_SPACE}\\/) if @src[3] return false end saved_pos = @src.save_pos @src.pos += @src.matched_size data = @src[2].strip if before_block_boundary? @tree.children << new_block_el(:math, data, nil, :category => :block, :location => start_line_number) true else @src.revert_pos(saved_pos) false end end define_parser(:block_math, BLOCK_MATH_START) INLINE_MATH_START = /\$\$(.*?)\$\$/m # Parse the inline math at the current location. def parse_inline_math start_line_number = @src.current_line_number @src.pos += @src.matched_size @tree.children << Element.new(:math, @src[1].strip, nil, :category => :span, :location => start_line_number) end define_parser(:inline_math, INLINE_MATH_START, '\$') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/smart_quotes.rb0000644000175000017500000001427512672246616024055 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # #-- # Parts of this file are based on code from RubyPants: # # = RubyPants -- SmartyPants ported to Ruby # # Ported by Christian Neukirchen # Copyright (C) 2004 Christian Neukirchen # # Incooporates ideas, comments and documentation by Chad Miller # Copyright (C) 2004 Chad Miller # # Original SmartyPants by John Gruber # Copyright (C) 2003 John Gruber # # # = RubyPants -- SmartyPants ported to Ruby # # # [snip] # # == Authors # # John Gruber did all of the hard work of writing this software in # Perl for Movable Type and almost all of this useful documentation. # Chad Miller ported it to Python to use with Pyblosxom. # # Christian Neukirchen provided the Ruby port, as a general-purpose # library that follows the *Cloth API. # # # == Copyright and License # # === SmartyPants license: # # Copyright (c) 2003 John Gruber # (http://daringfireball.net) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # * Neither the name "SmartyPants" nor the names of its contributors # may be used to endorse or promote products derived from this # software without specific prior written permission. # # This software is provided by the copyright holders and contributors # "as is" and any express or implied warranties, including, but not # limited to, the implied warranties of merchantability and fitness # for a particular purpose are disclaimed. In no event shall the # copyright owner or contributors be liable for any direct, indirect, # incidental, special, exemplary, or consequential damages (including, # but not limited to, procurement of substitute goods or services; # loss of use, data, or profits; or business interruption) however # caused and on any theory of liability, whether in contract, strict # liability, or tort (including negligence or otherwise) arising in # any way out of the use of this software, even if advised of the # possibility of such damage. # # === RubyPants license # # RubyPants is a derivative work of SmartyPants and smartypants.py. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # This software is provided by the copyright holders and contributors # "as is" and any express or implied warranties, including, but not # limited to, the implied warranties of merchantability and fitness # for a particular purpose are disclaimed. In no event shall the # copyright owner or contributors be liable for any direct, indirect, # incidental, special, exemplary, or consequential damages (including, # but not limited to, procurement of substitute goods or services; # loss of use, data, or profits; or business interruption) however # caused and on any theory of liability, whether in contract, strict # liability, or tort (including negligence or otherwise) arising in # any way out of the use of this software, even if advised of the # possibility of such damage. # # == Links # # John Gruber:: http://daringfireball.net # SmartyPants:: http://daringfireball.net/projects/smartypants # # Chad Miller:: http://web.chad.org # # Christian Neukirchen:: http://kronavita.de/chris # #++ # module Kramdown module Parser class Kramdown SQ_PUNCT = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]' SQ_CLOSE = %![^\ \\\\\t\r\n\\[{(-]! SQ_RULES = [ [/("|')(?=[_*]{1,2}\S)/, [:lquote1]], [/("|')(?=#{SQ_PUNCT}(?!\.\.)\B)/, [:rquote1]], # Special case for double sets of quotes, e.g.: #

He said, "'Quoted' words in a larger quote."

[/(\s?)"'(?=\w)/, [1, :ldquo, :lsquo]], [/(\s?)'"(?=\w)/, [1, :lsquo, :ldquo]], # Special case for decade abbreviations (the '80s): [/(\s?)'(?=\d\ds)/, [1, :rsquo]], # Get most opening single/double quotes: [/(\s)('|")(?=\w)/, [1, :lquote2]], # Single/double closing quotes: [/(#{SQ_CLOSE})('|")/, [1, :rquote2]], # Special case for e.g. "Custer's Last Stand." [/("|')(\s|s\b|$)/, [:rquote1, 2]], # Any remaining single quotes should be opening ones: [/(.?)'/m, [1, :lsquo]], [/(.?)"/m, [1, :ldquo]], ] #'" SQ_SUBSTS = { [:rquote1, '"'] => :rdquo, [:rquote1, "'"] => :rsquo, [:rquote2, '"'] => :rdquo, [:rquote2, "'"] => :rsquo, [:lquote1, '"'] => :ldquo, [:lquote1, "'"] => :lsquo, [:lquote2, '"'] => :ldquo, [:lquote2, "'"] => :lsquo, } SMART_QUOTES_RE = /[^\\]?["']/ # Parse the smart quotes at current location. def parse_smart_quotes start_line_number = @src.current_line_number substs = SQ_RULES.find {|reg, subst| @src.scan(reg)}[1] substs.each do |subst| if subst.kind_of?(Integer) add_text(@src[subst]) else val = SQ_SUBSTS[[subst, @src[subst.to_s[-1,1].to_i]]] || subst @tree.children << Element.new(:smart_quote, val, nil, :location => start_line_number) end end end define_parser(:smart_quotes, SMART_QUOTES_RE, '[^\\\\]?["\']') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/extensions.rb0000644000175000017500000001650012672246616023517 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown IAL_CLASS_ATTR = 'class' # Parse the string +str+ and extract all attributes and add all found attributes to the hash # +opts+. def parse_attribute_list(str, opts) return if str.strip.empty? || str.strip == ':' attrs = str.scan(ALD_TYPE_ANY) attrs.each do |key, sep, val, ref, id_and_or_class, _, _| if ref (opts[:refs] ||= []) << ref elsif id_and_or_class id_and_or_class.scan(ALD_TYPE_ID_OR_CLASS).each do |id_attr, class_attr| if class_attr opts[IAL_CLASS_ATTR] = (opts[IAL_CLASS_ATTR] || '') << " #{class_attr}" opts[IAL_CLASS_ATTR].lstrip! else opts['id'] = id_attr end end else val.gsub!(/\\(\}|#{sep})/, "\\1") opts[key] = val end end warning("No or invalid attributes found in IAL/ALD content: #{str}") if attrs.length == 0 end # Update the +ial+ with the information from the inline attribute list +opts+. def update_ial_with_ial(ial, opts) (ial[:refs] ||= []) << opts[:refs] opts.each do |k,v| if k == IAL_CLASS_ATTR ial[k] = (ial[k] || '') << " #{v}" ial[k].lstrip! elsif k.kind_of?(String) ial[k] = v end end end # Parse the generic extension at the current point. The parameter +type+ can either be :block # or :span depending whether we parse a block or span extension tag. def parse_extension_start_tag(type) saved_pos = @src.save_pos start_line_number = @src.current_line_number @src.pos += @src.matched_size error_block = lambda do |msg| warning(msg) @src.revert_pos(saved_pos) add_text(@src.getch) if type == :span false end if @src[4] || @src.matched == '{:/}' name = (@src[4] ? "for '#{@src[4]}' " : '') return error_block.call("Invalid extension stop tag #{name} found on line #{start_line_number} - ignoring it") end ext = @src[1] opts = {} body = nil parse_attribute_list(@src[2] || '', opts) if !@src[3] stop_re = (type == :block ? /#{EXT_BLOCK_STOP_STR % ext}/ : /#{EXT_STOP_STR % ext}/) if result = @src.scan_until(stop_re) body = result.sub!(stop_re, '') body.chomp! if type == :block else return error_block.call("No stop tag for extension '#{ext}' found on line #{start_line_number} - ignoring it") end end if !handle_extension(ext, opts, body, type, start_line_number) error_block.call("Invalid extension with name '#{ext}' specified on line #{start_line_number} - ignoring it") else true end end def handle_extension(name, opts, body, type, line_no = nil) case name when 'comment' @tree.children << Element.new(:comment, body, nil, :category => type, :location => line_no) if body.kind_of?(String) true when 'nomarkdown' @tree.children << Element.new(:raw, body, nil, :category => type, :location => line_no, :type => opts['type'].to_s.split(/\s+/)) if body.kind_of?(String) true when 'options' opts.select do |k,v| k = k.to_sym if Kramdown::Options.defined?(k) begin val = Kramdown::Options.parse(k, v) @options[k] = val (@root.options[:options] ||= {})[k] = val rescue end false else true end end.each do |k,v| warning("Unknown kramdown option '#{k}'") end @tree.children << new_block_el(:eob, :extension) if type == :block true else false end end ALD_ID_CHARS = /[\w-]/ ALD_ANY_CHARS = /\\\}|[^\}]/ ALD_ID_NAME = /\w#{ALD_ID_CHARS}*/ ALD_CLASS_NAME = /[^\s\.#]+/ ALD_TYPE_KEY_VALUE_PAIR = /(#{ALD_ID_NAME})=("|')((?:\\\}|\\\2|[^\}\2])*?)\2/ ALD_TYPE_CLASS_NAME = /\.(#{ALD_CLASS_NAME})/ ALD_TYPE_ID_NAME = /#([A-Za-z][\w:-]*)/ ALD_TYPE_ID_OR_CLASS = /#{ALD_TYPE_ID_NAME}|#{ALD_TYPE_CLASS_NAME}/ ALD_TYPE_ID_OR_CLASS_MULTI = /((?:#{ALD_TYPE_ID_NAME}|#{ALD_TYPE_CLASS_NAME})+)/ ALD_TYPE_REF = /(#{ALD_ID_NAME})/ ALD_TYPE_ANY = /(?:\A|\s)(?:#{ALD_TYPE_KEY_VALUE_PAIR}|#{ALD_TYPE_REF}|#{ALD_TYPE_ID_OR_CLASS_MULTI})(?=\s|\Z)/ ALD_START = /^#{OPT_SPACE}\{:(#{ALD_ID_NAME}):(#{ALD_ANY_CHARS}+)\}\s*?\n/ EXT_STOP_STR = "\\{:/(%s)?\\}" EXT_START_STR = "\\{::(\\w+)(?:\\s(#{ALD_ANY_CHARS}*?)|)(\\/)?\\}" EXT_BLOCK_START = /^#{OPT_SPACE}(?:#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME})\s*?\n/ EXT_BLOCK_STOP_STR = "^#{OPT_SPACE}#{EXT_STOP_STR}\s*?\n" IAL_BLOCK = /\{:(?!:|\/)(#{ALD_ANY_CHARS}+)\}\s*?\n/ IAL_BLOCK_START = /^#{OPT_SPACE}#{IAL_BLOCK}/ BLOCK_EXTENSIONS_START = /^#{OPT_SPACE}\{:/ # Parse one of the block extensions (ALD, block IAL or generic extension) at the current # location. def parse_block_extensions if @src.scan(ALD_START) parse_attribute_list(@src[2], @alds[@src[1]] ||= Utils::OrderedHash.new) @tree.children << new_block_el(:eob, :ald) true elsif @src.check(EXT_BLOCK_START) parse_extension_start_tag(:block) elsif @src.scan(IAL_BLOCK_START) if @tree.children.last && @tree.children.last.type != :blank && (@tree.children.last.type != :eob || [:link_def, :abbrev_def, :footnote_def].include?(@tree.children.last.value)) parse_attribute_list(@src[1], @tree.children.last.options[:ial] ||= Utils::OrderedHash.new) @tree.children << new_block_el(:eob, :ial) unless @src.check(IAL_BLOCK_START) else parse_attribute_list(@src[1], @block_ial ||= Utils::OrderedHash.new) end true else false end end define_parser(:block_extensions, BLOCK_EXTENSIONS_START) EXT_SPAN_START = /#{EXT_START_STR}|#{EXT_STOP_STR % ALD_ID_NAME}/ IAL_SPAN_START = /\{:(#{ALD_ANY_CHARS}+)\}/ SPAN_EXTENSIONS_START = /\{:/ # Parse the extension span at the current location. def parse_span_extensions if @src.check(EXT_SPAN_START) parse_extension_start_tag(:span) elsif @src.check(IAL_SPAN_START) if @tree.children.last && @tree.children.last.type != :text @src.pos += @src.matched_size attr = Utils::OrderedHash.new parse_attribute_list(@src[1], attr) update_ial_with_ial(@tree.children.last.options[:ial] ||= Utils::OrderedHash.new, attr) update_attr_with_ial(@tree.children.last.attr, attr) else warning("Found span IAL after text - ignoring it") add_text(@src.getch) end else add_text(@src.getch) end end define_parser(:span_extensions, SPAN_EXTENSIONS_START, '\{:') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/footnote.rb0000644000175000017500000000431312672246616023154 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/codeblock' module Kramdown module Parser class Kramdown FOOTNOTE_DEFINITION_START = /^#{OPT_SPACE}\[\^(#{ALD_ID_NAME})\]:\s*?(.*?\n#{CODEBLOCK_MATCH})/ # Parse the foot note definition at the current location. def parse_footnote_definition start_line_number = @src.current_line_number @src.pos += @src.matched_size el = Element.new(:footnote_def, nil, nil, :location => start_line_number) parse_blocks(el, @src[2].gsub(INDENT, '')) warning("Duplicate footnote name '#{@src[1]}' on line #{start_line_number} - overwriting") if @footnotes[@src[1]] @tree.children << new_block_el(:eob, :footnote_def) (@footnotes[@src[1]] = {})[:content] = el @footnotes[@src[1]][:eob] = @tree.children.last true end define_parser(:footnote_definition, FOOTNOTE_DEFINITION_START) FOOTNOTE_MARKER_START = /\[\^(#{ALD_ID_NAME})\]/ # Parse the footnote marker at the current location. def parse_footnote_marker start_line_number = @src.current_line_number @src.pos += @src.matched_size fn_def = @footnotes[@src[1]] if fn_def if fn_def[:eob] update_attr_with_ial(fn_def[:eob].attr, fn_def[:eob].options[:ial] || {}) fn_def[:attr] = fn_def[:eob].attr fn_def[:options] = fn_def[:eob].options fn_def.delete(:eob) end fn_def[:marker] ||= [] fn_def[:marker].push(Element.new(:footnote, fn_def[:content], fn_def[:attr], fn_def[:options].merge(:name => @src[1], :location => start_line_number))) @tree.children << fn_def[:marker].last else warning("Footnote definition for '#{@src[1]}' not found on line #{start_line_number}") add_text(@src.matched) end end define_parser(:footnote_marker, FOOTNOTE_MARKER_START, '\[') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/blank_line.rb0000644000175000017500000000123212672246616023412 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown BLANK_LINE = /(?>^\s*\n)+/ # Parse the blank line at the current postition. def parse_blank_line @src.pos += @src.matched_size if @tree.children.last && @tree.children.last.type == :blank @tree.children.last.value << @src.matched else @tree.children << new_block_el(:blank, @src.matched) end true end define_parser(:blank_line, BLANK_LINE) end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/emphasis.rb0000644000175000017500000000344712672246616023137 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown module Parser class Kramdown EMPHASIS_START = /(?:\*\*?|__?)/ # Parse the emphasis at the current location. def parse_emphasis start_line_number = @src.current_line_number saved_pos = @src.save_pos result = @src.scan(EMPHASIS_START) element = (result.length == 2 ? :strong : :em) type = result[0..0] if (type == '_' && @src.pre_match =~ /[[:alnum:]]\z/) || @src.check(/\s/) || @tree.type == element || @stack.any? {|el, _| el.type == element} add_text(result) return end sub_parse = lambda do |delim, elem| el = Element.new(elem, nil, nil, :location => start_line_number) stop_re = /#{Regexp.escape(delim)}/ found = parse_spans(el, stop_re) do (@src.pre_match[-1, 1] !~ /\s/) && (elem != :em || !@src.match?(/#{Regexp.escape(delim*2)}(?!#{Regexp.escape(delim)})/)) && (type != '_' || !@src.match?(/#{Regexp.escape(delim)}[[:alnum:]]/)) && el.children.size > 0 end [found, el, stop_re] end found, el, stop_re = sub_parse.call(result, element) if !found && element == :strong && @tree.type != :em @src.revert_pos(saved_pos) @src.pos += 1 found, el, stop_re = sub_parse.call(type, :em) end if found @src.scan(stop_re) @tree.children << el else @src.revert_pos(saved_pos) @src.pos += result.length add_text(result) end end define_parser(:emphasis, EMPHASIS_START, '\*|_') end end end kramdown-1.10.0/lib/kramdown/parser/kramdown/codeblock.rb0000644000175000017500000000351712672246616023251 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # require 'kramdown/parser/kramdown/blank_line' require 'kramdown/parser/kramdown/extensions' require 'kramdown/parser/kramdown/eob' require 'kramdown/parser/kramdown/paragraph' module Kramdown module Parser class Kramdown CODEBLOCK_START = INDENT CODEBLOCK_MATCH = /(?:#{BLANK_LINE}?(?:#{INDENT}[ \t]*\S.*\n)+(?:(?!#{IAL_BLOCK_START}|#{EOB_MARKER}|^#{OPT_SPACE}#{LAZY_END_HTML_STOP}|^#{OPT_SPACE}#{LAZY_END_HTML_START})^[ \t]*\S.*\n)*)*/ # Parse the indented codeblock at the current location. def parse_codeblock start_line_number = @src.current_line_number data = @src.scan(self.class::CODEBLOCK_MATCH) data.gsub!(/\n( {0,3}\S)/, ' \\1') data.gsub!(INDENT, '') @tree.children << new_block_el(:codeblock, data, nil, :location => start_line_number) true end define_parser(:codeblock, CODEBLOCK_START) FENCED_CODEBLOCK_START = /^~{3,}/ FENCED_CODEBLOCK_MATCH = /^((~){3,})\s*?((\S+?)(?:\?\S*)?)?\s*?\n(.*?)^\1\2*\s*?\n/m # Parse the fenced codeblock at the current location. def parse_codeblock_fenced if @src.check(self.class::FENCED_CODEBLOCK_MATCH) start_line_number = @src.current_line_number @src.pos += @src.matched_size el = new_block_el(:codeblock, @src[5], nil, :location => start_line_number) lang = @src[3].to_s.strip unless lang.empty? el.options[:lang] = lang el.attr['class'] = "language-#{@src[4]}" end @tree.children << el true else false end end define_parser(:codeblock_fenced, FENCED_CODEBLOCK_START) end end end kramdown-1.10.0/lib/kramdown/element.rb0000644000175000017500000003670012672246616017637 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # module Kramdown # Represents all elements in the element tree. # # kramdown only uses this one class for representing all available elements in an element tree # (paragraphs, headers, emphasis, ...). The type of element can be set via the #type accessor. # # Following is a description of all supported element types. # # Note that the option :location may contain the start line number of an element in the source # document. # # == Structural Elements # # === :root # # [Category] None # [Usage context] As the root element of a document # [Content model] Block-level elements # # Represents the root of a kramdown document. # # The root element contains the following option keys: # # :encoding:: When running on Ruby 1.9 this key has to be set to the encoding used for the text # parts of the kramdown document. # # :abbrev_defs:: This key may be used to store the mapping of abbreviation to abbreviation # definition. # # :abbrev_attr:: This key may be used to store the mapping of abbreviation to abbreviation # attributes. # # :options:: This key may be used to store options that were set during parsing of the document. # # # === :blank # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Empty # # Represents one or more blank lines. It is not allowed to have two or more consecutive blank # elements. # # The +value+ field may contain the original content of the blank lines. # # # === :p # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Span-level elements # # Represents a paragraph. # # If the option :transparent is +true+, this element just represents a block of text. I.e. this # element just functions as a container for span-level elements. # # # === :header # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Span-level elements # # Represents a header. # # The option :level specifies the header level and has to contain a number between 1 and \6. The # option :raw_text has to contain the raw header text. # # # === :blockquote # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Block-level elements # # Represents a blockquote. # # # === :codeblock # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Empty # # Represents a code block, i.e. a block of text that should be used as-is. # # The +value+ field has to contain the content of the code block. # # The option :lang specifies a highlighting language with possible HTML style options (e.g. # php?start_inline=1) and should be used instead of a possibly also available language embedded in # a class name of the form 'language-LANG'. # # # === :ul # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] One or more :li elements # # Represents an unordered list. # # # === :ol # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] One or more :li elements # # Represents an ordered list. # # # === :li # # [Category] Block-level element # [Usage context] Inside :ol and :ul elements # [Content model] Block-level elements # # Represents a list item of an ordered or unordered list. # # Note that the first child of a list item must not be a :blank element! # # # === :dl # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] One or more groups each consisting of one or more :dt elements followed by one # or more :dd elements. # # Represents a definition list which contains groups consisting of terms and definitions for them. # # # === :dt # # [Category] Block-level element # [Usage context] Before :dt or :dd elements inside a :dl elment # [Content model] Span-level elements # # Represents the term part of a term-definition group in a definition list. # # # === :dd # # [Category] Block-level element # [Usage context] After :dt or :dd elements inside a :dl elment # [Content model] Block-level elements # # Represents the definition part of a term-definition group in a definition list. # # # === :hr # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] None # # Represents a horizontal line. # # # === :table # # [Category] Block-level element # [Usage context] Where block-level elements are expected # [Content model] Zero or one :thead elements, one or more :tbody elements, zero or one :tfoot # elements # # Represents a table. Each table row (i.e. :tr element) of the table has to contain the same # number of :td elements. # # The option :alignment has to be an array containing the alignment values, exactly one for each # column of the table. The possible alignment values are :left, :center, :right and :default. # # # === :thead # # [Category] None # [Usage context] As first element inside a :table element # [Content model] One or more :tr elements # # Represents the table header. # # # === :tbody # # [Category] None # [Usage context] After a :thead element but before a :tfoot element inside a :table element # [Content model] One or more :tr elements # # Represents a table body. # # # === :tfoot # # [Category] None # [Usage context] As last element inside a :table element # [Content model] One or more :tr elements # # Represents the table footer. # # # === :tr # # [Category] None # [Usage context] Inside :thead, :tbody and :tfoot elements # [Content model] One or more :td elements # # Represents a table row. # # # === :td # # [Category] Block-level element # [Usage context] Inside :tr elements # [Content model] As child of :thead/:tr span-level elements, as child of :tbody/:tr and # :tfoot/:tr block-level elements # # Represents a table cell. # # # === :math # # [Category] Block/span-level element # [Usage context] Where block/span-level elements are expected # [Content model] None # # Represents mathematical text that is written in LaTeX. # # The +value+ field has to contain the actual mathematical text. # # The option :category has to be set to either :span or :block depending on the context where the # element is used. # # # == Text Markup Elements # # === :text # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents text. # # The +value+ field has to contain the text itself. # # # === :br # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents a hard line break. # # # === :a # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] Span-level elements # # Represents a link to an URL. # # The attribute +href+ has to be set to the URL to which the link points. The attribute +title+ # optionally contains the title of the link. # # # === :img # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents an image. # # The attribute +src+ has to be set to the URL of the image. The attribute +alt+ has to contain a # text description of the image. The attribute +title+ optionally contains the title of the image. # # # === :codespan # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents verbatim text. # # The +value+ field has to contain the content of the code span. # # # === :footnote # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents a footnote marker. # # The +value+ field has to contain an element whose children are the content of the footnote. The # option :name has to contain a valid and unique footnote name. A valid footnote name consists of # a word character or a digit and then optionally followed by other word characters, digits or # dashes. # # # === :em # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] Span-level elements # # Represents emphasis of its contents. # # # === :strong # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] Span-level elements # # Represents strong importance for its contents. # # # === :entity # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents an HTML entity. # # The +value+ field has to contain an instance of Kramdown::Utils::Entities::Entity. The option # :original can be used to store the original representation of the entity. # # # === :typographic_sym # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents a typographic symbol. # # The +value+ field needs to contain a Symbol representing the specific typographic symbol from # the following list: # # :mdash:: An mdash character (---) # :ndash:: An ndash character (--) # :hellip:: An ellipsis (...) # :laquo:: A left guillemet (<<) # :raquo:: A right guillemet (>>) # :laquo_space:: A left guillemet with a space (<< ) # :raquo_space:: A right guillemet with a space ( >>) # # # === :smart_quote # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents a quotation character. # # The +value+ field needs to contain a Symbol representing the specific quotation character: # # :lsquo:: Left single quote # :rsquo:: Right single quote # :ldquo:: Left double quote # :rdquo:: Right double quote # # # === :abbreviation # # [Category] Span-level element # [Usage context] Where span-level elements are expected # [Content model] None # # Represents a text part that is an abbreviation. # # The +value+ field has to contain the text part that is the abbreviation. The definition of the # abbreviation is stored in the :root element of the document. # # # == Other Elements # # === :html_element # # [Category] Block/span-level element # [Usage context] Where block/span-level elements or raw HTML elements are expected # [Content model] Depends on the element # # Represents an HTML element. # # The +value+ field has to contain the name of the HTML element the element is representing. # # The option :category has to be set to either :span or :block depending on the whether the # element is a block-level or a span-level element. The option :content_model has to be set to the # content model for the element (either :block if it contains block-level elements, :span if it # contains span-level elements or :raw if it contains raw content). # # # === :xml_comment # # [Category] Block/span-level element # [Usage context] Where block/span-level elements are expected or in raw HTML elements # [Content model] None # # Represents an XML/HTML comment. # # The +value+ field has to contain the whole XML/HTML comment including the delimiters. # # The option :category has to be set to either :span or :block depending on the context where the # element is used. # # # === :xml_pi # # [Category] Block/span-level element # [Usage context] Where block/span-level elements are expected or in raw HTML elements # [Content model] None # # Represents an XML/HTML processing instruction. # # The +value+ field has to contain the whole XML/HTML processing instruction including the # delimiters. # # The option :category has to be set to either :span or :block depending on the context where the # element is used. # # # === :comment # # [Category] Block/span-level element # [Usage context] Where block/span-level elements are expected # [Content model] None # # Represents a comment. # # The +value+ field has to contain the comment. # # The option :category has to be set to either :span or :block depending on the context where the # element is used. If it is set to :span, then no blank lines are allowed in the comment. # # # === :raw # # [Category] Block/span-level element # [Usage context] Where block/span-level elements are expected # [Content model] None # # Represents a raw string that should not be modified. For example, the element could contain some # HTML code that should be output as-is without modification and escaping. # # The +value+ field has to contain the actual raw text. # # The option :category has to be set to either :span or :block depending on the context where the # element is used. If it is set to :span, then no blank lines are allowed in the raw text. # # The option :type can be set to an array of strings to define for which converters the raw string # is valid. # class Element # A symbol representing the element type. For example, :p or :blockquote. attr_accessor :type # The value of the element. The interpretation of this field depends on the type of the element. # Many elements don't use this field. attr_accessor :value # The child elements of this element. attr_accessor :children # Create a new Element object of type +type+. The optional parameters +value+, +attr+ and # +options+ can also be set in this constructor for convenience. def initialize(type, value = nil, attr = nil, options = nil) @type, @value, @attr, @options = type, value, (Utils::OrderedHash.new.merge!(attr) if attr), options @children = [] end # The attributes of the element. Uses an Utils::OrderedHash to retain the insertion order. def attr @attr ||= Utils::OrderedHash.new end # The options hash for the element. It is used for storing arbitray options. def options @options ||= {} end def inspect #:nodoc: "" end CATEGORY = {} # :nodoc: [:blank, :p, :header, :blockquote, :codeblock, :ul, :ol, :li, :dl, :dt, :dd, :table, :td, :hr].each {|b| CATEGORY[b] = :block} [:text, :a, :br, :img, :codespan, :footnote, :em, :strong, :entity, :typographic_sym, :smart_quote, :abbreviation].each {|b| CATEGORY[b] = :span} # Return the category of +el+ which can be :block, :span or +nil+. # # Most elements have a fixed category, however, some elements can either appear in a block-level # or a span-level context. These elements need to have the option :category correctly set. def self.category(el) CATEGORY[el.type] || el.options[:category] end end end kramdown-1.10.0/lib/kramdown/compatibility.rb0000644000175000017500000000135412672246616021054 0ustar uwabamiuwabami# -*- coding: utf-8 -*- # #-- # Copyright (C) 2009-2015 Thomas Leitner # # This file is part of kramdown which is licensed under the MIT. #++ # # All the code in this file is backported from Ruby 1.8.7 sothat kramdown works under 1.8.5 # # :stopdoc: if RUBY_VERSION <= '1.8.6' require 'rexml/parsers/baseparser' module REXML module Parsers class BaseParser UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" unless const_defined?(:UNAME_STR) end end end if !String.instance_methods.include?("start_with?") class String def start_with?(str) self[0, str.length] == str end def end_with?(str) self[-str.length, str.length] == str end end end end kramdown-1.10.0/COPYING0000644000175000017500000000243712672246616014324 0ustar uwabamiuwabamikramdown - fast, pure-Ruby Markdown-superset converter Copyright (C) 2009-2013 Thomas Leitner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Some test cases and the benchmark files are based on test cases from the MDTest test suite: MDTest Copyright (c) 2007 Michel Fortin kramdown-1.10.0/doc/0000755000175000017500000000000012672246616014030 5ustar uwabamiuwabamikramdown-1.10.0/doc/documentation.page0000644000175000017500000000541412672246616017543 0ustar uwabamiuwabami--- title: Documentation in_menu: true sort_info: 7 --- # kramdown Documentation ## Overview kramdown is first and foremost a library for converting text written in a superset of Markdown to HTML. However, due to its modular architecture it is able to support additional input and output formats. The following input and output formats are currently supported: * Input: [kramdown](parser/kramdown.html) (a superset of Markdown), [Markdown](parser/markdown.html), [Github Flavored Markdown](parser/gfm.html), [HTML](parser/html.html) * Output: [HTML](converter/html.html), [LaTeX](converter/latex.html), [kramdown](converter/kramdown.html), [RemoveHtmlTags](converter/remove_html_tags.html) (a special converter which removes HTML tags, normally used in conjunction with the LaTeX or kramdown converters) The [kramdown syntax page](syntax.html) describes in detail what is supported and how it differs from standard Markdown. For all available options have a look at the [options documentation](options.html) or have a look at a parser/converter page to see which options they support! ## Usage {:ruby: .language-ruby} The kramdown package provides two ways for using it: * **As a library** kramdown uses basically the same API as [RedCloth], [BlueCloth] and [Maruku]: require 'kramdown' puts Kramdown::Document.new(text).to_html {:ruby} The second parameter to the `new` call is an options hash for (de)activating certain features. For example, to disable automatic header ID generation, you can do the following: puts Kramdown::Document.new(text, :auto_ids => false).to_html {:ruby} The default parser used is `kramdown`, however, you can select a different one with the `:input` option: puts Kramdown::Document.new(text, :input => 'html').to_latex {:ruby} You can also reuse the created document object to produce multiple outputs: doc = Kramdown::Document.new(text, :input => 'html') puts doc.to_html puts doc.to_latex {:ruby} More information on how to use or extend kramdown can be found in the [API documentation](rdoc/index.html)! * **As an application** Together with the library files a binary called `kramdown` is shipped which can be used to convert text in any supported input format to any supported output format. It either reads from the files specified as the command line arguments or from the standard input. For example: kramdown path/to/kramdown/doc/syntax.page The input and output formats as well as all available kramdown options are supported through command line switches. ## Tests kramdown uses various test suites to verify the correct working of the parsers and converters. For more information, have a look at the [tests document](tests.html). {include_file: doc/links.markdown} kramdown-1.10.0/doc/default.template0000644000175000017500000000470312672246616017215 0ustar uwabamiuwabami {title:} | kramdown

kramdown

fast, pure-Ruby Markdown-superset converter

<% if context.content_node.blocks.has_key?('intro') %> <% end %>
Copyright © 2009-2015 Thomas Leitner
Generated by webgen
kramdown-1.10.0/doc/default.scss0000644000175000017500000000643112672246616016355 0ustar uwabamiuwabami@import 'design'; a:hover { background-color: rgba(0,0,0,0.1); } aside.banner { font-size: 18px; line-height: 27px; } aside a { text-decoration: none; &:hover, &:link { text-decoration: underline; } } #content { blockquote.information { border-left: 12px solid #080; background-color: #bfb; padding: 12px 12px 12px 0; margin-left: -48px; padding-left: 48px; } blockquote.markdown-difference { border-left: 12px solid #dc0; background-color: #ffa; padding: 12px 12px 12px 0; margin-left: -48px; padding-left: 48px; &:before { content: "Difference to Standard Markdown"; display: block; font-weight: bold; } } blockquote pre { border: none; } table { border-collapse: collapse; margin-left: auto; margin-right: auto; width: 100%; td, th { padding: 3px 5px; } th { background-color: #080; color: white; } } pre.show-whitespaces .ws-space { background-color: #f44; } pre.show-whitespaces .ws-space-l { background-color: #f22; } pre.show-whitespaces .ws-space-r { background-color: #f00; } pre.show-whitespaces .ws-tab { background-color: #ff4; } pre.show-whitespaces .ws-tab-l { background-color: #ff2; } pre.show-whitespaces .ws-tab-r { background-color: #ff0; } pre.show-whitespaces.ws-lr .ws-tab { background-color: inherit; } pre.show-whitespaces.ws-lr .ws-space { background-color: inherit; opacity: 0; } table.kdexample td { vertical-align: top; } table.kdexample pre { margin: 5px 0px; } .kdexample:hover .kdexample-after-source { display: block; } .kdexample-after-source { display: none; background-color: #ffffee; border: 2px solid #e6e8e9; margin: 0 10px; padding: 5px; } .kdexample-after-live { background-color: #eeffee; border: 2px solid #e6e8e9; margin: 5px 0px 12px; padding: 5px; } div.kdsyntaxlink { float: right; position: relative; top: -17px; padding: 5px; border: 1px solid #e6e8e9; margin-right: 10px; margin-left: 10px; a { text-decoration: none; } } } .news-item { border-top: 2px solid #ddd; margin-top: 46px; } .news-date { float: right; margin-top: 2px; font-size: small; color: #888; } footer { clear: both; font-size: 92%; text-align: left; a { color: #898989; &:hover { text-decoration: none; color: #666; } } } /* common rules */ acronym { cursor: help; border-bottom: 1px solid #777; } .float-left { float: left; } .float-right { float: right; } .a-left, tr.a-left td { text-align: left; } .a-center, tr.a-center td { text-align: center; } .a-right, tr.a-right td { text-align: right; } .clear { clear: both; } .inline-important { font-weight: bold; display: block; text-align: center; } kramdown-1.10.0/doc/installation.page0000644000175000017500000000464612672246616017401 0ustar uwabamiuwabami--- title: Installation in_menu: true sort_info: 5 --- # Download & Installation ## Dependencies Since kramdown is written in Ruby, you just need the [Ruby interpreter](http://www.ruby-lang.org), version 1.8.5, 1.8.6, 1.8.7, 1.9.2, 1.9.3 or 2.0.0. There are no other dependencies. ## Compatibility Notes kramdown should work on any platform which supports Ruby. It has been successfully tested on the following platforms: * Linux with Ruby 1.8.5, 1.8.6, 1.8.7, 1.9.2, 1.9.3, 2.0.0 and jruby 1.7.3. See the platform specific installation notes for more information! ## Platform Specific Installation Instructions ### Linux There are a variety of Linux distributions out there with different package management systems. So we will focus on instructions for Ubuntu 15.04 here (which should probably also work for any newer Ubuntu version or any recent Debian based distribution). After running the following commands, kramdown is installed and ready to use: sudo apt-get install ruby sudo gem install kramdown ### Mac OS X Mac OS X Snow Leopard comes with Ruby and Rubygems preinstalled. So installing kramdown is as easy as running: sudo gem install kramdown ### Windows You need to install Ruby first. This can easily be done by using the [RubyInstaller] - just download the installation binary and run it. After that open a command shell (select `Start -> Run...`, then enter `cmd` and click on `Ok`) and type in the following: gem install kramdown [RubyInstaller]: http://rubyinstaller.org ## Generic Installation Instructions ### Using Rubygems If you are using Rubygems, installing the latest version of kramdown is as simple as executing gem install kramdown ### Manual Installation The latest version of kramdown can always be downloaded as `.tar.gz` or `.zip` via the [Github releases page][ghreleases]. After the download the package needs to be decompressed and then you can install kramdown using the included `setup.rb` installation method: $ ruby setup.rb config $ ruby setup.rb setup $ ruby setup.rb install [ghreleases]: https://github.com/gettalong/kramdown/releases ### Using the repository version kramdown uses git as its versioning system and kramdown's repository is hosted on GitHub. The repository always contains a clean state of the current development version of kramdown. To check out kramdown use the following command: git clone git://github.com/gettalong/kramdown.git kramdown-1.10.0/doc/news.page0000644000175000017500000000154012672246616015642 0ustar uwabamiuwabami--- title: News in_menu: false sort_info: 30 --- pipeline:tags,blocks,fragments

News

Atom-Feed --- name:newsdata pipeline:erb <% opts = {:alcn => '/news/*.html', :sort => 'sort_info', :reverse => true, :flatten => true} context.website.ext.item_tracker.add(context.dest_node, :nodes, :node_finder_option_set, {:opts => opts, :ref_alcn => context.node.alcn}, :content) context.website.ext.node_finder.find(opts, context.node).each do |node| # context.options['contentprocessor.kramdown.options'] = {:auto_id_prefix => node.lcn.tr('.', '-')} %>
Published on <%= node['created_at'].strftime("%A, %d %B %Y") %>
<%= context.render_block(:name => 'content', :chain => [node]) %>
<% end %> kramdown-1.10.0/doc/links.markdown0000644000175000017500000000041712672246616016716 0ustar uwabamiuwabami[Maruku]: http://maruku.rubyforge.org [PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ [Pandoc]: http://johnmacfarlane.net/pandoc/ [MathJax]: http://www.mathjax.org [BlueCloth]: http://deveiate.org/projects/BlueCloth [RedCloth]: http://redcloth.org/ kramdown-1.10.0/doc/bg.png0000644000175000017500000015553412672246616015143 0ustar uwabamiuwabami‰PNG  IHDR,-—J tEXtSoftwareAdobe ImageReadyqÉe<çiTXtXML:com.adobe.xmp £,±× IDATÁ bä6¶ @ÝÆ%% àíØ7’™*»ÿÜÿ8ñ…mæ€ê:ǽíl²³Ñ#NÀ6â™]ì¾ø‚BÃÃ|r0,òÜ¢ ‡Ç¶âwò¥øQ§H¤ò缆š\ Ä ¹î$›rÆÙ1ùõsÆa†¡Î¡Éxb]»Pu-úÚú©k˜s—ŽÊGÙ”qÁ^#ùº)ñåÒä*d–=ÊKLªK{³¯TçH'#—ŸÜ›@uYu¬ìQõé}“‹G"i-ùHRÏ´…Kdo9¸r^Ëè«t²…rýéQ}þ|êAGÊn¬šÎæyìä°ê³èY\ýýT×BR×g;(B?òç–CÞB»7—õÐçÖ°|‹G½‡Soh{Ù·ýôäÚ»¿D\ùNc¥³Ñ¶0Çr9цô{ùï4кÚI¬ã,¿¿v¶Ð ÖïôI©å¹8ÔŸŠp}ÚAZ°u©/¯J¼îv&¦ê˾ÍÛ‘{K§œPÎzmÅx6‘:¶ë1÷ïܧ`ÓÁÚõ%dúÝîrb Òßÿv¨ûW(®ÜW… ^ý˜Ù¬eaûh¡÷böý¬¿·œ“‡qOjŠO××1ùcÜÕ•ì+¤õ˜8Œî;Ÿ9ÑÍãé ½GxÑ?ú\®P$䜤cƒŽè ѼÇÒ«¶J¸Oö8Þwè+÷kVß8ýnq;I=Ònš«‡ßw9#¡ýÐÚJhêÈ!àŸ±ssôò}˹EÖûfg|IÞ«„Ž.øýw!•S™Í\r(g¾;–›Ľ¾î©uÉ@©M$Òu™ï•{ LJå3qJXïÉ4 '[ÏÄ1ÈBºÉB!žWÆkq ùndËKû©\;¥Ù<|‚Ÿ»ðJ˜|ýw{_CbYïÁÉÐÿðL'6ÇçŽ~DZöO\Ï´© ¡>—Hwº?;zú–»Bœg TGþIlú3‘³^æÀ0Áa(=ž”_ìþM°Œè,/K•#i)IwLúnN{È>íapY4§×’º¾ÊdUmS fF94ÿ HjOâšÙ4Ý Ò'²ry'YÒÓ9ß…Õꓹ%R¯£h]¢¥ŽËh&0‘½J ú¯qK(Š­’L$÷Ûâ]1®Jé2éÅ t²#ÆP¬Ž,«ÅHqElEÓÜ«Ôl‚¹Gn·)œqìÂ|eÊCÝ‹÷y$&à•µï=h¬x8‡-S[ÄDs±¬h†éJT;g=)~RðTï×Ð,zm»Òe}º´­Hhõ})j‘Ƨ@é­éjĆ«RýT Žê»G» ¶¿ÅÀÛÄ8 ð»Ëx(Æ-ñy #~Õ+cÝÈ­’Ø1=OÁ2)Î tEí Oˆw†Â4wæq±Ì¤î*±ÍJóâÜ ³Êb_ã:YGDÚÉÆH|,D#cj€±èé}4oW€°TîG<„1%/C"¹…çÀCNÐV&é#6§iÑáëâòûT·'ºã º²§Fa<9DµúJ{ émg—%Þ\ÿï!êøË8æ CþßíÏ·ñºKˆ›ëŸ›Cæ[äz'';äu'˜ÄëN.a¬¸Þ<Ó‡ôzòa!µžî!ËÞw< c‚úw4üy/ûaéÉ·U4Z$ëÝeÈø¬@âµËq)A™Í“ö£³Š¯”¾ňõ´µ3ÊYÕõµIrß)˜ËQ¯A€ni϶¯O>JÔúÊÏF_ÎŒ:{:ØÑ 1;BùYšß=9óÏù\Úk Î÷t;[ùî ;Q»ºŸ&úZß"›óý=°&^ïå©5ðºËY9å3ŽzòpÕÇ{'(žðÕ?õ”õÔûIÿtgöݽ¼©^»ã&þú÷Q3Ïö»$´S Æ^˜šÜ!¾ÿmaQ„WûôS£¯®®ìSñ)è}ó9ÑÄ·i>e§°þ½ Áú]ÁìÛ| a~Ì•†äêl:f¥VäUÒ)ßÜ»òrQ©ßñè=˜O‡C€ú\¾G¾\=„ ÓXù¼&™½´—z\»ÀJ˜]®¨%¥ØjÈJr–wç8\$»®‚+R¤ùžÌ_ÆKB™™Rú† «5òça£Ê¸-#÷†0DÌÆªÚš·¥%ä¶ s¦Â›ÁEu|j¨Œìš„Ãļöî¥uµ…I±ŽT®ÆÆy4‘GL9·‚­?lOÖ‡!PéEîîÁËž–)qí‚%³ì­:O[ùêªb!Y†`óŠ¸ ×»“L6åvEß3I•‚ÔTÛ2¹º Û,,ðÌOFÅ8æ †ÒG’%~‰Ö ¹G"¦N¡÷àrr0ª¥\~sPn=õË)nÁ’rÑ<#ÄO–ÖèdËÛPŦ9D [¦zgFÔ&T+£ðìR®j,ýÖ4»1óÓ0ïb‚Z@îIÀÜ ËS¨”XÐV%™‘ÇT kyO!ÀynDâÚ´*,0‹ŒÛ˜¹.N»2L iËO <$îqe-™¼X)WA‚m MÓtªG’K©Ä6¾øC=9ËRwüñ‚•lm;1ô ãï"${—¾V†äbäµ é:BæÔ­ÚÝÐLªw÷‡¸5t\Ñ1ɛ뽋̹%PÂr_ «ÎlsÅ“¥~ï%”áRWF:X­[C¥šÒìEqÃÔ ‚ú$ùšÑ'Ðõjw }eé]Cæ8€Ÿ'Ñ›q^É•ù¢Ö(°KÚLžCšœF#ÎBÒ2:¹{ɤÈ4WwÆ1ú¶óáMnä1¿úHG,P]ÿÈ#×{9$ÒréxVÙ‘î÷¯f óH{ Tß’î«{VÎNîMÐÜ(ºïûäóõ4©Ð%äÑC®¾ßŸtè1 û2_cZ¡Ž¥'ÿa×§þ([wõ®Î—ü®Ú\.ÐÆ4Ì4I÷l¡ $ŸæŠ¨¡­'Sv| Îì:cÛé;¡ÆsüäŒ-ð¾Ò·a..ß倸m?ò<íP4 }6ú“¶šN:KÇu²®Pv•—,®Î±úÊÚÞœ5ÄoyÖÙ,ôÏp‘Ãðãºbhîi´~û‘Êw+†‹i¯}dÓó7¸A y®æU¬üÔÏþ†p¿‡«QŠ+÷#¡|—€ÏßúMžª“}Sȯ´ïâ*qòin ü1Ýwƒ Zϼ¹ä¹ŒþêšËO]·iÃyҼʋ òw]éäݧßOñ5Ät´–=g_Îrô ß1±¯Í§cåŸ IŽšz`õã…¥§s†’é~7ŸŠŸ®\]Ί5ú/9d_†LŸ§û^Ñpü}OÆÌGNVÏú~G.?в¯2Sõµ7ÂÉmÝvv{o“p}êÙ2¬ÏfP8ŽYf¢?².Àáí‡÷Lgg_W;iB:±w9йրÅO”µíÇÀbX-a¾}W(MO­Î~ìóN~x1_>×ê){Ò™$nWçœ]þ¡ë±WGg ë€x¦ÞÌBhCO³¶¯ä j€yuŸ µP®e_­Cœ!î+ÚMYdýívWQ§{°6MDãyæƒWá<8"Õ‘ ÕVQ&à6‹õ¬Bõž( èÚ†wñÚ—Y B²œ3Að²rˆP[úò\Š·Àcñ‘ÙÄå+ƒeÏcªtD‘|7HÍéÞZ`å¾’ÏÕb›ŒË¢@ѕ{KxD)ÔOÃV=%°ØTkmP+$ä90< tÚ.~.¢3LRƒ1;S‹ç×J°í(×6f}ºÌSDl‹p$RÉO…xYb®Cà*^f¢T=¦„\"x²Ë .aGk‰¬,B¶ û¨ÜúVw–>‚'ì—ÀŠ9^r–tO°ÕÑ“½3Íí^>î†2”Cè—☈h­½#ç%8"a«Ü>܉£øÜ ÍÉ:Y,›ÌNDÔ+¥wŠtYèƒ1ð&9!ÇùK8K´ƒtEŒk!èãÝ¥ýFcJ_‰·`›Ù‹Ž õwj,ú(®§ A^–VŒòaž3C²\ÐfF"×Ô‚ŽB¬2žèPp"í'z c„²¢§ˆ]y\z*õ†q7&ÂÎ|Ô+¤„å­gà´)½/äJü·Q¨¨­°#^Öe Æâ5ÉGj…òÊž˜7cÍ»´èãnGíÀs $žó,ÈlÃëhŒ‘ŸeE–rðÜÑ WÓë¯yÒvsº ‘¸e´– ¡ní÷´4u%î_0?7B¡xî“ûÃã÷V.v±Í5BZ¸=SØømq>гrbW‡L=ÐxôÉÕ5I²Ì—\“|9ù1JàH#äkÙ¹D{é9Õýfr¿»CÂp.öõHâ׈±½òšæ »†1“ËEêY¯mg ‰B¾ªt9ÌϽ…a<Õ bƒr]r&x–Q@4è¿·xõ;qŽúÔ5Ô@sv9]`¿>í\jŸO÷†¶¨¯EÇW„Ër‚ë>¨¯!þïÙ7®%¬½%&¿ÈúLgÆÞùzÏ“ ^gè—ý¡3ɹV?¥B%mCârâëÞ"^Þ®®þºùžÐ—ǪP}MPVü–ŒÉë~2n¬†ójN×÷¥ažE\½ã·Gi?å¾ ç+²¾›OñÈÏŇ¾*†6²oÆõ•Wu~ùJÔV?‹q9KÓב 0F‡¡\[ñ§úÐFò¨œ¹FWOœ»a‚XŽ8:Ku5„º Mí+dȟߊg¡ý<\m.Ï'» Yü5[ÐH·ËÏ»a?Lqÿû˜Nû†:Sh§ ]ÿå—Z(®î«ÒC-âü; ?ѵ§z¼11Ö‘ohÏ[}ý‰àûµüîØ¨ì'†v–p”k¾’Ar}_zè·z¼ßvVá~äÙYÆ‘Èö(çΘ^u5ÀÆ»Ç3¹—`¿Fà凨¾ËA>ð®é`ñ³ºÌÎæœþDmÕYõìOÒ½üÁu——ÿŽ×™¸c¹æWº¦ùŸ§ðÅw×Õ m#ébòôüשWˆ!]OÆ‹ù|i+W¨÷”ô×™Æç]±$J.Î¥ö/H }'ì1Ä`ë¶½8\ŸZtá°§;¼QÀîeP ÕÇ~ÉYjWçIüž¨ë¥àòŽa)DŸž%\)£^ïî:yåyM¢êÌñ¼Zè„1ôÏÀ¸@Ï-ºùTH‹,PÝ9\Ât¤Qƒõï-®¡$«+Žƒ™|Gï}_•,}ñ•4ÀxTî-†q6¢{æüN8WLœ{Õü6U©»ÚÂHYVÂÒN¼»&âÙbßb„eWì•5•Y9ߢç“ýn€>UôX¬š\²ØjœVðŽúU¨&!§Ó|\¤ ëp¥ »“6MJíb¼š)–wãºTØj‹Úµä‰J:Ð2"*»SÝÚRyGR+Ë 6ã¶„–úÓ§ M Ãµ+¥Í.€Ž} ÜW”EèK£õç°Øž˜ï)léÓ°ÜIKLKÒìJ‰F¤vg$m (%!„–À®ìEóð\ %ÚN”{!}Q¾¡ÙÊ:ß­:.ÒÌ\/£¨uK|/ ÊE ìû@¹’Æu^ÁÇâ{s|+öÛ<Ùš`Ÿ ´³õF‚®.ÒjȌ۴wö@%Aì%‘)TW‚Huj\Æ 2„çbdHr¦;3³- ý2$H â0¢ƒq^4^S¿nêkWÔ³&»þ.4¶Íý·H¸ çZX1nÒ™<”P®[_!äËë„»Q[üBÇÓúìñ"û–3sZ’{ENç…8§}sÐÒµ•+/˽n–«‹»‡CÃt¯t&NÇ=„˜ß¹²ÏT;”» $iÁö”³ D*WEÑðê+y½c™ÅåA±7s|*‡^R@Âz†±õ0ßâ‘GäÄnÔ:»=‡²j°,ÅÇ«cˆÔ ÆL‡u*ŸË¾Þ%4ÁŠåyGŸ{ h0þþÊ‹Ý@¹>ó%‡/~ìæaºìa½Ó+A\8öÅX_Éãz׳H,n¬æN>¦ó㩇:͇^5X§xÎ -Óuà>RîÎÿ(ÿ´‘×ÐÑÖÓ°‡ÒqþÞÁ['Ím®†’¡­í!b?lôLÅÕ ã鈺³¹ô›_Œ¾_Ó›ÒèzÀ?ÉÂèüCx–lSC?GÄɾ-tjÆgóˆ>»ú^,o( µË+Ò‹~âs‹ïXæ]½¡c×zKZ¹Ð6ŸW¡ü'FXÏäpïìš¡¾Ê³†3–±Ó«°Cß÷b÷•pŠCJwçÜ\t¾Nã¥ÂPö@ëRHîOÉ[“…òTŠM#Èu)uÁv%î-(hËÌKL1Î uPÄx­™Èl û$ñP«h= B»’K•³¥6rù¥€Rgâš‘œÝí x~ª®Äë¾#f”>³ï4¤{HÜËRhâõêÈÍ“‡¶ÍÏâ‘Ò3I u2­|¦«“]TˆÇÀ£§SWÂ4¼’Öžpgb¯ i‘y¯%ÑÌp~) [$Ý) ÆËœ‚:Dï*Þçw”ûQ#Xã4D´[ôÞb!¬mq1Ø¥Ü ëÚfW&æôˆíA"¾f,«iš k®å“r½‘K3&¼:—ežg´«yÏÒ2¦w‘8î%Ä<ŠÖiB!o –Í€v—8DàÐA430ÀŒØß@y(¯F€t5JQjžnQí©õÈy ïˆie©K¸ ’ÆY§œR €jýÒ¨öìc¢vWç(}XÚˆ¡R‹aÌÌÑôm::àjù9™½‰®ßŠæfrWO"è¼¢¯Ú•-„T(dÙ‰úŽ!Åüæ´;a¢y,Äe:y&!û1î‚BÖ)÷ >yc*"5ÐÖ9ˆ[âÊäÇvù´¦G]½Ì ĸg’Dâ=õ䛓Ù9€+@½Ó©Ü—³=Ì¢ÞjkÅúXp®c„*ÒV&tuøX³sZ ¹¿æUNX.î©!º’hý½˜'ÖÕÙìÂûýx"_ÏI~ÈL´?ã´ÈËÇçVÈ¡*Ô»ª”Ï<†ùèj8û;¾„¹útm ùìQŸ¿ÕÅ~¦=ìlÈ×*'.>_O Ñ5â}7`§ãH5fW¼ÏÕœ?8ŸÒ»{ÉY0ÞW9 4u)ÌÀkšç36ŸÇ0‹.Ÿ°ýÉ!Ö·Ï loûI¾îPÞÓcÃÉ5½–ë× hø!ùýK?M¡Œž¾Ž†üþm.ô#=OÂæw û=C/^Žö¹;%wÔY~0øê×^âøö/ªGúû7a}UÆù”£¤Ô~ò³ÒOu¾Ï²þô?Fílžîgž)ew;ÓØÅuprô{!Ö³b|ßrdˆýì#û g?]æ³õ½^‘ô,Ÿwõ4ºqµÈ]@µeH.å#­ê¤é¥×”orɾÓfŸ½®%¯tHäuÍ@ôÓ ÿ^|l6 ý!Ø.Jÿ$o||õPß[øòx$¡r–¿Âò ¯xŽ,“¬u„å²ócñ1ÙÑöŸ]r¾ÝýhJùŒ×b™!q¼¯èSü‰Wó4pRyÏâjd>ÓÚj Ⱥ›ïÔ׿›((µì¢;êìhéO;ûP|/&éJ`qýéN«ï!î >÷þÛ$×íz¾F`|å=<Ç“¿åYþÈ€€³Wo GÈ{›k§²/­AŽg q”à/0‚ëMNõq^é뙸+'Ÿï'ëÖÊ<ßù¼¢¾]qc̳ú¢È>_ÉçõRÕ¾# c9s^'‰ÓµÌ5‹%è^lL´4…É]¹åå¸u“@™ËÄä°VòY±Ö„©}c­â–ˆ8i[sÇä¥ÔHo ídñ¤S¯É¸ØÔÛjTÒ)?|ÝIj@ľŠyÅY‘–@ÛåëÄoËd“®Ïä’¹tõpTa qÇ9ä`c%݈Ç0W¢ÿúähT£»iÄøi6„ò˜¾)§OiÄ$µ’,òx¶&…¤UâA £:™=­[q& T?b%Eªå„»"ÒDF*Í´2L;r«§;©O•*56ôQÇP^Y1ج¢Ùl”WäàÓÌÚ Æ ï4…Ðá„°–Щ+A‚§Ë—Ê5€QJBÙXSSW’g±=ئ q)WõÞS//3‚4 k‹‚±åEÄ¿²| •;9Æþ€<Ýìñ ‚£¹Eò¢t7DÁigZF&:ÕAÁFò&[S€¹'mƒN!>Œ‚êU9­LâÂÔ#k”U¤|…ú¹0˜ÏNŸÇ|ÒRC[IÂÃúþ¯L_õž!È« ¯'9ó±†6;Jæ òÊàÕµîË5ìŸwöJ‚¼ŠC¥E:wt’ù¼ZÐŒÉéX9¤Óä%³yZ!ŽŠgtQyÌæÙd‚Íih0’¯wcè ëÒPa«kÃï;ò ¡´ŸæØ¬úôÁ‘ïäÛVgÞwo«‡o¡‚8ïè”tI»†`â)gü!âl ¶¸réI!_˜×@ÿ•}UŸ«\Âðé÷¿ÃçæË½Ä’ïNÖàó–|œDýp¼.ýI!±«£B*¾Úzt—'á9 & WÈkêb¿?Ë[–;”ÕØoŸ"”Õßœ®Ån†L~^ÕÇÄéà2¤ïw‡(Ø\º/Åéªà¼æ™4¤G:Oý“ˆ÷5~R”AõšèìÈÞבϪ˜~l]úÙÀ×{‘È^µ ñèàÊZ¡¥?õs“³3»xõrDd{¥û*GqÐF>“ƒôõ“±\+†ìÌÂØ cã 6¦¾â+F߯æD_z¤Õé•ÝLîúÔ‰¾:wtÕ÷,ûêÁÄ·3í»â„¬8ÎB_ŠOö¿Ë3ƒò÷WC‡Ax­üG‹³ Œ£©¾Ÿþ-ñ5žÅØÏ޾®5Jùy+ (úÕ_ѽè§iÔ| <{{ “òVyÙeÈÏŠ êôeËgóÉ~‰”0þ~²+{3·… ¤ÞQ: gﻄŒ]ã õä6¾ê¸8—öN~²™ÎçÑQO=l ÕmeÅ™‹oÖíÑCÕ•J1Äëéa tÝæ[ å¹To,ŒýÝ}µSNš-àÅú ãª~ˆGº§Y=“Ã=‹Kè,ä÷ íÁ\è“q)%ßžŽ<‚‚Ìkâ.$¾¶.ºØN_†A2\W#I/Ýïì;¢…|_Û©÷oó“I¡\Ãë†òûJ~¥}}&P>#Åý$hHúgƒu_~lÏè·”JmwÊãKŸ˜Ë*Ôk)÷²ô±ªXWçCºâ‹&P»2–ÄÑÉÕ€»H_…æLÙâœ1®Àdc ]%ÚxÁKf×-hˆ;z¤èã²P²Yˆ»q¬ÎÐîèGb ¤»¤Ô…]E)κ4³¶ÎÐŒâÌ”z`Œ£í¤êµ'®[àðõÊa'$ÊwÅ8„Qç•õŽdÓxLŽ ûŠúN.¥8#l+Ê4 X¶†¶ˆÇ“°±2~!óÕ0ÍjQâe¶g¦§b™u‹ÜÝ;Ä‘¹^•O¨Õñoóˆ<,ä;!Çëo”5Å“íb}0JF¹ªó’·:ÊÌíF^™ì2—a y1ÏÆÔ"·Kò|Œjå»pÛtŒ'ŧyG|G¨›‘E]E4_Y[GÇT;èN$Ê[v‚Ï]ë“ C¼æÉ\ÛÄ#2£~Tæ•-[IÀ³1xúeˆÔ+—%Æ|±oSˆ¹WþZ/¼É®:oó¢uùYÈgråÉ.ÆØÑV'4š,#³ÏH=ØnÁçQïO JÚpün 5øÜÌ3Hæµrðá¯ÛNÆ2 ®N”hŒ+ž1Òc”‹ußé]*?òtä¢Åáú´(ŒWwX° ÖB®„Üåú;‘“,¢6ÄH9ج‡j‡—¡¹’üøÛgBýŠŽ±å¯â%—¥Ñ-µ q$“nÐ5E>Kç»yf¹c#~=õ àÚç“¥œÝd½³OÄõ¨«{—ü`ÚÿNg å(}*eß‘Úg"+Gì!B÷´žºÆâK‹ÇÉ¡ƒÌ=‚…Òÿp,@É5¹ó!T Ži/§a•¿åLïßÍ}üömÈ™(jØ+ß½>ÍOÊ1ŒÝ1Æ#;šw‚Zƒö`f°Ñù%g’³ív’¸âlt£N-êçºP¢ö3î+ûèMu?Ó³Ri_ö2ד¼ÿ­/ a†ñùTlܘ¯ç9…ÃWæu÷â;[;û¼Z˜`÷N¯B@?åyK¼Ïx⸊o³Û£1,ד¾ãÁ9¼wI®x#ŸÙ¡¸q5/ÕUŸŸ)?É—üÊï;P =”kÅ3¹˜ Ï‡8c÷v] ;–kf—ªo.îN¾FÇZÕ³ÒqO:®Ô•]CNtù÷­gq=†ñ\$Æé%«žG9¸ýng6—°^wòÑïî»ûÈ>û²ó+;ñ°~W0‚ü]—â:»b[óP¶úsI(>ƒÜ_ÐwJg¨+…‚l®ý½PûaXVϾi2fó|ÝÙ5NvÌÏÍy…vÂz,ܬ|ö1Iä`«‘oÁbÈ÷EV|:ì^|NR ûÞùLgýÜñ•}pp¿»/ †“uY¨>2ŒÝCŒî)|‡0žqªyƒú\‚Ñõß -B åýN|aW½îN£Pñq×€íeäË5_É‚©f–êѸÔ$é×PÛhÀ}ä3+™+ûRŽŽ;ù» žåZÂ_»Dóeu/ƒÒõ ß™µµªvÐõÉЅᥳRnA¼îÅðˆ0®ÿ5ó©L}+.V†²’7sâå~Gh,Ä}', rÐ9”*yÛû†ÒRÜ¢ÊJ!fֽУe ´>Z¦¬ÂÁâiŒÂ‘± ôNt£–»‡ÞÌ|ÙÓtca»…¦˜|¼ÈƄؗ…¬,g~_¢ ëºs¨Šýnd¸ï ÝH0·&q¸óº2Ý™øKÁã~LW"–ôf?®à˜RŠ€y³«‹©—§xqö „Ü Õ¿…‚“e®.¤9X{wò"º.Å“¯Nº‰Ë.P+ËI½+÷",íãÏÜL9Þ5per0n•‘<‰ôDý×€¤Ý‚5A†©«¯ò0õŒˆùNsÚ$í Idfˆ+äºEî&Léʘºp›¦» ’]…˥ѕˆ€j‘¼²Ò'ÓSQï&ý‰j±¤/žDýJÁ 6.‹NëeË™ä¦/°‰ZÅ`”ëbb”‹ònBJÝ|~Ò 5Ð=9´ètIPÕêã59XH&m5B¼Oª]½Ù•q|Ìù`òg À9ú{ˆpÞL½EW£Œ+‚rC‘éI¾ÞŠ %Ÿý¿ Û¶“)OÖÕ)0ú£gÊKÏà…»Ò¸5ÄÊ*ÌÊÛl] À—á¥f¤˜yÙÀ#“e°»]–gûj¿+aõÒg‚x&£ëé‡&ì¡ެgº²#Ò…ý f¤ë31 vg½sXQæÊ§jþ ñÚâ,$„6Òɨ­vÁêj8ç¶ï¸ºv/¥Ê7û6Š+··k‚Ë´MÖS­(s*YXLë]„¸|ù}8ä°S^ݰYnXz%¯!½ßù•9æ£ýn V}µCœd.c!泃ͪA}›¾^Ýcáíp_Ñë·TÞw;ÏðÓ¿cˆrÔ9ÉÊ×QC&Ü­œ"4½Ý†ù“”÷Œ/ì§ô ^¿¸¾å»DꡌF0ÎÂóŒÔµ+;ngq‹§’:ÉÐy5¿ð¬{Õ32W>rP}Í9)öC|¹§º‹b>ã§X(:ÙOt—$ »ë·ôPŽxo9*ˆòþ½Ðr‡ôݹùüª³JÅS™ÑÀ!¬½=à™BÝ:aírÂátNùÚÑ:ò³ˆºãå²CÑÁKöm=¢  «·ƒ˜W…¼lOÕêÔÛì*‡¶Ø„èíóÎÔ•ð¬wÇò‘è¨õC€B~²öÿ ‚D·q,A€ÿ2SeK$€·cßHJvfõý¯30€Ç4lLèÒgpéÈZ3?‚GŸç@ëT\ü|2΀Œ© )-XH{àñ˜ õ{Rë!SZ iœÁŸew—ða½[¸0G™#yOYw„éà¾ë©bH³‰L.èÚݸGg^ç`ìT÷¿ñÈæ~:+PŸ,OE‚|w¢Œ ˜‹ó=1:Ô§á¨m=ZF º2æ)‚R2óÝ=_Mb!AÈ]äJÌwä6´ª´Nre*£`Ê.€Õ„8ôS¸2 Ò„?Ñ ãŠ!5¢m0­Ììî6–¨pkˆ- J[URâ4¯¬Æ|-m•¤F›ˆ¨~µŠºfŠÕè8Ò&èÜìh·Ay"ô&zu”IB˜º†>”ƒ¬&i’"ä ™­ c£20ÿ;à|ÃR¬“BÀ\Bœü`¨KNÇ­Bz*¢ØŠ2·ÈXÌw À<“´AA¹w+"‘þ2:’q­ˆ--æ–‘ë`žQmõ†AiOJÓ’Ý„ëb¯ØŠ§ÕÀ{¹,ÎNÔ™°î >È&ËѪTV'Ä´Dr/<+•oâü ·*ÈiE,[€ÀÁµ1¨ì õIž¸>"³2úÐ Ë2oVo޳š®ˆùlnCá!<¶½kôæfŒZà1#±kýL3¹Àa\›Oƒ˜©ÎÆ©á´>ùHgîØ>‹ˆÃ ¶—yÃZ±~*ì¶jòùŽžˆØ|FèúÌ „tßæ¢ï)´;‡hP@æäÃÀàÈWC†B¹jpÑ×èÓ2¶3}.u‰|½*0P…1‡uMyíâd„z/>…&ÃØÅ™ZqV  áüÓƒ@œo®E4aÏ:¾…3ç…ut<ÚQCjP÷G(…â`Þö–ƒØµªŽ-|ƒ~ž²7;c_ë©§Ž™ÞæZ“çÚ@|–SŸo ŠíÓƒ©ëÔ÷ŠaøÃZ-êíó*þ7¿c8Z+!›¯¾^;RqYpÜûàÄÉÇkÑ)ÇL4Ú8U ut>b¨‚µ—ÚÛ>7C=«@ÿ;ÏbTŽ8/ƒâg¤¶ú©Ìg í+<ÿ.ÏBêGö8W<#p¶q -Ð\öoÝõ1j¾ƒ<·œ‰HÂD­=… I]ïåà zÔ^Ó+þ&8æ3‘Ë.î%‡AÚ{yTš‡< Û+ù:‡Ë+”9ÔµPçß'¨Q9âÞõLDŸ›K|Ø;µB¡Ÿ-òºŠË‚Ã¥õmPOC½wuUC~¥ï£¡xõÐG9+ú»”)¡ŸSì^ñÝ¢V_ž‹yûŒ4;ÿÊ)¥ÿ–k!4×T꜡’Õw½šéÕ=¶Â¯Âl§Œ ŽþO¾?ù˜’G(3ŸXCn=½#ä†ûY¨Í7—WþÙŸëD9íM½Ó‘\b|fÖ¾­E`çÇX¸Ç¿ÚseêOú< j„RošKÆuÎ@ÄùmÏ%üˆx˜Ÿr¬®ýL³î÷ÝŽ$CÚ‹qèþ3B‰VΔgâæØáxòÙLâ»Ï¥ÔƒùP»Æa|6úàøL·ÌÕ½1Ô·{¾ÍUfui6OƒéÍדý`¾çßæ0¾ã[ÖJGC.æ†qúBù¾“ßЕg³æSlÏ8;XÄý™Húc—pðygW[€¯)RÁêNÔŠwÞÆŽ¼DÔÚŒ4æU)>œEÆŽ¾e>ÎΔˆèÏ»Å6É¢Ú®DWvùÊÁŠm'š‰ðL+C~b^OÄY£¾uUÔê#R[ #šqt”îÀcéQ¯Lp¦]\<÷A¸ ü?Ò¶‚::¹Iž0Žäl ¥zIð§}ZÈ 8ÐX"Ðü[¨tÒuiøkˆØF‡8TÎxoÑ‘w?Ⱥb¨W&ĸ@ï°eÔe$‹I«Lª½Hêc |·DwÅ22ImÅ(h#È)ij`« ¢®Š\-&iËëO²”Ë¢p›`M=ŠLÃþ‰¢T&ðw(yùv*“|€>µBâˆ\‡&å¾Än $ÒŒ[÷€P²“; }«õ!„¾-‚•üì¡N1„\ Ÿ¬: J8}mZ?ê§Ft]‰JíCà88­JÊ22ü,¬;¡(MqyE¬†RmtpèÊìÌŽçÝ‚ëJõ‡’Õ·<-@´Éjô¤­c1€É¥Uô̵ževvDO’91’äó=#\*s[à«ÇV€k¼ ë_­/)Ÿiʾ[_!äxÖ»±˜>&}fs(»! TOµ²ãcH×»¼ßû¤Õ\ý·9‡ñÃ\G:äl5äݰïÛ'˜ŒÊ§B3躋tH‰bMÌ Ùôóí h#¤5è¤PHzK¨ÀÅ¥•Ž3Ê¥4žz&/óÐgg¸Ö]c)®Ö A\Û# S§½õ¨yã;Ô} È9Iúˆ¡“¥#ÍI(~Í®¯D¹ÐþûÙ»{÷t zóiÔÀ)È[Ö¶WrCK(¼çákã|M°f9ž-è\r_쬫;6¼hC7š³„g<êž ƒ*ûvY°˜·¯÷'¿øè Û^Þ~ºk˜>ŸËgù=wq>þ.àë.g g8®ÝQÆY½Þw; Z†Ï3\(G:F~™“äÛ½Ö£8ýó¿~VÐÖ÷:õù·«+É«íºS·^‹Þ錅¯Ïòd‡ñ^â7™ñ¾Ö™›‹×gøvšÀS„üŠ{dzJ¡]ù@å~”g©Ï'£+w;J£rÚ½: ¡»%ß,§kñ±CD¼?í,òQîKÞv”àÇnA s¸ž‰o}u÷]\V)G]p¸aþ¼ÓõqS ~|ZqzØh6spãŽ.L§î|§¤¡¬ìSòÒ矆çÙØ«/.Þ¾Í7…y¯`øJ~<Ï'œí[¡¹¼ïö›‚Ÿæzåêú5éHg¿¾Ý% ÙɳP0´U¡Y`7îÅ¡û!¶[üøwZå ÃÅÀëîÐ 2”{…óGÂLÙüøÖPæAÞFS˜îða\ÑYzÄÙùªäÇjš3ØK®EgõHΦyQW|ºv ‹Œ}™ÕÇÎêãµÕ'Œê]°f¯˜rô€Œ\mƒÌ;A…(¸þLè4¤ÞÕL‘ÊÕa¶€ÇøN†¦öŽ3ñùÙ¦D¢ö7Rˆ¡¬ŽpQQL#…šØB²Ï·W¦vgœ†Ñ—5$NÔ`«gÆô¾Ur`ä\žàÒn^¶7ð©SX|øÏ`߇âmÈ$+sHD)¡n:=HŽT{À1Å£Ç>9” €<'ù%ûV›ƒXœ@UƒGmF½"ûtg/AYÙ§fÑ´N›”! µ tG!©3[KÁÏmqGSŒÓâÝÀû¼³—mˆ˜{àkpp2+é2ŒÛLÈb߅Ϩk«‹q¤¯,&é²0æÌ!¯ˆl¡ÎJBP ÉL‡h¼£Æ,|B›D­q@l‚m%`,}iÐpe¬[ƒJRfAŽÜÊV¶è¥gD摨,Âö‰úÙ ‘'âzRHœ&Ú½Ä9ÞÉö“Ài„¸’È“|]è„Ú–8»j”N¸¿9¨ôæÒŠÞù°ÀÕñ³ÿÌ zfŸï­§‘}{Z@wÖCïOõE•ÂpÔ zõѰì4ÅùšÒ¹Í=N6íÔg&ªÐ×_$qy);žä‹bûN5W÷V/GU,#zC>•_ iîxK ¶§pvéþ;P0/,«güµ¦§ëPæ Ça°=ªÏlÑõ•0ÄæJ!†T\[C4‡ééÚð;S*>_™]9eŒì-”÷Õ8Y¨³ã;áèNW>Ñ~pBŸr?X±½ùº8ôwÍh9ú’e‡öxò™ðÌWùÍòaãɧ†*z/;SðÝ¿ÑgÔÝrõãî!”_F²ïþ.*é5frCAÝ; tœÖ{8ô5ú,CìçB(g!»ns ´œåÏfkî"kA§:Þí¹DÒ+B¼ïâ;ü§ìM(Ǻº†äbû»@’[gh3úb‚¹g@þÏ8šÅGóó2/J›ëòNPsè$ñÍçÏßöŽ¿Õà§½ÓØÑ%#ìÅ0ò|ø¨0öŸvfãô»\‹C9ÍA¯õUŠå—´eAüDš»Ae°³][¨âÅÐWö0‡4oÃâ2RÑÇÕs|ÿ‘PÎɼ¾õ—œ /ù\šÓÓ¾Ÿüî©߯”_ÉѸâk€¦ƒÖ…œüùïCÇšÞýs©G÷qv}Ÿâ9Ÿ‹r;íÌ×]Ïö§lGš3…á]ÙçŽÙ•{*vW®gc4Wδfä k”ç©/×N»ïü3ò[rÈÏ@nG^+»•úþ\Bõ,(£ÐQéÈ»"ꉧÝwóMYŽ~M’…Ó¹2 Lc9Úÿ¾ÌÝ[€öÔÐMêJAKHNöÝLJGœ‹ò ö¥V@†ö\’ÊÛ\ú. “˜ü˜íÄ"Ä9c¨˜cèŸ9½ê;ÞW†¥Üõ,Šv&×þ½Ñ @ Ö'—â8Äš6ˆ@í5¤ìé¿rm…zÁ¸onéTWÖ•éQó~>zöÖûï\ÞƒFÁŸ…ô~ÛÒ°+á©3y€He0ÌȆéª@%o¬MñN$ŽF×ÔQÙÖe«¤ßXµ)ôiFÐï y…ˆP¯,›BÝYsAuÔFÄÎÀ¨3‡ØP‚Í&²Õ¢ö+S+^[©³?|ýVˆã!{›l !ÈÊ8&§`wÇôGCùV›d´Ë²*U{ Ô’§e.nñ5A<ñŸ•Ê¥P²)×]*è¨Öl)Øh¢2Óü!^ö98´–ƒ ñ¤:#µ…!Àü[òŒà¼&ïR'PÊ`vcÔm2·°Ñ¸Ø¦hKÈCÀÊî\?å1—:a”šCj‘é"¤f€®v’Eb¦½1¯§´; #7äyÔâŸêAÒf™3 @O>î‚jñ"¾6¡ñì˜n¤ Œ€ôîÀ=›h½ ›ÀñÊ!#3–›yvB…U |40Õ?ï‰'ÊÊ #)z›ª³03^•âÏ+_#¼Ü‘ÀFåCθ¤ÝY\þþ_‡èbuqÈû?¶.oRC}ªGrƒãým”ÏT¡ÜÉ’ýY j†þ7ž€aˆŽ. ™ë7â xÝJ1ÌJkU Óó$Œ° Ôi Ä+ÈZtÊ9U‚Z¼@öª22·+ùh:Ñæ`ogá3V}#[÷i6ô™¯ÄóÊNH‡ËßI¨pEÙw!Mžw ˜C<î 1ú¸·QÔ'b™U#Y¥º½äLXûi}4—Cr)½mnÐÝS¿Ê_ ÿ)Orš\òR›=¨¸´&ZÑíôþd§gVúô’úûäçúiën§KÏVlÔ æ“Þ¦aœ²7;u5bÝùˆ—Ë× ]S_wvªÒ¼ô+ƒùL8ÖËQÁõ9ŽO~Å9šÏDs§3)Ƴ^“ Õ‡ûo™–ÚlàûQ˜Æþ…«Ëß‹1êðþ¿}V¦äòÝ!$_OúûO9#‹åûA¾ŽèãìíH”Ê»_ db ñsg7Uí]çBª§yW‚‡ÿ›îÇût–çóSŸvXñѧUÁÓ{ÚsQ²CB,-†Æ ÂêÙ'{ÓA©j°3J¨wõ†‡º8ÓG£²ì£çW¾rÚŸîZ‚ìÒŸ aáÖÕÏh}¹úø_ Tc>”¥¹vÑíÙ*Ée8éÌ«¡=®¡|þ]®Åß<7Sþ%§ÞÏuÆ Í«Ìa¾¶ž“Y¶‹‹çß|MKШ_CDOóé~F¸Æ¨åèœg•³‘ðQúði‡Aq :²Í»I?²¶U±˜“ߨ»èàÄ 5#û~Ç` 5ør'WS·ŒNa‚=:c¯¯K!*ÉÝ‚9™5àŠE0¶jäH©(ؤÄq6#«¼uM £Ç¹/õÒ=8-H!Ô  (Ê,!}D´Aï®,§­&y°¼a= »¼ú·Q™ˆçct“N£@l‡8ê«à`ÂÓöŠ¥K 4. ÀéÓ€ÅÛ mª_HÆyˆÕó+ÌÉ2°ˆÓ0`®ï°:RàÏ ¾SÉ•xÙAˆ=r›¤K¹f ÀOG»¼‹©eð>=cv¡}%<å \w'®Bo›ueDLϰ:C@yUt¶A»‚³©8 ‘êS°>BÞ§a´2ÛHœ¢weí¢t&ŒÍm·SWŽÊåf_&"J«(K[ñJÙ°¬zƬ÷H$¹ç‹ãwOô¢´»qÉd/û<of€ö4HvŠ—VÁç èÓÝCÔ`'¯Ë JŠ6Ÿ²ù|ß9Þ¬>ôk¸È>½eU°Ò¼Ò+DÜ÷ÄPßÞó˜v´Œ \£×ëP'ß–ì"†¹D²‹àËÓq$á_ÜÒ鄃Ʋ°äÏc²PB¼ŸäþyG³û³ãq8½bÈ݃—5……ñÎÜfd'{‘+lŠéO“Ö0]mç»êèH˜f ”1¥F¯<”¹\-àÁ·Ù30šíÉ4É(¤e®`¯½^1"ÔiX[ˆÏÛ*qFì…DÒ\)®ÓÈLÒŒ˜&‚y&ۙ椔ÚXéL̶’\ÿ¨‰õ+cç‚\Õë­B˜›{W<‚×$Ií"wÍêË'qDÁÇõãRo!XP9 ÛéIâzÔ³+ eGTKwL÷Dïè^ï äJ¸/Ö˜ŸFõ‰’„‡æ]ƒs¾Í™Üò%ñîçA.'ˆW&e[¯Éè®X6{âr±ôÎAâ·RêÆÁ¥;ÙÕHgå´”Ó }ŸÎ©G ¾\`S)4¥2Õ1X;±g„¶QuJZYráKBYi©­‚(¡)H‚38«ž DÙEÛTÞ7¤ÿ5aÒ¥P÷O¼³'‚ ¤x}Ä·&(ŽÖ·z9J•þ *‘®Cûw ÕB¹:šÚôýÏ¥\Âj!ÿéìm½i€s ëŸI¥zíCBÄ*:g ²¸ì.d~0Ž+LVCûçÂÞpÜ µbÚ—bÛd]Éu-_)Ÿ-(2™ç-N o:$ˆÏÄ9ú3Bª/º8t·ÊÜ"åNåNÇÂÃ<ŸâÙ—îtr΢6ØéoMïò½”U6ç穮꨾> Å~^g„¾Ë[élG}¶@>žu¦C,Ýç·ºz¶lëN^™—k+”c¯=ž‰iœõû5œ°”«™³Ó·3¯Ž8\Aý~+–Ö³„ëYE÷U~«—q¬¿ B~µ {ÎÐ!ÈKrEÃ…4f}U’ìËÚŠvT²çŸš–©{W¢ŽÖS¬IÒ;±=ðuÑïLÉÞíóTß´{ôéLú«ý»¼ul‡ÞŸEumÎÓ‹>ä.¯5Áõ\ÀY—Óg×Þ)º}ëzbHG‚#]ñ• ó;ßÓÿ..úþßv%Åq¦ÞÁmŸ‰®–«Æú‹©yßå½’M(­A¨‡ºŠþŽ;îûRnïì ö.‚‚u?JõH^žÇ`1Å3í[(íÄÑË™ÉôÕï‹0»tb©öjhñìWGÍç¤xÿ½aƒ$6X;«O÷SÞõ­)ôÝNëoyésóÙ!ܳx1\Ÿ;†? J÷ÿõ`»³Ú“»=ׯöfvÝÛ‚g¦ç¡•PëºÒÏŠ®HP§©ƒgò¡O=šîÐ} Tl ŸºËêXªÓ5‘ù¤s*Çpÿ]Ä 3ɸÇÙ˜ôlŸ› cE»?ù\H9ìçBjØc‹®«™Ÿw ¹½ɼrh¤êÛ.˜'Ø‘ïýäho½/ è2k›… ¸ù,;4‘1wÚÊP«O§­©P+嬾6°·õn~“±ÏcJ¯ÔBj=Ê_Šèûn>F´PîI¡‡ŒG^ZÆæòß¿…‹SÒ½ú#ü4d \£%8¯tèè)'‚ßéqܤ ןŠWÔäèh ‹RjªŸÄŠí3¸>¢@mk˜B‚ã›$#œ¶ê·(CýNÌí`´u™$¤§AìdA渄ëU¸VŽA× ü”gp­!÷Nv!­ŽÄcÉ!Ö¶¥ˆâíšHOÀö(䌌\—Â&QiŸ$³‘a½ëä¬ÒW—Qƒ\“°…ÈPïžKÌóœj¡£ùƒ\¢ÄŒb”ñ4”*¸X ÔI²ÌdêŸèòDX€ì[(Ud½±Ý-FË]±.Ä:4þ©^§Ø(Uk½`ë+:cIúDŒ+rkÁ—Œze!J—bk¢F­’ÚêrSê)ŒM¢¥I”«’pɯ$ÖgŽT"¤/³ utmªŒJé›RÒ¼YV!áôí”f"âÜ{7¼&ÛŽ˜Rݽ"eIúK©Œ Ÿú£!§³U~{ö1pŸæÚ’<: |Ñ«Oû§1lI³i¹'ô™I….’ÖÍ+´Ò§MÖÜ’SŸSHÏ bn`ëN!ûh!Ïz:äÎÖ 8åU ^É#Ç iuÞW>ò“ÞžÓ£²:bÑfÔv Áë))¸ˆ-Sêøò˜.µ1¸2¦ÆÎØÄU!ï„í§/lßÅÀaF,[¡ùȸg³›‹^]ýó¸”Cuù󷜃 ¸¶FÅýÏ#~{ p}›‹ÌÛé躓ÓÏkž*X¡üù_¡:7W¯2Ì»4WÈÅY|gg/ðøÆ{EgLvÖ9)T—<Ì»‡DR|™ƒ¨þNžïO÷ 5Ÿqlæé5@îæ£óe.–~vò°4WVCÎ8(ÝWñ‘ýmoÐ<™q ûï-"ïvÆÏæ³i³s~nå‡oNWw•j]þl¡Í0o~—*òÖ5M¾"åjغ2ì§unJe6¹²§·õó-‰¡ÿS¡Zˆ½šd¹Oéf Æ·c|B íOåJ §Îéü8’r* šJævwÐÄóÞB·‘ByðˆÙS5ttwÒJ¨îSE}¼“×JÉÓ¸ .ôê=‘3¥S?Ã#ißÃjƒHåÚ†;@½:×rdJ½…Æ6g9$´çQù‡óÇ„G<íI&R—Èn¤h#žÔ=õ;âšrîUÒ£*Úw±‘‰±<“ãe¢œs1ƒîìQCÈhpÞ®l ‘ÌÛŽZXzá¼Øˆú¦P3ÐYY"1ÈX&» ’^êÅ…!5Í_Ãp–;cšjˆeDùT‚P>…b‹tvt{à~'.]T¬u•i„!.6‘E涸£ §©qÖ@­‚L!P•JS1¨3Å!@ùŽÁ‚P›þÜlOuiU©ÓÃìûÍбfèwB¿BÚü¸(aÿíœ"ï7õ•<¿W>òP/—¯ËÞ‡…ù·ÆP ÜS\†š)õLí ýó)ÜqgÙÏ€’í'鄹âQËÑö-ØÜ’tô*ªÉÍ} TÞbû©n’67ÿ~D:=œþü»Bžiïhï Ðîü+#‹¯× G8Oãj®øRñzšãŒ_/cµS]Œa®Èpz)½5Ô¦÷=(-—jR_O…c~úâËQF37ΔBîùÔÌ#ä=õÍGÒP¯ "ÔÞZkäáñs÷W°Žôç&gyUª‰ò¯Á<Î&®îz2BéþVL>1¯§B7û¼íúZ˜¡‹Œ—rr4|ôzm>—©ù9v´xš‹÷Uik2¿Ÿ”];p¬›DÏñ÷Ò:!»üçïÀ˜]ÛÝIwò¾«ßÌþÕïE¢®úù(ŽÉÕ«žš}~Çû“ÝFöðìth<äÝî%Ç”ÜþfGêi÷"ß»pÆÅM§íª>‘ÂØÎxh›zŽ`(×Î.+´0F†°]˜WÇ.N~Åû|Žu¬üÊñ%½ÃOõ¡^Ëí¬í˜k ´sˆ\ŸrµæâŸ?~âoó¨XV;©¸"T¯Jbò9W-Õ7Ns°»ñlÇiÝ•—\OvS£É^k CÚîŒHpã¹0F§oé9œÍ+ºÒŠ+CZÈ×À0NbO%æìš‚ÕRÍ…jôt´¿ © ¾îäUPÇçaÔO -IsýÙj @ýš>W—g%™>;ž=‘ëÞB‹ÒZä®Ê‘Êì(¢§1óo ïð;µæÜÀ ¼–ú¦bn|ÿĸœò| ÞÙêéIm¨+‚ÖŠ—‚hÝQª%ù®PG`‘9€þ¨Å«J­’¸ÜSmj6ê»ä8`‹N–*ƒu 5žè¹Äfl®F-tòµÄ¦ B쵟6º 1¤mô¨žzǰ˜÷.¸§*êœÂƒ%@ûV»; äOÇx‹÷)8ŒÒ,7 sÙÃf$Áö§SÙ^Hæ¤2§•1@§·,a(0Í?RGEO²oc yÇd]?öp(5xc(!© mEAžÒÇ‹-¡Þ˜£î2‹R°;ÛÚ Ì»Rý$&‰¡D’kŠvC¢¸™[Á€:«æ‘!NŠ»"`º ÆI Ü;ðêxœnÄS¶q¶r)·J ¶"æIŽ´máÑɹ*Õ?Ecœ·ä»$wæ” âe2r@‘'Q{*¤âã]HL/ ¹'!nlF@¢¡\š¢Èº¥Þ)’•¸o3ÃÒ@vÔö1l×O¹“C„Ü·½ÎW-XW>@tÏ­¡ûž¡íxÚ…õ¹í;*«8Lmbl½B3¨wñ,:¤<—ÒTZß|2Éðñºø”sehWQ :°ß] Cíšzšpö<²÷Våút`Ls·Ã™Ë"ó¶C(Ö?£&ÛìºSÐ|ä« ÀYÚ]½‚f(ß\´³”‡BÝRïìÎ 7ñšâJñíÿ'†qëÚ‚Í\KM8;öd·ì÷ógªf!~[z¿ÕÑK°Ù€„–‡19$iUÆûL_XϪ°ÞãDáüâ¹í¬?FÐç²çtÔ½óAY󢎚ðúíAòwñÜW9’“Bc6ä’§Rè(Ö]䳸ü¾ÌO-æËÎ>&¿ƒí§cƒ¤ášã´ú*Nç{¸j µV¯Y>8ÞWz©ë)ÌÙ±4€?¶·åU²|~7ŠbúC)ó×5]8\ôi_JíÌž÷ˆ¯$ÀG®+é “åþL µ/€yšçµã+"òO|qþ!W·Ÿ‚Z¡÷%C§òû?8 Ë÷`ÍÐC|îLOÌÑ­»cì¾:#5c¿r¢îø¾à§b*Ôv?)ùîãû]¡„”}}f>5䵊44ruG—:ˆk'?_Q|ç—%Îî-¸) ÍQKг®CwÆò¾µåHÏäP G*µûh!ž¶·ÑBÝQ8¾ºðgíW± éj\·±3ÍÄʳ4NNˆý騢ò¡w._a,>‹¤øâ±$öÓB(»B8ÿè{I™$¤%#\LäÊ5dìS)_K¹¢ Ìßê­“Yò„g^)´q†šW¦ÎäaìJ¹r Ôwä(¸R²ŒÎô^¢ˆhìjƒRFÄŒ¡ÝÉv§g«v ã•¯âKô ¥TÓÅͨ^Ùe9ЧwÞ™ç;;K–ÁrÀêð$3"SÈ#‘Æxw.·J´¹‰W1 vnWRŽ{º8gW‚v!œrÀ«2Rü˜³Æ@ÖJ€«P2•[ Âñš¨ŸJT…[%r8*Õ' °GËÔ4M‚œƒ÷ÜŠæf}ù›B.$,½‘4bÆüT¨ e6ΟH˧H-ÆWE[ ÄÖ2õB‚z7HÛ„¹>‘£Iù •!­¬Wò$ienp]¥¤D:3ç/+Ÿ'àT´&_>•Äx Î•˜ÃèÐîPlRº¶bŽ^&{Þ>[¨@¶S{Fb^*sˆ®zÒH  ¡ÖpD½:•Ç<ìl½) >ƒûÿU¢©åZ$ÌèóݶkU(QÚS9ªuÙ‡A^Õ{È âïeÂp%Ùw†´¹ý›è=ãº$(i“¶ ³QO’*¿„ÛìjL_ÙÅ zæßNð ¤6{‰cñûß­–e‘”L?Jçú¾“ŽÀµ‰kGí4®úâ¯À{‹¡¹Wtu†¸–rDñµg /Osëa¡fŸ bÖ 2·úì³øtuoJÅ—k[¨gVÏ`lGzÿ6Ð2×½¡G.¾7:õ-k™3d†æt-òævŠ{ˆ·«Sh¤÷}˜÷$ñRZOÅeÖBS1¹.Úg…¬u†\‡"ŸMeìø£ú—ì3½7¿†ÓHû./4_\¼vÄ·´„Ï¿+¹êý”pqVyFúa9›×ueœŠîßC‡:Wvö"ÏgbNܽµ/s-RÖ)FéGûTÚ®Gž»¿D¸¾x5ªªŸ|bé¾ÌI‡yßÍUÓqØuqè4U÷sÅlb¹. ù|Õ³ &?îÍT*ðý»8{Œ¯~"7×-Îg1¾ÚÝCˆÐcj³•Er/„øêTßWƒ ¹ºò¹Xk¨^Ï׺´ò2/£3\ìgâè¾bÙ[ýD…0Þ›jÄyƹbȯÈt]5d…á­ÍÛYÀûw`MÒ’ Ã<…ëïŒB<ËU½ï¾®YÃа´•|ò°Žzvõѵk›N—B軑È~æuG»œQy¯xNÅäí=<6Ô“Ÿï¨éœ=½Bsãìñ(Ló‡u⺔`5Œ{8ž‘rO?Îûz+ÈaÐz7©ë×D«ašÛüíSÇyŸ÷wÈJ}m®é`й“<±'Y»âa×VÚ!¬ß=K}鵕‹7–1Tƒä°EÌÁµ÷ÐÁùšÄE¦2FˆàèoÓê#PßɵS˜Ïì!“Q¸šðYw÷¡…ìx£Ê1÷©qBAª=›¿òhÓ%äëaß¼ÈWE-Pƒ>Ÿ ÛÌB]1hÁtß) ”ÈûnHì¤U‘Š„.ÖÆˆ>ö§„‘_iå3v* ûIø‹øKOz¶•_e¤ºÖLìÓïóÛX5ƒU€Ñ®Fù¡È²?gxÉš)V2Äñ¶Ð#(ëê K’rê*W&Õr/ŽOŒAZ¾+‚ç^H2Úš(ïì‰ÊÕ$OŽ@µ«< ‚ËOÂÒ1ùЖÊLŒPW:¢!ÖÁ¼³²“'»Ø<…ºÂ`¡3]ƒúͨM‹—2ú¸4”NäZœn"ÿcw ©rCí`ø3¾ó‘†HÀkj„ˆõÇ&̾6ó3Y¢OYË;)yžîKƒè¨œº£´« ,£ù®,óÉ«m…ñ6 ÊCdO%á©Ø.CåºbÙƒ)Ûo¤6c© y$8»¢Œæ„ر^]xHC5CjTî Àñ7bÂL³žñJȬÓX„¢£8}¢;=/ÃÔØÕ‚6“å…XzdåÑÀ–(¨×@2lÊ;#Jù°´ ÁtÏoû "ƒåÚ„È«az2™åG0ËñuOH@ý°º£K¼%äž\I.ï¥`g7ÊżžzÝ5ƒIØ:R©®âB©ïvF®›Æ]@ ´ëJÈ\ ÔOEIº!¿ïxfèûÝ4 ¤>9$îù•ïé=Ó'Jß3–Œóï`D¼Až›] ¥‰£†â¨ì e/¬´ì$Œ‚û7íN×”¡™³A'å5“è×mGàxáø,|e¯¦eTÌ‘[(ײŽqýk.ü*¸÷•NXÝœ@'ÞO<ÇîÓõa—\D»CE¢WmÕ…â&B=èãï­œhžúÜ%4ˆzm` Ÿÿ¾3´P:­w³£ùx_ñ”CÔÕ÷C¬nr]üjQ¸~Y#,HŸO šùýw¹Xi¼âXÕÙ9Ó¹V?™Ïê^z_Ô¥+ý˜ùvÆ÷Å¡ûšh^Œp¾´Vñ|Á>*òwàÉåÊîar-¡ý–ÍéKÆ.®¹˜åï¿Îµ„…²nýYSÈ£¡™ÿ…9é(˜Å¥Q¾QôŠs¦Ð}Ó£½ß”£o.î¥a®Ù|ÊR^¶;„ÁC›õ†âlOôå(IÆï8k ù§¿ß‰®#3íwÿ<–#ïÍgü“Hï¾{Âzæÿ}»›j׳ü/¯öï­¼qZÝþŸ‚äÿÒ½9|µ°Mù[gÅÒÏdîèÞb kÒ#NÇ^zßN9áz/Ôøâ+ÃbÜöpœN>Óç6yØç±(çP»îj·6†û}Q-^µâ¿[0 ýJ.Éa/[OöË«@yWß³‹g~ß¶O ãÎgË]{wÄ Û{¥3*êï‹qŸ†8ßzD†ø£}+=ŽQƶ³DŸ®Aö œ²wñÃ@_å~ +T”u5x*G_îOÍËWÔû)xE´Ö 釄ôììº ‡| p $q¾ öéd\Y²pÝɧr†×~'SäžÃØ=´êáReª½`ÉTXç6Øû;ao¹~ÅË"ú¼4Ô u5æA Í„s°r¹ždoÓþ)4*j¯ˆ ¨ÍHS²Ì.i¢Ï§†V8Š®J6<}]ìZäH±G°ê1Ø},ã¬ãIÞF`ÊŽ0Q¨³·)"©wƒžk“rUÊ#d޽Ç0E2ÙŠ¡n `×óU†bÎÞ3ŒAécÔø¤GLÊ{Pº8ê(X;‰ÉZ,W ’ê.Éš®!±'aŠ;Ëè¬ {pÚF µ‰]IâUA“J¾³ô§§l SȬ,I÷ŒQã(’ß5¦,Ò¡—°, qGI´UÍ >IFØ ¥IˆP·JgO@Íd=ŠLm[¼R”J.ÀÜg”8Ê xÝ’GD@Ù‘ú6ì‹xà ŒMéþûÕ¯ê½s#ð÷àö;%=*×ÅA|Q—öB¢øåÚÊ ³biæÁûùžì¯ne.å 7ò5 '‡1dH½ž¨¬Dš´ä:›`L…mR…QõQj=yÕ2)‚AðITW†¨¹sÊ=ºiP¯‚LÑÎøl!…É4žêbC0É¥­ä k‡23â[¨O>Hj¥|™×L efÒ¤í¤¤·ÉìÂ&o³8É_¾…™CÚÅ›qwqßÉEìFs3'(/› ]æêOp+·k¥¹Y5SÌÁ~hNv|¦³'9Ü&mÈiÔPVrÇËU€¶ÌŽä‹E2öÓ^rè¹jè¿"‡Áuwá=ú¼ %Ã˵ȡo òu©Ð5DêyŸæô¦< ö•œÀÎX¯î)ØåZì£ï ýÖ“0ß>–Á^;ó¸r0´ò³…4µ^£SŠëêL)¬×Hg„}¼ï„è2ǵ;ÂK ?à§ ãi>R^_¸_¡Íø* áUÆ-fpaÞ»£¹J/é$…å¤wñS¢úüE.»xmú)¡ñOníG2ÊÏfȡ֑!W\¹o=&w‘÷ûMF8O¾/r%$ÂÞҙƟòû¦£…ÎüþÔÓ‚¯Î®Ë‚…Kèù4Ÿ·k£ïgƒ°ÞÕ%æäÚçB˜®ím½6ß>›°øå\ßåì¢{íäÜ÷{…­„ö<*Õ5’±Ò˨¶WºÇ €y—— ®>5Hòë¤6¾Öÿúj‡Ö*gþÉæç§:Vž¯;)$‚u-PÅâÊû*ðô~$sÕç«ûW‡Â4Vÿ1ÅéÊ\æË¡àËÚTŒ*\OG¼°!­Ñ ÇÀ¯8oƒyêýi‡ Eß®­6:ZÕ5Õz¶{1oÛ½}P1ïÅ\vz_é5•ä%kcÈGyÑó.¾"ò·ôƱ5p5te|õ{°–3‡t½§!àwž=PòÍçÏøò’`¿§§t¦ê#†;H„ë]¼Ö/~ˆ‘ç¶—Ê ?4&‡‰ét{X#È‘ö•ô‚¢²®ìF—yW€„¤è3…ìÒÜ sÀõÄWŠHg[yqžïLOq¶nƒBhŒ|ŒDæòl$ý4O÷o:vNÍÅ5Žo= ¨´è #ûz-ÕÎÕA¿ÊÙ…Í—§Cœ®€Œ«ú&j¡îF©ã» ‰¼bÐì3jë:Äèˬ˜‰O½Ù«„£ÿ  ’×5$ddæÑ‹ËÖøÁhð•8ïi¶‘R1—²ˆçÙE·%£G…TóÄ3ð¼ Wë•0¹ˆ¾\òež–+0`ª™G „:ÌÙÌq߉VVƒ¸+ç‚܇! Ä³r½‚¯Gýˆþõ²‘ v”À¥ÞDe•1PßÑ·„ÒÝBZšQ×6~ â»øX¼ µA°‰9ô'Aî‚û.ÖëŠÜ:“§ÞÉ~Ö‘¡5O -:( òÌGR,í!_WŒ³`@j‰¬GÌ[°MC“iܬtJ¬ÑŸšWÄ´‰MÊ&98O ióùãKã²+ã6È;šPjˆ±^‘Æ;A»…gFÖ´ŒÚb ˆChÔ¨ˆK±N „¥WAñÊRª€Pª*KE‘¯¨µ)l%Ø*Ä/“ë6‹6†ØÖÓyêŠó¢ƒtd(·©rZ‚eeB©™ãŒ,j•ivæY‘{²<“Ôä}˘w„€é1žC¾Fõè©„ÔKpAÝ)0çâÄÕ?óRAÎ÷„aFw=”b ñê §H-Œ™s9¸'ÔBwÔ± b°†íÓÆP‘ÚLÁ å0wg œbÖ ²‡#C@ß}O:j¥quDÂAº®èÖ ýj€“qßÂz£¶¥ï`{g2—¤™œdNPv¯ò ¨ŸîQ¤s]ðÌ”KaYN÷€w´Hs'0ß`½ dò6cúÒ#ÏÏâÜ|~¡¾Å=Í7•íßÇP]wrÏ®¾Œîœð›-|G,vÔ_gpòç6CâoiÅ‘q å†ÅEõý¾¼$>í•e†d¡ÜK’¿ÀkKHa3žH8N›S\9•y_¢RuóóäP0!Ì÷&ÊÐï­Na*Ì«ý0Ò ù÷—_êñºˆåæÛzÇ3Ÿ3òø¢Þ*`‹xÿγ D¿î·€½Y­ÕWÓO}/²JÛ§ßO ˆý½h: ”÷“Ž~r µ/´ö'?;ŸâDhÝÕiòýä±ó¹‚?‡ÓxÊO¾¶½ô0ÿÓZ:b†åúï‚W ‘q½¯ãQ =ŸxVìì×½CN¸Cûû(l æ~”ÎòmÏov%t ëb(nŒ1zó®Íäz¤úSÖ”Ð\óp­U0¾êû"_Q¿Ú+GÉ¡µÁ>¹êåýî¯bšÎyO _ 6Ÿ6nŽ ¢kï•Ü$ápý]^Z0¨÷¼9fÈwÇZÜÂzíê©âûº¥ä#²¶žùL {.ÌÕ˶¾/`£²«OÉÇúÓaCTì»@ÎX[ƒBþϵ™ÂÌ¡¶–Â>\¹:Ί՗gR(¡%ÌO‡ž±8îwáæÔA«ÅµDÉg¡_¾1íwó‘¸i6Àql=.õvög ÷SŒOûiFöâk!fWB|?é æÒHÝPœ¤õ+(qî §…܇í˳ÃÒ„ÍÇ\V N¬ŸGq ·ß[sñ!\êÖ)˜‡šA'KÀÞc0C»ŸÄ50ÐÚçd:ŠàÄùd_3ñÍUylW¡HøÒµo «zpi7ä…Eôþt,)WŸê¡ õh'TˆW éAòПêJTƒ¶êvЇ@Ÿù×*rŸüS„ØÅ–AËžÇÔPEèÐ1‚]ÁP÷ó¥—ø< GÇxõ’bZkC‹é`+ †üÛb+DÈ­Çò/3bZª#{$Ò…¯ÿŽrùdäŒÎ* âø5}/fưöQÑÂÔãéçÈy)–  G„|)3×;˨BA¯X&1aê*E8²Ìfífe®KuëéB¬ ƒô+…a(gÂr+ôaùiÄ¢;:b©bØ ÅÒJ˜Š'ôeÜÍVãRyL èÊ€"Cq^_íQOŒiµD÷€|UV¶–g‚W¨ò=8xížÖ6lX³Ô©HGÐ!P°pÖ§„à°¶èNòÝhýfÉ¢Ýãž"ÕfÄÔc`N‹´õHÌ|{[Àâ*2®ÌuªÔáì^F›]Y ƒ¯ cnÆäWÒ6 Ð[òuÆàHa›Å ôåô®¬Qnã:"'mƒÊSíJ’›œècÁÔ2zwN¢õIA@5ÄYC覊1Aœľ0º¤>Ïâ‰Ópo8òYÅ·»B$ê§µC ]¡xªH'»ï¢ SO'8*ßVbõèBcFŸÔ:h-ˆ™/å¹ìˆ¨‹öïD¬œïO?‰Û¹%5l8s£Ó<(ÿî༠ûO V|šÕ9ÅæhŽzwuM¶â:Øtæšo÷@Ïp«]Ÿâ#ôÆo ¢GwñZ†$r©›‚ÀB)=C¦*?y·SkÈßÐf‚賹ܳ îÕ‚¶n>…lák¿d †êF´ûÞ.¡Ïgm\þÉÈÏ-ŽËYg‡3…!´~oŸ(ÄsnñåÛ<´^=Cú±çbª®¼ß=tòt\w'ÊgEÝW=*PÅÙBÃz¦ïzªç}÷ú_¡¯ìÓ"Ï¿09ý±ûé/>ˆ~RÉA=>}¶ýD¯ k_(ù(h×;Ÿ[:Æï‡´øòßO jñm—“õ¨‡\Ÿz$_̧ȾmVóŒ|.ô“rh¤Uqö*øS{ÅdP[S¾þ¯ ] u_ÅEŽ÷Õ ¡çSZEÌ/>yOyeð|¬Ï@^ÚÔ®°ÔZ¨Ï£R]qÔ›þ™ˆÉÅ~ ·°XJÉ~pé~î2F U9¼ús‘µc`ùýÔP)ò·˜9뇅²W…~>S.d™úIuÆÿÄ%ÃÏ{PL¾œ6W|ehzÎk8Ë~9n#Â%_×4ž1¤Ù¯S™žÑΘ}<Óu[¸N¡PªúdNŽq¯Ò·‘/[ONÿäo…z6£ë·†ãky 2W=‹ŠµO“Ž ¤äº’Ò§I<Õq«³—†eWÏõU8î§Á2ás>=èÄØŸrDÁñ»¢ã³Þ#†Íj¡íä%cyÅ{'%ä{IÛ}¿z„„}ä4¡›+9#cž]M/š“ñ(+ûR}ÛûV^C‡–áãÈ*©ê¼Ê™bˆ”Ö6»9“¨Žq¾eÍBѬ|SŒóÌê(´2È+¾‡‡î3†òìªR·ˆÃý‰<²àYf±`AÎ.| b#vçø°ß0è»R›(¤­‹uBÂ4·Iì°OK— 8&5F»ß™‡ø´ ÚÐÌqt¦… î[F¸ºð ÁŸ2 s•pÄ{ W‡HµK(i ÂÂ&޵bžMòMäC{2u‚2‡Ø$@ªï¦½ {ªEl ¾£YP0Ífõb{€^4‘î¸c›aeçÝ[øKì.HªKéú—Hi,°VŒ‚ýµ'p|Zã:" ØHX'RºĮHðÎ6:c%yYm+×*¦¾ÏC€‚É®·:¤1Pº€=Y[g$ÑÙ•!OÒ9Œ…FñºÈ{Ð zOð„£qªÆDå2ÙƒpØ‹'{"iD}F†0*—]D¸lâÝB`ž™òSL ]B5@Ø‘jÏœ¶äU…Åîè­ ±­eDçƒß‰ú“¥/æÙ¿ª—SShk‰5ÝÀóJ'…Öp|*B]†élƒÆžà?„óOòµ`y1±'<dƒ¾«÷oƹèЋç~£F,@ë‰NCUWž*4¥_BtCà~r– ro•t–ˆyÄ•šKÏ¥^a%ï)Ål×<WÑš²”›×k)%¾S¼orI´S¹:æwäqe'`ÝË^Ô‘qw`°êê'Ÿž]ãx_üc å¥-˜Ü(ïßá bû‚ñ‚Ú#^<íÑ]À#ÿؾŠkhŒ«ó˜”žwr”è~ñÑÎô~gêG5ßWóŒ.CjzÆ#‘kOúæ¨ öï§YšÐ|æ)LÓµ1øUqFêcAb^ZcèðØ™Wr9ÆM}=ñ4W“ô;ù¢”¾ë~§Ca'»Þå%Èé›÷m`þbZ÷rÑs÷ëžBù˜,û*ÎÙ¹ÿ^5 Òë©!£Ä³\‡HИö¢“õOª ½¼صíEßZÏzuÀ,ÃÇÙ¾ÊÕ\ªô€Ýï„ÝG:kV§ã´¹¢ëÀXKJÆ|ŽÑ3tŒàÚ=‚Š×0îE/s|¿úB9Òß_é~>–léûR×ÊP›¸¨jêý˜/g&£|gµqÔß‹pø 0ß“qw¶¶R xö+Jríý‰²\zïü*Ìúšÿv€í€ÞÄUyÕ1YêY_縢kÀæßï-’ð kÆ-¹À;xùÿƒ1ìˆAù'ßëäîÊ!¹§.ZØ«\¾Î†‘õ¾²éÐkÁ+†bØ;zƒèâj,@­úJ™Óa«‡³¸ŽXsØÉ¥§ìÃ8ù½ÛkΧ®Žr… öû®¾0˜¯Ÿ¼¹¼ïvdÂLýª5DÖuå°MÒ™k Ôà ¸?å§©Õ0ZJg#™K%¨aý.M J°9. ãš>諞ñ½ÅurεAÛ‘=•–`r²³ú¢æ*¦}å0ˆÈå=½–`g~òÂGõœX¸uÃ~Šâ—RÚ]´¡ê=…‘C¾îŸÀÈ}oÈçQÚÉ$ûo9ZD;tt¦FèpvpžÆ»ÈŒ,¨wæ¶#pÕû¢ÂA'ùØ ‰b‘xE¢ w„2‚ö‚º Ú• 愵ïêOW¡~±'.ôŽ€cß1²Âq'"ŠËhlf£ÞC˜ l'Ù!øÞ1>-8´§j«„Η¶E(ÖÆ@ØJà©Pmö52b@ ©Û 1ì¬ëmz®>þÝÔ5¢>²ªâûR’PI{ÑÓ{ ÖHÑ·…öÎc^w |'w‚mIýíDQQïìÉ•áS7ﻑՄ‚­úô”€*ÃÙªŒRòéÎW²>å'8å3®ìQ¸sìU]Òf åƒ:FÄH£é¸J`åI2—¢†Z%÷êÂìC¥p‘ЮÙ Ü*q%i|ò@^_ S|®‚ç¯äb/üR2¶=„kP¤þTК+Ÿ›=ÃGmTyUmÓ™%b}à­$g>Vè/ï,do«ÓOòZ¨¯A¬áƸVƒF9‡õÛ^X`žƒƒú”\Ý¥ý³,4JúÒ0K_Ñ%ƒ¾oÐñ›F—\K0w"ªï'þD×j.Ö´°Î] úÌPK9Øl²ßÑe¬ÒÈ.3\j{Rˆ>¢Üw}™r?µO>í;Ô«*¶‹wê†ñå{/ÀùÌÁÖG¦Òܬ°Â¢ü¾«Är”÷mÌGöñy·_y@éú=¼Î•ŽFÇ\“RÇdýnŸ½*¬ßåÉ|:×=óÙ|N0z<Èhþ—~ßÑ%LBûZ!–P\›=Aõ™Ý˜TeB[3„ͤçxˆé|éµð\.1ÎÝ'ò½úiÈ×S^ÁËvýêäô5=wþ6¥úû¦s•iÿ.o¤3Ìu%¯ªé¹ªWÊë[ZßÂD^#ûŒÀÿ¥w;/=2ã¾qôêõóƒ ˜¼òûÆ8°îa“Ê‘W ©úyês›ë§%È3d§ñ¹ÅßNæß7YÑéê¦gÂýÞœS0Çuè‘N<üueèùLgÙ»ðöŒÐŸìJÄúc«ª¾FÞ¿ ²:þÓzÕ\wu‘}:˺3v//7–½¢P†z–öÊ€û·ù"Aþ³69ô£Ígú]ÈŽt-ÍUŠ÷] šfÚŸOÔå'éõîØS¥ç^„é¨d×Ï|ü ÚšéUL}r[Ô¶™è‰9bÉ[Æ*uu†íCÀý·ž¹z=±_™ây–ž0THWG\ÿŸ 8AŒG¨×LW*H~ã>!eõÌþÿ9k¦•|0Ãäãf¿*„yÖïÜ@n]°‹æš]4Ê”zÜ Hó)ad.PöR,ŽóhƒO/~FÀ1@ÿ4ZÑåUк#ã3°+eŸvjTÛÌ¡²CŸEºƒŽ•üŽï<¦ØÆ ¼~Z85FH{Z;l—¼ß‘6“ºò<ó˧þ[†T<ŸÅ¼Lä­XzN*kaHÈHóoÑš(—"åXÕЦ äÝÕ&±¿Ó›iuâPŸŠ2¢äOæU1Yž•eEVÉ“©Zð/h1ÈbÎCiDOh#sÆlã]±fðžVAªmÃýÎ"ï‚ùM9„Æ(^šÝö‰è}{Lf„l+OŠÊ?³Äœ¥LQ²s˜[V¦| ÷GuLŸ“ÕÕbï˜ðN+¥ßªL©rHíKºÞÈÒ˜ÏBTê y*›Õw”ÑÑyìú¯ùœAæd'aÌÝI:Zž£bU(ïHj¹cÛUˆù4)?¢”¿)?ËÈl§C¸)_Уó‚5ZŸ iz\ y*÷]=‘&’]%îhÏ[½uO»2L ià·óe¢®x;áNÐ sÊçLÓO¢v¢cš ãÆ1n‹çaX ÄÝLE–ñþÉ’xn.»2ý’O=Q±ÞAFd‘/Çß"XŸÄÒù9ñß³ŒÏ`#9PF%Ì—2µ&—UäóΚ}a æÊ£"tþDj­†„ñ[Û°ð0=ÿíwJuS[%`sC[ö‡0–+µŠTñ0öI"J éT@ MtŒès ûÝH+o–5ée!¶ [  w :W¾’˜\i`ƒdŽÈ‰úÀöû0FÚhkçïl½Qß3€ø0õtgYÍåÝH“.µ Ú­)اBhPÎäï µÒ׺ltòÃ7”¿ÿÎ;Šl(k .·ß¿+D‰ãÎyªK^/??íN––ßg+6œÆïÄPiþº#Âõ;®.\`íC.ßíýw†ÊÖBYÅQüÍ{å;‡ ðþ»èê­S¯ì­¸:ŽHõ‹ò{©õªï‡9ºr…<ó?z§|Ïß‚ÜÉåQK¨AŒú©N lÇëw\k c pùý‰W ¤:?Ç£ñâùžæí»Å{~˜âñVšúM®òL2~É=ßåk˜Ë5ŒŸC¾º!òünèœ?3à¸â%ïw§©ž ¦Žwrl¿'NÑüOþì ïÐn>Ÿ…5ûþóf*ßâyt"õsM²Ië–ç)aŠé?ù]n°;ßÔΦʽ¹~zÐN hýÖk©(õ³Q3~@Z7ŸÁúŽ(¾Ê%ïGá±b¡×$†óïO…XBžñ[s(W>ƒÃqYýú4— ”?i=Õ%hâço¿b¤ãe/ð›FÒ}*´‚ù®çîŽ=„Ý3îÎ_õNˆóÉødÄKÏQ]¨N?¿wòåÓ½ß$VÃŒH8fG› kO.'®kZs…üì䆨…ú<§·Íaa³e(? ú¾æÑè{!†»¯zkÃáË¿ÿí4( œŸ8C¦4wÁFáýRqzñþ”ÐnB_?ùnKÈ{Šo^÷ŒÎ­¼N Æïðµ¢^Ø—òr ØOºzçêS+H¿Ä cåW4é´~>‰æÍÚHnfÈöìÞ8~¾0>Ê› ã¨êO&Á¶Êlͨ;²qúÙVy°Ö¢MeÆòn¨=f÷Êò”­Je µa:R2Ê]!MÏ#tС¤Q4çàŽÉ¼ÊI¸ÞZ$­eñ§°sie(ËØ‘Ž*sîæ}Ñ^JXâx r ÁqͤC²Éü).ÆÀ¨½!mAÄ´ÌìÅÁj KEâúí‰2¤wç8PPÖÛp$äGÉ·FJËp²ŸñKâÊ$1Ò5’¶.õH ±iºŽ òXÌŸª1YC¨Sëh2±ÕŸ”ÖJbé Š+3s| ë`F~/H‡¼Jz&2Q+œ#b숳“ˆÏUóRŠ)ÿTSeСB!®ÆæØj’º"IíŸÉäy5ÎGÉCjģЄð,mEô6‰{r7Ú( ŸD&q@•MìéÖŸ‚@ã~7b”S¹>ÊBuk‰ÂMÏÐècXl³ä;Å—·b¼›‡¾òe^ëÝÿwç«ýüdŸ‘£oS hs…jó󌀅v°µ¿ž³A³´?ë¿GHWMü÷¿óul¼´K™f¾®ûH0œ9÷ü» qh¯¼žú-÷œ>jHWû<Â~&(ë:NÄzÄßóK««Ï¬n0žïŠ/ù?]zÙæo°úñL‚ì:`ßãÔÎïO²~UŠÿþ›_9P…þ;½® ®]¾#XÃçý1ûÖ‘^æS½J¬ñª@û“ü$IXŸ#$¯…qöZÂøš?Ýs¼‹Ï¤W ª¸ç`M_\½¹ð~OØ‹{¨¿Ÿ:’Ç9wˆQF¨³³O/Z?ã‘áòÚÆoìˆg'ߌ»O³sˆÎ ¬¿ w–ÊÏo’å:Áø¾å»ìÓ_ÌŽÎ;….!‚¶Æ:¡ Œ®×6Š®žâä„2§„*ª¯ößZœ]w9‡Z‚±Ø~±ç¾kxT3¤½9ìî£.‡h¯öžÀÙÏ ×;Þ-Xòy×V_Þ;ºÉʾ‡´@¼ò®áZ`|Õ98¥Pa¼·]ÍGò_%Ð"[’rÿ ~o.Ž¡¼X‚<Ÿz‘tS-€+0âøn™Òç0/¯ÆÎnfI!ÍÆéÃIâùTß3‹§sÞ·!·qÖhÜŸ†åñ ¬x cu:+§âêá„IÛYZ6¨Ç2"=QÙ•!W:džçŠzXÄ¥1I+E¬ŸO+%Ãñ“}n¡A¨ÓèQag»†Ú®LéÙŒ+8Ïç‰8úŽ÷fè˜Äç'Qo(}*l‹ÚTz[ÈŸ¥_“C©ÈžÆeªF++ÉBw¢ö1@ùïoO³`:¬Lým¼º ⌞›¨Q>‘WA™ÅÆ£ p”Ɉº@žŒ€}‚~Š%M£`>€$½#á4ˆÖ¸Ixý$YU‰ÚŒ! fäÚX+Šm“¯CräÞ<Ï,ùÛo#I{ZÜ#¥·†T ÉÖ$˜*&ñÉéY(ˆÙÞ“¦y/òŽö${«Ò­ŸRWàxjÐá)Åñ·ÄÝä« æÎiޤ„Oã¼ 'N3ÔŸá}²u¾Šî`øn<ÿm¤T7Ú™püXÈ]ȸ ”Ù•>‰öS¤\!w TÆC˜iª³‘d^Ľ+IH…ê£"NÏOÑž|[ÅÃh+a ,З!±=¬£ ¶‚õ=P¢ҵͱKëÒ¨âìöÖvrÊ–&Iæ*Ÿ!ý±˜sà9…=ÝË»äØ@O`ç+1¦¯6óy盩ÍPßo£Ñ|v‹ÚçQ­Ð÷Ù}¡”ïþ¿?Lß*}5®”²_?PïM4&åÊ{Ç0(ï&NCÔ«ŒÖh“Ì£wò¹ñx:3‡tŒè2äB¹fÒ”ª{˜OÙÕŸá5Ëò¶+x¥ï±³·¨H[É_å*o»,Bòg‚†°~{àå÷Û\Æ'Ó:Õ‘hc[¡‡•tÏîH¬AùÝð²W7;]2\_•¹ú.´¾Â8 ©\Ùó~—+c*níâeÐcéó[Ü„<`ý3=ªç¨o«ï¿sÂã°Ï¦D¹KíÁ´Ï[ý ½Ü­ 1»ãÍÏvÿS]2×Ï_ÿØù”»b‹aýNÐÕÙ85¤Ð ž¿Ë§è*ôgj(®žg¹œp…þ{èØæi/"o=#ÜùU”úˆÿ’r×5ÈWêûíB…ñó‰4ÏöG)dèïwÄ =ðÏgB—^xÞJãN×3AœŒ«Ÿw¢/|U$Åþ´éR°õt^¢¼ÿ]>¶«¾ôç7‡zkÄó»|w|å÷;¹9†þé.ÖP¼®O¹Ò 泃UZÈ}ÛP£ï?+dû&oçSpRçðy§KŒÔ½-l(ƶï\0}§ßMx<#µ9|äÐo] h;Þka°—ô®aöaŽøO2¬^û‰Ð¡x??Í é”†.»ôý™¾¤Ôïõ÷G¡¸ Üjº«äu÷lÐ<­e÷VÐWšSlAóa~U/ýë²W~ºÀ(Å¥Jêóç§Èì?%$¹,´Ïdú¨a(Ï€Z(ÝyÍ—3¶§Wu6†`½h|¯Œ¬f™2à|F¨BÅI),›bmç—™´•uŠŽöÖoEΰÿ]È#ðíò`7¢gZª7]òþ;ádQ—ç4.oƒ'ÅìÓÏ ´ €ŽFWaµÐžñ8ñ¶÷—Õ÷ð1À˜*GD¸îÚb{KK#†6ŵäÓ5¶õž cˆ§“n¥@¥%=K °²M‘\ZÌ+BÎd+Aˆ+SÍ,`ŸR _—d㑉<Öñ1Ej§†ž¯x†Øh'Ó,¬b£“Í$ë1ê‚qG¬ÈsŸIŸjxG§*éÜFË/l û(ǹ"œ,Ø3BÜd"㤰LrlŸL}‘=ñŒf’Zá¶¾ì1-fd¡Ó!m ËdÛC4Ê*T{ $RHW% ütÛ§ bÚ({20ïÂeDU)›±ämwzÐÛ X,bVÇ[¼L‹?5b æ@=ˆŽÌyW­¸V ˆÝB~—œ)í¬{RPùÚŽÊ:L«rþ$nSƵP?•Mu õ¥,˜sà™ÐŒWMcGÝâOe‰ùd'¦¾4þŽI6ëÚ ¤³K>•5~ùá›…¶(ÊÁô÷c\ݨñ<(È[uNÞ¨ ½)èÊg+ 4„uÌGÓ‚ö9L…'áyg4‘òÈÎå0ðn?1D’rk¯ÁÅ?ï¸Zˆ¤5¤µ8ðÝJ3g ï}4„ç©W¸$»Ø²ÇB?ê3\¦˜]Ÿâš½ëšb¨òÏÓiQíØŸò¼âÍë$7oßýLêóÅûÓiP•ký»^žïø­EßÑeuí¼CŒ¯æ´íüÇ®ÿ¤g‘EÈÐv#ØÎ÷YÐó^qŸvwåÏOw9†ìúo»ïί¶[%|Ù?pñ9ÙÏ(ÅSÛ*S;òz2êûœxC_%úö^l=tÆvJØjêjžª‹N×ÌöCR ­â¹„Âe”®µ;¦îŠä9åZ`1ÌÏ!­”ÁÆJ×ÂZ ŸJ ݧ¿ÿ­0P{oÎ*äÀ½Á=Iç3Ué^ç4}{#_G¹ov¹7º*µÈsÅï˜Qÿшš«êËO¹k¡FÚ§Ñ€ˆ´ß-ìnýnïwÖÇGú$? š«Ïa?ncì_Ž{ײ??⛈áø/šæJ2r±zã<ƒ'ëa¤[O÷˜±‚=O ‹=`^…J…ì}8LÀ²:Yr…¶‹Bðú,ií…”öŽ<5)¯¿btÎéÙŒ¨r}¦¶¦…ÓBƒÑAÝE²Á4fä­êýú¯˜À8Žò 졆j@\;r÷>?ø5È­Ï!80®U¨(Êm«KZ¬lç§À™9ÿ-äHãÃ0 è¬@_L«™Šì$sy$Z Ò'“ZþÍ2±ã½GÂåIP¦F£ÖœŸ =䥡¹Åº¨’uÖ3ýX ÚQDÊG|™[ òQ‚–¥VFæ9´}8€§¡²¨ÙnW‹àë;RoàF#LHí]uTB’}~ôöÜç§’팹J5îÝ0Ȫ`À»´‚Ì‚€6²Ô͆gàÝ„@{”þHl+êoqôÔrÞ-BøJl<º/g(3t²g3%iMž+°âìÓBÔ•ïñÓ—Å9øEP›ÖV)~D?¿êGvydI† x Ñ—Èû'ßžãD[)âÈÁFÞ‡BÖ2³Ý¥PþmhÌõ ð•|{²C †úykŸM×»yì ½@ˆ:£¾ÿµÀ>O A`¤žƒJ}B:;’„Á¡- è㢶aÄ“©Ni¸ø a£I:grFZ¹îâ½àÊÒ–~Pû’.gű»Ü”í@Y3óÄ–ÂüÔW X˜ÎbWC®ôJLÜ¿eìäìÊâç3!g,ÜW…ï‚»rŸÙ S»coò­È{TˆÝÙ^xGšìS*<-õ޾øJ¾¶xg£ì¬%¤ ›üúí¾&-¾î)Aîäï<Ó·x(0ÿ}3=”Pß¿í2Ôvëè#OÑç]®"i„Ô»²¾ªû·…Ì1ßã|Ìsè>ÌG_KsÇý)¬ôêAæÌÐ ¦oÛ‡_êµ–¯ù^YÞXú,ØœþüÝ^ ªOû$Ÿ|Ä+íîsÁêÊ\ÑÙUŸŸúrΧ«Œ!w¾jÄþ¡šËøœ%/ùS0ôÙ_Å\rówá^ƒð<Ó'å ýÙäâáûo¿“Ysm-%L¢ÑShÀêÙfK°Õ’ú’’Iú•¶™.uB™ñæràÞíªLzÿýUTW0ž§]•Ê€²¦çvµ+?£úLcÜóL@ýÓ°üü»ý„¿u,@¹èçÜÿ½Éwn‡óürÕ¥àϩΌê+>N0‘õY.gR7ÖŠ®ùL8Wq½Jþ“VG?|öwÝÝwƒ|Ç=À—W^¿5 ö-{Q¨Xú3`(¦?2:ñ¼³×3ª+„ùæ}„RHÀç·á47ŸÃÔý ª+¿ r Ï'Þ:BÝ¿ëJ Ñ·w÷Ò^ñ‚õw†úòÖš.¤;þ¹Ë0ÿ¨Å0ß$é[]|ÿÔïä)\ãs¤ î.ÿ}'Ì9”±Q+¥[ÆS^æ-ü)»SÑÿÑÎ$×søâ[f#n®©w-R°®.ÔCfùnžï¸ºx™Ä³ì• ùŠ£yÜN|¨Û®Hh.͆ԃ"•¦W+ÂÐfö4ØÍɯ¢bXö.h×OóÓ˜_yOÙ> « Òù] ó6÷LòÞ1Íèl¢l§R'¬Ç¾ãFËBSò—íb…ã^J ¾´F¯Ñ‹Ç¾ –Qû©²&Òm-Aè@ˆm™ÓLvéÈ>L0teuÉê¢O»ÓWLÊêmdJ‹(@{›´ÄxÄP~€RO8à gY;p;îÝûl$Ì ù w<¶áŒAfk!®]´ R°Ó0vô7´•Ò΂!¾§Ô·™`]&3:ÆkDlCÒŠÞsù-ÚºD‘X š@€¸jÐÉñj‘Έ}xä“ 9¿+ÖÐìÈ œöJg Ú ê!QÖ’e–ŽŠ¶‘BÐD>›GsŠTfixX5|u£ÚóÎ@B]¹N Èm‹ÔÈ–u¦^X½Ž€{ªeÊc‚÷>à§'jbëIA¤-K; ^HsOô=ÂM¹b¨'ŠrŸ’ži’Ê;†r”8 MiôC 6i±å©ÑÈ ÓÊÁaœ ­32´âdkP•E<—‚†’ ?H­!Žmüœ§:ÚÉfe„0 Hošë£+ bôÇ9Zœ·9ð=úÔƒc-_ù|R0ÐæÓzwKϻ݊uã>‡#XW¼Õ[‡ò3Å/ÀÚ š”æÓ*ÀY¦×÷§ùxYvmFtmŠKÁÔÏ3@LŸÞOñêk£½šÇ¤#èÜé[ &_?õä†ã÷ßâ3µ¦û·ßLíÆÒ ÔGºÛY7,§ÏCKÔ?ݱru:;ÜŠéÚÝ‘è¸yýïÜØ „d|Ç5å6ÝÓàr/5Üâ \ú2Ó†iWï#n’÷×]Jò”¿+¤ç¤«``GóQ-®ÜtþŽ;¼J¿Ëž¨ Ž ©D_oŽwîÐÂÄò>öO†h¾xq¾k¹³Ë>ëkôDïvÙç‘kQM¡¦¾Þ:¦~‹/&ßCjÅr¥g„WuU_qÖ[Äß>?%l°àúÎ^˳2¤É÷§_¦úã}ÌwlÊ{//ääe¥©¯0Éw»Ì¤ÜÖkðõO5('ÞŠ`~^é;Ž‘þ'2Ø«œîìÒæ®Iò«<ÕÃWƒ†ª®­.¹¹ædM¹ ˆ¸\³×ìן|oæûßæÈ\¹0÷âF¹ó(Nã·¾xœô݃À]笾\2VÁá”}Ã¥ òsô²;²Ë§†’B¼ÆYæ†Ì㧆h_öþÑ«ßÑý‰½ù} ý<w¨î»?õ;EnwšÇ\ùÎÂço #i¿êï!ŸC ØJº €ºúy· ï§GFý“vwu´ÎEX¿Û3ƒÓ;†|º¹ÆZ^±¦ê+ùø>Ì}Añz¶„F½ai)ôþ@Gܨâòlwê!©Uà`ܧÜ1‡èÚê—G iw0¹)´½¢Ïžœ¯}z1NdoƒÕx:ÖøOü@,1aQ§Ôÿþ(>ÞR/>ED—Vqw¼¡½ŸÓUÞ=P¹yíZ”âtO¶ s_éêIìÊÏ"^>‹ŒS|7dßÞƒócÐçSîä/€úL°›Ï§Â5å²Ñ)öîOü–Ë3µÞHóÅôçýUNq±‚büûáz‰ÖŸÎµ‘PÙK°)Þ"¡KÏN6 €K7¨…"èšL[nY{áxco¬K%`_Š»“`üùäø ea$—NCj(>”a¼;3ÆÖ•›gçÊæÐÕ…WÞdèˆZ»òŠ(PZ%*¯SC32Ì?#ÈBm]¡˜¨¶SѨQž1¾“'õåùÉ(!vH»&¬ŒíIAÑâ]N%Tnó¡ÿHˆÕ癑“tâZõæ  ldð&s_… Õm•ŠƒuL»˜ÃX9HÒ7ã<j(ËèšÓ½õÒÐâ«ün…ÀÖ÷I]JøÕ œ­.ûôù›BñÁñó–«8¥ôy’‹앟îäZ€^âK¦ÿäŸ@s`ÿ¶;s>.Õ\ iìâ+iség…[¨î£QFÍ.ÏÐî!v>ÕÉÅÅ•5P›œ««ÜÄÂü9Ìů¥àwœïþ(åæÿ@Íx(-ôUÑ5)¾?Ñõ[2´Q±[,óØK]ÊÒzñ,nÜùÌ' kÇgÊ`Ï1¨P4Ì•½e)/ív¿ZèzµŸA%òt–‹|r tÏÏCaCuøù·¿Š"ÿGúc.]ŠÚs¾zpùª½ —°æŠZŒÍå5|Hÿ)”žÿDô*k8—^éÅcd7ÙŠ«ï¼Þ-èìúŸŒ–|Ý)Âr¶WréŽ òÓ¯±ÜºÞå’Äg$GŠ·ç§øåsñµÇ—G_}ýœè¦æÛ{BªÐ<•Õ¼…–`=‡J¾ò…ëï€I•¯²*ÝýJcÅWü6ô½-ˆ†‹cF,ÿD±Ÿ]ÿ`¸êe ÇÂ|ºg¸¿D ÒòÝÑ÷1ÊÎ0Íb÷»ÍŽXÂ$ìKîlAÛƒt <þÉÞÁ•Ï@Œ.+¹Å¡ï Rn½`~²{«Â?u¦`öÊ>Ÿ¡aSÊÞZÉXo'…7†ÑkˆéÅÞæN0½P˜§:+4ÆV×Bâ+­éRrå¶}";'Ù§Ýš¤ûÔf†ÝÜÝ÷†M×{`x ÒÝN¿,’ù4·†ƒÓxïè³Pý¶³•F­êL}ǧ{W1"¯¯POî!:èSè]D Ÿ'Y‚¡<…àÇçÑÔ½€}~ŒNTãögí’š +…ñt.õŽ`ûD˜jBµ›OÕ ¤Y'$½âi\«g§µi(@í^©aÂ8…¡örÖ›Ð!ò¡­JÅD¶†`ütœC*å¿?Y$Ñ}º ñ¦Ù#P}&'Âêål¦…i>)ôbò9Qê-û²Ð" Ï­“·‚´ž )j(%‘|‘< ‘ÒÊ+°Äõdݶßê;EMkXÞ%²ç–t,‰†ý}ä˜Þ•Jô:Šäm)"ÏÄ})¡¬)q0!ä¥T 1òžÈÛ„¥Å”IˆjA€òc4;J«€ æþš•i6Š+*Ûzg¨•Pyw)Ç¢HÛjï¥bñ=9E„t"ŽJ<2Æi†¡5+Cz7Γ˜¥oÁ5Èé©;l-`2p^Vck…ûVš òűV¨kDBÝ1¯©ŽîT©þtÖ˜?ß[ƒJ/AGET݆ó‘Û8ößâS¡Ü³ù3!ä@ÓY‹ƒº¡íä€â ܇Æž©ÎÂÂéÍÒ+\g¦ü4Š9 -»¸ q$îK%IÜDïܬ+Ï¥—ÇX@ÞS•ÃΘ‡ ±ì NxŽ=ŠrÙŽVaù$l'yïëåÈ›©ñ‰%An€ÂTÙ'ÜÁi…x "듹ms‘Òürd.…³c;€Ù%çmW“žéü¤[ä.¡Î‘¡øœ)õE’Ó uÃ싺Ô*@ zC¼%ø¾‡#áI2'¼Ì% ë“’¶`{â]`¥Ðÿ-·2ÆW>ÝÆ'ò9Ù³ å*­ÒMn)Ÿ§†Döðèn¹suÚ]8½1ŸMÎî…WšÅ‹ãêÆþ$þ,å9õ¢Ðh?¥ÃBœ']ÙR¼ÇT'%,ƺâM!æP×QP÷¦ô*ë€9ô c~¥˜nV\>Ï©¯Š…Újˆæ¶çI®bOXG¹˜}½u½Ó]¹ î½1KèWú9äG(ángCbßÝè\º[xÍ¿ÃÕìÊgRè>{˜k\‘±†¸V¸§ë$ÏnwV­Wþ;<”ï 0vw ¼¹8 iõvãïãÔqssOïÚƒì÷ 1pyñìˆÑgб†7¬ãÎm3hÞž“_É¥Öï X|Æ|z üW<ÿ÷äWtåÙÅUŠ‘žnŠ·yÚ¿å[Ñ ÛnõëŽÿ!ÀçthòŸ#.¾†uFÆüŸü9øJÁÇèwÎ]ÿ,¥• Ÿ|'½ós$”«0ôŸ‰|¼çg˜!Ìß•!^¹6æq ±æ]Lì®g f—<®÷öC´ùÜ“sŠ—>6ÊÓåÚ@†7­ïˆ¬¡ÏtSÁuÓüÝRÂx&qrú«Ã®JŒþ¬.1~Û^O¹ ¹Ú;XyÙÊŒþpïwÚƒSòÒÑäŽ|¸Úéwj·^éœÂ‹‹áW ©FäÆ2Vò5Ýyn… ðú$4Œ3ˆÖ-õT˜E‹ÓÖÑçWFì•þ´Œð‡Ož¨@¹W‘õγè¡Q}&I~ü»‰+%'kÅ0•ØåOǼ1í]C ¢ÿpëœU”ý)8$&¬½rî.y­5ùÃáì‰V.þç»… ¡ ¾Õ®taë‘;&uíi!VàK[å{”Õ¼5ÛÎ$?(’«-úR| œúî…¡½Ë³×Pv·¯S©j`´]0M0Š«”’"æRc}kUé»êJ`Âs°-‰}_è‚U)Vÿºeœ +tÒ iGªÂÈÌv RM=ÏA¶#¡³œTbâ6ß‘(ØÉR ‘Ã>àÕ¢*ÚN'⹘ß*†:"”ŽLq4±M ñm‡øóVYˆòÃ.2Ô¹X]„9r^3ê&Fˆ…¡$0w'd&¥gÌêÙñl ÜŽÆ;iOøµr€`;éÌÄÈ#ZïB€ã-ÖjЦïÄóXP«“e7a‰]1÷ˆ i¬ÊR™æO ¥»Pë`oQdŸÀïè<ÈV©9â’sAìIÜ:ÅRœÈ:Kö° Ô'ú@i¶N!AíHE‰ÅšÄY’¬¥å±@¢ âçQ²Ø³´·@úMÒš C­ÖŽRÚµìMpTŠÍ }4ö*lÒÄf‚^'Àìþ"*&û#+¥/¥Š¾~ºWÐ|ç”Ð  u5GÜÆSP, M{GgÏ™<š_ëÉ!aJwÜ5`¢ä`lzQ(Æ“.'|D??ä»×xëêÂÕ9Ž®.»Ü¨ýˆL xL ñ®5ä=½ÛÀóhÚ²¬Gƒ6GcÊÍ02Ô’‘B8÷IÁpZ'‚™-kÿŸ ø0pÇØÑÜNK$€gá=I©g~þñ\Õš’Œàê_5`i9iUÈCVW>K ñÚ”“Bù4"Œc Ö\êô/aŠg©M±BóÚlmƒ0¼;sÊñ‡øc­b]”mÃéÿÓ«~'ø´ÎNƒS‚¶Ç —“Úä7œ\©Ù ¿Ú>O²Å©¸Þ;úDÃúÖÃK]ô6âb´Û…5ùì’½‹%ZõØ-­Íï M^q'ªÛuº\[º¯¼m˜w:ÓéÉÕ«ƒLïö7‰†Qöw[¯àqÞS!è¹óÛ¶w®MvÍÚ}×wœMÞ‹L>ËlåˆÌÙÕk)—³ Î;ˆ>ž¥· ?ñàýQæpNŽôŠŸíí”ݸdd->‹aÅÙçI•ê;}®èÄ`k/ØËû›bS€6«ÔdÓoÚCB%Êõ[*¥âuEÓAÅå§Aò.šrÂ?ü.JûêèhÆ÷)G;3¹y5ÔßÇLôüõ_(ü¦ù„#œ•°Õ`Ї„åúø³1•™h˜¼;q?Šs}ãAš™»)=»¼|=ËhBÞdµãQÓ+µâ¸¾ó)Ï-¿Cû1þZØ5@{Îkr®6ZžK!SD³Ÿj}8’ÑëŽ Y“{ÁèMý|ÄMgë¿¡PzÓèLC3œå©ÔÂŽøýD¾-³Ž!gò.¸¾c;Ч¾¤ÀùŸt]‘š4ùʧgŒ‡>‡l=È}g›ÕÄûò~žŠÔ:E@þ‰s ¤£O…á%™º7ÓÄäx]ÅD'Í¥^H*è›æô.:”£íbwÅÊz6Éå7¶FÚlüçßrdsº—\“|==Ä5r÷&—SœÓCU?®p¦x(ä{y?‰¬É3ØÚH-×F¸HÇÕ f)Ïâ`f]ߌ%8q}f K’R{*Žî ÇÞU¶kSË”=ûCžÒÑ;VV|´éº‚ßHæ§ÚQŒ•ãvâ¨ïD]ÐÛЊæù ¹+vqìÂÊV7©Ãº"] B­ ÅÒû›±0²‘Áç+Ò R¯‚yXï°o=“aÌr†‰ŒÒš;G`¦4¦å'^ "¾߆ړZóéf"ðOõ{hUcóÎbÙÂ-£xÜÓ=ØòxdD£JÞÁ#ÄÆ:šR/’FòˆåÚ"!ÓŒš*¹8¯ìˆxDË-2sÝÈ=‡(a&Ìw òí¡GdƧ@¾Ä:¨›dÖ”„{ŸÉÆ)¸Ôº1V‰AÚ PBC3`ÛÌH© Ë‚èÂUu=žDêJñ‰ŽDooãg1·»":ê^ÖFKqŠ3G¡—±'ðµ bœFFCh$ÿUð"Ã¥µ3#†úñ ƒä¾È&½2«eŸªó½ %òȧøÜka\bÓL€Îw «  i ÄÉaVt;R[Þ‘+ÒÕÁx"´o¡\œþ·Á ‡s3mKҮθ£8š[>ãDWªë7øë¢7ÒÞï†ÄfçÞhsve“vŸÆLX8%wA]HµGÌT¢ •M(a`zaàÕå'š¼þâ{ ì;¾yš6fävTÃ) Ë¦1ø,Ðë(.%Ÿ¿äT÷ov”Þam¶‰‹£1‹‹Ž‹ ³X—¹Z^»A²˜L­Aìå`+d$=Ã*À™:†9ó d—f=\² Ó*JSƒ?ÓßèE2ŸjüÉþŒ=8V[Þ¦=åS*]ϲ’žéùTMɇïÅXÆìâZÁzɵ¹D&ä½ý;Úžl¿ªA²ól üRõÏ·¸¨Ù¼vþYÁV²ÁÆg¡§?éó_³‘´™Þ–¼øLƵ{™â%œíÞ„íHàRÆWÖW^ ãu$ÇcÆwBÒ³\‹9™å0ÿRËÞ¬«Ë«9ˆ­š>šþïæÐp[ßrø oŸÎù¹ÀÉY!ìAG±ÞŸµ6`~M ¹ÕÓŸˆ¦î >Ÿþ×L~›¾ú‰bë+®]iZž=›”aX¾.x`çÚgؘ©Ÿm%wt(^ž»Ì6¸ö}ô(¶óQöÍ`º~M¶ÕˆÃÚÓ?Äçϰ¹WµY^íjVëQÆÎPÀ—ÿÅ=3 s&3‚ˆé­Øƒ #ÒoM.Ýe¸þvµx¸ÈÇ£_ÝR<‹‘Þ£ÛâÕ¤Õ‘”#ÞË¿±Òõí$b«ÍkDÛ ÁY×pš!ÜfÁâ”m bæqPÍh›ótj.e'•M1žL½ý齇䑰ƒGWz‰y;í#@±ÉÛ<*²@ZŸJr:3Q±~ï€càÔ2'uÕÊ5ÉE^úì…:ÐÌ‹à˜E€ülÅ`gvå¿^Ó-cr`f¢vç7XýHlm€)6Ö|²ÃF±6±bg sh!{çi §BZ(Ìè€í 7=#ùzroÎ&]̽ÑËcØ>wðålïò¸uÜK8Ù6èüé«‹{{ç`8èÏÏXC¤rèšÊÝÔ„ój@è‚ ý\òÔ>³ºÇʼôÝMTjmƒˆ¿0ï;™tö€ã& -gÜOuÛcëùŒä¤ÙÀd;…îïtQ¨S¡ºAr­°¸>:A=øüN¤mÄ·³í«ù³Œ§Áœíüïö1Û|ú}—#¹\mù,ÉHmþ•¹%3ži¤þœšBŸÅ•=½G Ôs>Bâìʺ3N÷}¹â±;¹>ü Gy>Ã%/Õµ5ðlÔðs¼¢¢ÿm£"”3÷U^Ù“—Ï ¿a Qß aÙ| °ÑÖÑ ñí,k+WHkáWpìßý{©VXó[`rȦ_ÅQ<«hŸÑ5Kú.׿nŠã¶õU EO?%¹räÏh Ûó'šôùl®¸£\‹AxÇçñ.~¯iK<ÂèÞ/+Nö7AŒ=Úç“ü¶x¯lZ@5ùàªC§½*Œ|¤û&¹°G‚Š\1}*ÄåÈøûÛ° y×@nÐÁÿýEX>&Çíµœdu1[4غ&åi<ÅûI8¬È»ï‹}5ÃlîU ÚìH éÍ×b›QÛ¨V"6'ã©¶rz®½»`ÿ2C›8ª‰Ù“>›]„ˆï¸‹‹Y«9ÑÏ­ô À5‚o êiwaÇc§Ø„!ö€²‹J åF9O fõ1Ækøº³ÚŠÐŒäÎPù‚eN¤'ëtTMC<`ÝÉmDåʘ—FĶ·²çü-X§À¾v€zUªÓ°£6D²&µ!HÅ–ÙÁ‚ty,éT§½\Je&Wš…Ó·ýðâlšêPÁ¼šE´]™f·*¾W„I„.=•V~ó6‘Óûò&¨ý¹ÄGÍ‹±G$°#AÜAƒ–¥´Fô+jëÂÊeûÔª’Ê.4rDõ áªâ=•Ö„b<ýRÒ™¨m’¤9;*‰‰u(äÉ'@,®àÊŒ³Pî¢;":[<ÔHT+Ç+‘ˆï¹œvŠ10¢ôêè.vþñ\2¢`!í"ÜkOŠ:¢å*ÌfŽ£ 1´„õ/ sZq ~'f°ˆÚˆ{ñ4[˜? ÄŸ€WÒ>ÄT’ê(W²+q"xi˵oMZËÊD Å^U páÂÞú*.'ìWwâ]riíj¢ìæ=!dn6ï!¦¸,¶ßr°ÝÅ=ÕzSοeXpB¼.5‰†B‚ÈÆ¼‡Ð0…qÎròDS ™MÜ"¸Žíy¼)0‚ôYF®n}³qéìŠõ¾¬¢6SîNœÏŠ®'#ÝÝÝù“\ÄþÉ#[ßqœXª¼*ÆpŒïR±#×ÝM´±ÈºêI’iWÓ—šàiß§lúæ3l8“wsõS¼m&~ÿ¯¾Š‰d¯ÏCâ)üÆïfh¦x“ÿÆ‘šŽ3=·7ºÇ¹»õ ŤRÈ,©x„ÖÉ#¶wÓc‡¸îIeœ~MÅb Ó¸D–áÂl„éÕﯗ’ “®i^ñ,x”ÿÆ;‰£wù÷XQÖ3mAˆgØA; š¸û!N7¯FèíMr=éÞÐ~l4åªpËêêô‡†3Ø|ooy†ý¹D¡46Œ?Âöo]ß8V£ì‰]t˜äh¬àv"Á±;‡ËO庳A䈫PjÖ;n3Ú+Šººø&y<ª»q7”|PïäºbûgIÌßþÚ«Æ€ù‰oL?¼Ï7‘-#Ö®~ z #‡k)s˜MÂ=@y2×ä¸Eô‘9ô$5ûÀ:"¦›™1 Íj†Y´L Ê¥ƒöâCòW¦öAÊåª!‰öŠT…‘ÛÎzeR¥®6tdp©ZÜb…üòض’Ü‚¯^qyÅ€©Îâ½/ŸÌýRb*Óã*žlèÛRAî“t©ÈÛB¬]Ó•LêèBD Íù! T™@× ]b¬û1É2¡@Ôé}iÈ´Ìig!_×ôÒ¡]€sÚÕ9¢9í –Úbíå[Q*ùV•E¾ËdÔ,åÓÁ 4¥ñQR­“ÒŠðØ<úBzUç”»ÜØ*¦NyK` ˆÇDêÑÆÞê$KØ—¶;‹~+åNõ£Ø¼ýIIo¦±•JÕvõƒ©vvžWwuˆ1N§×=웨G“w2†|EêC,AIð£†KaL¶«£bšÖ—á]¶Uu?B…æ³¢iFë&%Wêô.ct²®Ij9þj’›hûÞ`´¹rO° ·§X2e éL½8nБjg•4Ñ×ê¬Âí}m ††Ìå)'hN{Í@/‰¦ÌÜ¿wüe›Â¯öŒ!AwžÛZé軞â=4g6ó${”kCŒ&YßwŽlËñðjò‹êθÏÌg¹ÆÉdÓ»öB¦Yoòé&ª ¿\»ºöö€Ïÿ%ÛƒÑWx.1Ñ&€yg[=–·¿–ð¤Îrÿ@Ý ¡Z>aÞþ\Ýoëê4¾¤kG\êJí¤+ê¾=ÝÊbç38uKVÇ x11´§_±‚K]Mñ”瀘ßêÒÈ̦$s3uŠ­'¬ÈÍ«Qk6j#àc•l½†ÓbÃØÑ-=–,6Љ6Ü—‡¥©÷rh¤hýšh 0r»û²Ô=H– àJOFÈ)öQìѰ¨¿®ðn™üÁ­Jè&+Ô?Zâhýè¢ýôŽçJîÊš`ÝCôG¹ ¦! âR àȾ{W–’Ä9ÅÎ(Lõ®R;z³¢ÞÉ …l$â{CYê Œ§b­†\¸·ð çr‹ëLq²°ŒO¡ÞYO•ã– —àhÈœ÷PiBŽkõØ2° {5KëJ´‡ò½².pqlÑå9Ôb¬+`‹’HïAœ™NšWÑL¼ç'(û±£‹èèí¯ŽáV¼9ƒ P‰SG¿wMK ý0ƒ ™ÃL„ŽVâÒØ¥îÓVë´à[ËÒ»æ+{åÐXFcV¿é’.¥"2eÅR31ë­2;£`ϲ ¿“ôJäp7NODÖ8‰G÷>úU¹.!šÖPp²ªÖ!Ä7ÉÈàrº0úËsÉà„†·aú¤6Ü©¬ÆhDÌ‹-Rž"³ Q9Í©@˜…;‹"לµ>YÝ…‘óu.FëR•Ð"#pÙWb¥Xp9NQŒBoù,Ö ¥dåJÅÃÚ9hE¿î‘ö>ƒ# 7¥ïÇŸkpùj§c?¬Ž Žo3ޏºp Æ„#PßK’J;õžð Ô=¯»Jxû:gâÀËÛ´›‰Ý–ï%˜ÜTw>d°ïÃcÀÁ&ÎŒâ|³¡%äHÇß”€¾.…0Ú,R»?Ñņc΀|6¦ñ$—¨Œ3>ÕA°8ç`øuAÁ‹xí`R±µ'Ç †Ä5ÒÈìYÞ´6¿”,ktôl7ä=õLØ’Ì{Maåó×hÂgÿv[‹´£Ì¡¸t­h=Ë8ý¾Ôf¨‚c„Ã3Æ£¶1Kõ^ù´r´ï¨ºÅ°>Õ(‡ö.{2d[X¯+Ù,]½'o“¡yÛXò‘>ÃY1KÃõi6BZ8®®š¡#µém0Úl¼.pé(–J\¨6®†šq:¹îä2±ØÒóq -§ôUÎ,6¯jÃÄ y_ yõ úcÂ;‘#¼¼šäê5Ùv›ÉÖ‘Þ)àÂ~7ÄË”û‡3ÿ-€Æ]ý÷o™¬þ–ûI¼\°vìpÖèÛQž¯žùèŠuthònÿÞJþ-¬-¯éµ~uŽë(võGAJg½npFF…³ß(¹|ÐìrÒxÆ9Iª­ÖßWÁ†1y•ÃxWmü>áP)ç œMvé¾² §füw#‡3º²š7éœu%’-¦Ü3œÕ©b_SÔc³åy:“ýñ~µU´åhþ »žÙC€ë;˜Êá…Çwœmàþ™à𫤣×ð—Ît=QoÉ>_39ø‚s$‡ù•H¯'Ù*m¸»ÃÑðè§'9Ú®ÇÐ?ßøÊâ«´{æ3"”»ÁŽ&¥Â>ÑBªrL:ÒÓÔ£¾pÞõ]Ä+ÝOušŽÆiÍ_ýß‹c>Ã[FWSŒÉ¥߸¹tvÛ‰@]“rx'ë÷VÛ¯µ8E£G|–@>½ÒÚCÿëŸoúy<$†`Òwß‚–Æ•üLÄPïíÃ<°´‚%8°é3ÈO ŽûgËâ%ì;øiÅ`Q‡wèt5`±î[,º<ÔÅý^J›9qþ›œ‡Œ×]Â'aêÙùÎeî$•¼wieÃÑ©ókÂäòL¹˜Œ¿®ìš0²äBIýž„K=Ú|››®+rsH:¿ÝÏNÑbŸJY%¤%ƒ·ášÌS©¶ˆ5?ãuE*™ûD»†û¹ÐãÛßJ«¨×0›¯3sªäW žÃòX:€£\È_•IòŠ¡wf¦¶™¯AŽ  ¤&¢¡ÏÀ3¡CijC“ G]IúV?&"Ѹ½~«¦üÜ>xi¹ —'s[^ÁÖêâò„T•ëb8±wC€ÕGsE—øÁÌ ÓãºTgu¾ËéÐ/ñs8º¤Ë‡˜ÆŽ<“õ„“‚sazù.cXWå´”À…<+¡“9|È*éGÌéíäÏ>Àªƒ Cn.~Š?zôµ0®Ý•ÝïÀãV p Ä®÷:Ÿ©ÜÑX€ÅÔ® Ì%Ëøvå)z]z «ê*âCº(\ÝY¥Vx>It€kÕ¡ÇžqÞ½bGn]-aK+Öx[“9O=ºÐ¼Õ¶ç1ØâË+–;@¸Aî–Í(aíJžýÄpm±Ä5@˜Á¥¤‰ý½#Ï„±á‰¥kyP¾"´Www'ÙJñ¾³k˜§‹=YŠÐÑ÷\g\¾7“¼ºÊØ™xµë(…ªþ¤ƒ”Üþk«ÅÔeHáô¥‚$*6_3¸)b¿nb5ém¨‰nVÞOáÜ¢zïÑoË,&SMÞSmÄ\Ùë„lÒÞÞè”Æß^±œýîBÁÖ@u,C,Íú9=7[ÈO1°X“]6]»ªe õ(û’ÿ£¦ÝëáIª·Z5ýs'(â;•Ïtæ'žÁ þú^A²ÍPw .ÌG[8±ÝùÞN`ÃèN#ü1­;Á \ïþ`oË)óJ°OxÝ}Àjǽ³).0ŒÝAĨ×MƦnÜó‚Í•?tä³z~žM)i5}ßéȯ {8ÕKxµëŠ.Ÿqîò«ªýŸK±¹L®]2a5ñ¾=hDsVlBóu‰-gC^«ÛÄè_å™ùL'Ìé! GiC1ÕÀØÁ‘ð^ÏòÍÅÜFÅ&±ý¼ã‰1+ R¶i_,ræúÀ3¶¯ÔÅä’‘Ö½iíY?ÄwØw2å bÛÞX*Vð¹G×]ñ8®j½‡l´7†jÑ5šKÙWãï-1"^ÿ­³Fë_aL¡m³Èž“Zäð_‹l7 h­z$Õ‰ùZLÓUë[ÏÄŽÜ*â:*S_ù•™«½þ>ìš§ëWµË³—¾’ ÔÎDämëµS7Øz< Ÿc5= ÄûNçM6]—øbªËßçG»?R6 ÒìÊ"„2⯦Ãübm Å%ïrÏ.F¶´à ‚Ä^©¥SŽôÙê/-­Ä3zȇîí±9qØ–¼k„ð­Š4UKÍgTǧCרbÁõêÒ£1 oòª.„ó/ØMúNò7%+=ó9*Wq” ‚ßßJ+†`òê¬åˆöä³zaëk¶T-½ýì‚C‘>’õõ-Ö÷ªnp ‡_K?›„1#,E¤öm6ŒèlIóŒœ#°bŸÞ4ÇáTl©"΂q3#Ö'i à<xÅ@ã($?ƒâ¶ÆAþ&*Y=æž$- DõŽ\ÒèD‰ÌûL2£#Ž#Sœ(Âu3Àrâ`—FðŠqF^ Iʈ&±“>”ºG&ß‹ÄbO+s35A´:<—Fžy=Â#0ž:‹¶a ¹ï€«(£Ÿr“Xº—ª$’®êkq^d\zF”àë·r©ä}hUâŸ8–ë\N¾ ´'@Öª@ߘK¯2#Ôo!¢²ÞCˆøÉP–qP¸–Pæ¬X®,互°HQOÏq‰ö –83+úˆ%¯ªâuGj7ŒírTˆxeÊ[1jHÚºg"?=µÛ[p¥Yí•‘©:×–:¤\Éouô Üw”@1sÚ…UÝÅ8¯ˆAú”øÄÓ±¿³ô)<Õoe"ÝAÛÐ÷I{…qUñ;ÆkF››üä¶á-Jª·jm1:¼ƒÉäʪHºiwg®k-ÂIvàù—!RȘG%Ît‰ÔV0¸<ÜøNÀ„e=ñd›«‰{F;5ÔV)c靿 `•|oÅìR±y¥ãd¤µ%ë]ÈÜžN$²Õ·«CÃ’M¸½ï7p‘«ñ ã^¬AÆ©÷D×\òØz)¶|žä¢ŒÄýé’–“6üÏȧ¦ÿqlô®¹WÜþ·ñ/¼ê3Ñuêv 6S˜¶ô®`s4w<3I<Æ= -’}å#“&Óju§·â¨Ôúäú=Q;H׌ooò’ýªÌëI¦K pïj1bYW6þ ÑFZöïª0®Æè–ѽèíOU[{³@°Žtï Á¶„³ã3È»Òß%àóW,93¹®` ÌcM›‚-PJÕ·š*¼{21H?ÃuØÏ;*î‡þɈ¥ç#…³¬j!›Š3Ÿ“!𜹓üáíËÑï©>ž[òÙ6pl×w(&:nMMbh-Íÿy¢+&E³®æ|sáôϧ¸Š!àu]2ÖCzó‡7ŒvÚ)ê‘®LsÁC½ïCó_œk„ÊPW;ÕlÓ\ÁMÃsF=Œ3®%¶þFão¸(¦˜ü¹¢ÞÖ“+³™¸»¼ï* ;Ã\õ`çê‘÷dWÎŒr_Ù´€ù]?·ºî²ƒöó›®b1c6Pw=“1Šud”ð& cžÈzÄ^Èg“žl/ƒ)½Iʶ£ŸÓÃ͈nh°Éú1"tçœ÷°>Ÿéð×$X– FÜš 'ç¢Ð¨xè-Ÿ©Y=´V…ᘹ?Å„‰úîl(º²«‘Hr†>‚kÆÔ+»Ú8š0¯Ìíô½ÇSÑ„èÚL7°…qgS3'›jg×"¤Y~S”bÆg0 ÔÓö…¯JÆùÚ!¬ÓÔéiöo¿&ÚŸÅ´:ý© è8ód¨ˆ‚9'®ÍEÔ1½t ëŽT‰Ó^Y–s}ª´Ž‚~LOW@ç|ÅC#x˜T¶'g5{HÉI)¢ƒbùD›¢cÀu{ZÌ¢ef¬=jŸžº(BUZâlÃÕY¦Ð myìÈÈì¬ XcŸâzÁ…«‘PcÒŒ¶'§èg‚t¡sÒo/=«w:ðr4žÀ384Ú*#ÿ‚sqzþTVI³‰/˜úº ÁOgs>±Ñan:K³D”Æì‰¤<Êc† ~7—–"X½sò2*¥‰5u¦Ò%”à0žïÓJ#,™ÄK 'Wuã¤$DÁÙ%ý©ASÝÚª^Z¦ôͬ¦çQÉØ†)DÔî¾›Q!2¤¥ÌèL¤¢£h]Bâû½ÊŠg Ï©Y˜É‚úâ©Þª^Úf…PdªËKY0wc[¦ó*¾{ÍÕ—oa‚ô Ü'«P)?8Bª‰$êŽÒ©`ÑáöÒ:TLú6 ´÷$ÕùâÚ§“¨µý´U¬ÊÛÿbÎø?|{qmVC*“âšb Œmëë™v!Îngy¾Ý¥À Óœj*TO¹Ç7‹oߺºùyÂ+zgh \9ضõå•“ÓµØ,çŽGà0lC­¾»Rmñ`ÇÕIÍ"lÀýd—‰£­³!Äß`õÙô¬tj-èâòŒJÞi2uO<œíexË®MÜ÷ÔìtÒG:<¨y0à¶“Ï#g:(¸§ÃÛòZòNèƒK÷Å ?G0‰-éDpåWKñ˜Èú÷ŒCˆæ;>“lú'Ε]ŒG¼w Ó,Oë)§2zç·B8b[Å$÷Kç­°LpÔÇ4Š~Ø8}U¤¹Ë‘‰’)Ws.º[¸×`ºÃbÒ(@ùÌ–Æ.ïŠÚ°õ꨻fÃîñ𖃩½—·ŸMÁH„}ßJÞ4ëk§Ú ÿä¹Á¼9ßwsÉ™Ú;rrá YÙ£ÚwÛ_¸ÎtxËL}â™l¼ïÌ7oÄÔ§Û—ü“ÀöîOï%Û6G”ô&ãÿ¾Í&9ÑH‰Öê ôžMQi6~oÖ ô”‘ÒY£÷ÿø5Hæ‹,ö;»áQ]-¨¸rðóÄcŠ££&p·Áò¼›ÍŽô]ž—øú“![à#‚Z:žO±MDi¬E>ýæSç*g'õ®–hC§îÒîü’ãYúÍšN1Òw4áy6p´Ñú±26Ô¤èO•_oË5Ä.D?:æxê[ö]<[„¶ôFÝÅZýÏŠÜÕé[ŸM@þz&•HøJ½J˜.¢‹5Úüÿ ‚ÄF’ä@€üÌjºˆÌ¿ã¾ «GúÿwÖŒ/põT’Bq|’òÊN'F¡XÕ(vsÕË6%¶q:Dbu¶+„ét ¥X¥‚qJºimå§äˆcCÔQ_‘¦X±—Ö Æéœ(]ÑZD ”nC±\^8ïª5{ãü~ V*ÙêN 誓i u1q€ú»ÐW'BuÅÙ-cÙÝPëÑ+f$—vgì\‚ô|’ëë!§hòïfõ©µwÑ™ QWòÚ8 å^B7ŒŸõA=ðŽDN‹`F©±OäHle¬Gdt’•9¬¨½£!×J²U„ò 4q¬ÏŽå' Q~*ÖÉÊཷia_´º–MµNr££G(l{wa›AJð÷{°u&”òe8Å[d°a5FÓŸÈmP Â.àAYñNÃSÙ쮂iD'”³£QMàÞJ±Fw¹”0žŠl0‚´Î$Ԇĕ™¶r«èMVóifb“ro –Æùï@bÑúʨgH;«=ÉÖ`UCkè >¢³Ü`wÊ;³rxTg7Q*Fmh pm£à£ah˜4ݺ›Hà¢<–‘!gÀ^Á«/*ó‘AÒ­0 ¯Æ×UÏ ?™ÛH)—>Ó;õƒ¹ÎxgLåâ™ñ~ˆJ“ïÈ­ƒŽ wñ6»Üm’Ž$4o¨=P…š}ÝÓ£Àøæ÷Oº#äxÛy„…†ægóeÜÖÖ‡·õ©¾bÓ»ím&²îp–\éîÇïƒÊôø¸ß•2W¼Ç'‚yßœœ#wâ]¸†˜”g*Ê+3¿-Äá­Võè–Éš•¬C;SÑü;A¬æŒµ¢µe”¡³ÏÝœ9i¯öûáë+úìC¼Ë^ÀöݽΕ¡y5××DI8¿©»2ý4órç;¬Ó ¸ýØõ–DÃûoþN^…çé^M~0®©@Vœ'¼Jöãg vZ`Æ ÆïÛîvgúóÖ»œ n¼F¢ýSï°^yätñý]þDåùtWœâs‹®×;¯Ÿ|E:$»&æwÜ[!þ‰Èë½0³WÎ’ïååéÉe‹Åõ7|×[Îi/AË0Þí¾õ®,cÐwcŽ_ßÃË8éO¼B¸ÂÜl Ú×°»‚)´÷µW¸R þUnak@ˆ®¼Ò^‘×¥„çgú’ïtǹ"ŽïÀ´g¢šub˜Óôq%ø²ó•Øž7—» ì߃-AöiôÍU¥õ“ï ¢ ½©MHkNÄÍÅgOŸEÖÎ.«dÜ¿îæ Ë<éUDËw<Û¨Båø~W—‰ôŸôyoìÞö,Ð…ÃÝž\îäËÿ\jñöVïâòï§ÀGþig3ÅWvÒÛ—íæE^ðçN#ø‚оô)½:½ËóÿHT^ïêˆ|uÒgÍ]œáîùÎÏÉá!_>ã;&Š·¼åêªé~ŠÑeÎg¡ŸÞy¨ÿØ#¥—ކíeý¾ÈÝÎÔ°Ñ<öeÿ”`û»“Ê÷wz7Í+”3B™În>O’ebWÜ“drAh'ãIÐz•²|ð4>åUˆÛóhœ>“Ž|¿BïšÄ[ç»ûI$Ð>ƒBuUÒ„àçϤ2¿${÷ú–š®Ô5’ŽÂÖ˜üm#I+–ÄÞG¸{÷}µÿF؇™1<#—w=-PlæÃ‡¨Ì„Ÿp‡÷ÐØ5ŠÖ Db¯mŠ|´0¶Ç^µhà0§Úê\y‚·“1LðÀý¨L%“râK¶©h_ŒMœ®Œé¨hè+pĤ½p^Ìý'§É¨–Þ“ÒBï¹MÃYƒîJ©³zjý;3R;‰Æ#‘Âj?™Á‡“¥OV±=Ùž˜"é}E¾Ã0ƒm6ò…ït‚–Ó9ðûþŽ‘ë£¨†U¬½ç·bˆyX¨ idN³XÒØØv!D{¢´ªŒ‹ã§š<ÛR¬KÃnŒ¬]}~'“Ë;I¨ËPÈ'•ažcÞ5ôIˆh‰x!‰«…:sVé]¤å¸=Yƒ„@ñ]‘”Fà6•Ke@âfš“}¶Veü ªŸ˜v­uš&‹;¤3…E÷ ¯qëÈ@áO5¬M8åÚ¼®JœÜÌÚŸä‰,½°¯Ä„U¹ QëûÆý–;ºn¶f†0%Ÿc˜ät†ÃÄônÊ¥Ú؇›;ÆUÕO汓3;¦RXn ³Œ>v³W—Ôæ»úÜd¼—‰È–ÐFóŒ­Üís„L$¾Ÿ@Kôu7D¡®©d…àr¥zªgã-T»8hTvv,<ÉÖ Úxœ¿CÔÂ&kUoñ£éøЖ׵ÂWO·¢tG­ çk‡üé Hé;¯“¤¼Ë^úʆ}UÈ`k„ÿÉÁâöŽWgík¹ª±óx/áxÿt—eª³€æ{8¨3½’ÓôJ{ 7n^KÿÔ6»§ÃC^’¾Jßb†Oï'þiÐ:­ŸMø€Í•xrK®>é.õš.¡Þ".¿÷¥E6Øó¨Kw‰üìx™\Øz盘ûo§¨¼½“L—Öß!]eöÀÉ{Ú4ê—~G'g‡ÿ¨çìמÙ7Оõ»Šå»|¶ƒ~-KŸ7FÐèVOÀÉ5—ΰ?5^å Àè‡÷¿ýj–ã«ìvaÆrÓø™¯àr|õ±‰Ô¯ÿDˆÛI·Å?t•Óí_¦°{¾8¸æ¨ïp-ÉêŸß ±¢}‡ÏOxeŸŒÏ®—-ˆ?…çJ‘ú{:aW]n•¯q™Ùû߉A©ø¸†@zeòc÷;Ò=|\ïË'ä3õNÁ:–säŠwõ0k§Œ®ùr>™Ë+y\_w{šÓ}ë<ïäƒCó夸!½Ot“Å®4¶öçJ·Î™\y9¡¹;jºÅǽƒëlzÇgP™Ô©œ•¡^H~}6†rë?ô~àî÷»¼4¹âpýTìWPWJ†\ }Ûg30†¶Ë?_ÙÕÓU×+Gý¼ãU ŒsˆKPÎÓ]Μ^•róì­7ó È0ÎÎe±Ü4v²¥&T{ÂTQ½=¿—¨rûÌÔ+EÏm(cï¬VýÎÎZQÈk W|:Ó¸:ê§p.Ïô¢K;áÌw€xº¦I¹*=¢Ý܇å_oçÓ}ͤœV?‰ï+î )Xq8†iñ ˜šÀÓ‰|8ɇ%ôÂ6KXõ–qJ{(©ŽI°’Ø*hÝ+@]â£|1Jü¼%>X¹G)]˜¥V '”À©˜2ÏŽ6³ÕM00òbS½ •5üÍÜ+ÙŒQ0¯€­QU­G !M“³,x•¹Yˆ9ÄYX@O…x‚ ¦©Pª ‡w'mLÆq£ÞÉ.’‡å ã#P“Äf¦òŽ€ÚvÔg—Ð2êÒ€¾ÿ(¬Jàd7S@-¯ª]É´t£XT‰s593ˆØRlóö¢­#ŒÎc‰ …л0¾äÒû]BÂAj²¸Dú ª¼Ê-5Jz8Áž}I2wðl"µ¡ž¡EWD&ʬ½ _öwA&™ÎÖ hܳ´O”¨ùÃ2º€À!·LLñpþà ÓØ l@z–ÞfÒ±•Šq¸ÃîÆ&O ó |è\~:’ÞIÃó©œ4v £‚WúÐŽQäÜ9|&s–©Úfmr7rΖ\ Áç%eæÚгÉk¯ty|ÇýÕÿ´?NÇÐosÙxJÁè`{&ýbU:ïâ•y^qŸ‚™›áøL‘zë˜üН,ØJFñدÐfð‹Ž¸±ô¸B߃}z-Ãùiß*Úîôû¹Ãz~»7äâbÍ€åjYò¬WÐïú¬¨ž mß,MkŠ3( 5©¾!Ì.p+÷¿£—âò©žìµÑžw½•ítpÓÙ*ûfÏ´Èz!×QÄ÷Ö<ÿ&Op‚]u‡íëN®°[ïõ², ÆÙáŽ×N¸NqJ>\ã}¢ï¯lú>…FââküjþD½¹Ù^q®@ù5Ìןñ‚×~§÷å;8ÁOõP«XM醱4œ¨BaEªÄÙ¬ˆÙXØÞUJenÓ "§© Ö9™ÞQ™â¬¡U!â1Ŧ‘Ãñ[µ”’IÞhÂã©WÎÁz¡¸TÊbjÄx‡ºïê<¤³cØLû›¶Ú™šÆ—/_"=P}Œ‚åè¥ñ)26^7öö²ž$ c2Ô¥ý·‚C&mF5Ù‡Â.$»i›æ…çb>U•©)ÏånÆœ=ö‚À:È×A±V*¿™ í­¡Wg³JýD5 µþFÃÌ¢Ûìtž t¦É–ÊèÌŒ%PG JMÌF»PÛ…”íļ €ÐÈv@äÔ…Ï ¢83Õ0ˆu/g‰ì,ý8Øøaû™DÁ–Bþrq@ѶÅ9"æé3I¦ Ö'P„> õ®Ä}e©˜2Œ]-B=§8ƒ}XYaƒÌ'ûŒ©RœÔ c:ƒ!@Ð;Žê$IqÔf䦣`=Å“PõudÅ­òŠg‚É]©œeNafžŸŽª6}þÁ⟂󧰠m’ÙÙÇ{DšÇœvˆgò-Ô—QAˆƒÏ­óË`+»(¶(­ ÀÊ6ŸðLÈg°Ÿ!<ÛA»k§¡ÿʯ€5ߟÿ{H2æ¾ã?™st«Û‹w§{ÉmNé;ìÈ´€Ç‰W€5±ü<3f'ó„»CÉ´ß R¢õ²ºò+û¤´WÇ©ü ³±›P¶jWNØïôyÊ?qôzY´7•g*¤?rýIçaFÝ>ÿ|ä;ÝaÿFß‚47vYøØŸr'“ü]f#Wî£ÝUÁ¾ÓYFÚ*ñ\”þ‰ç-®º‰4OsF¡»r~£O._®¿ËÅwè®ÿlÆ ÉÓzëoY_ToÚïè'Eóc ½ËeÏ$_¯`°O¾Rü“¾ãêz7ß?Ì\…þ÷7¹G³ÙîcÂ~…ŸÝåj†gÈÁ%Ïß_Uå÷=nF¯ºwâá’I_ýªKk(æ—οÃêò®÷]h!¬§]Íœ^ñý£¾ ŸßíÐâõ¢³÷2ˆ+­¿ÓCó¸÷rUMíîk16Wo×—úä9ºÖʸšã³Í7‰ñÕÆ ʯøâyú=™î=½tŸ‘ûóužæR¾ÓzU—±_ªÝ%ßíΣÐ]¾±öà[¦y‡ç'ÃÂBßa®²Ÿ¿²ïÆç±W_®ôY,oʈce7êUN¦ô†€ØvÓ¢Þ|™ï¬ÛG ¾š/ÂKï,#pïù5ÔG7ÿN”éâÍgEŸ…ÄV5?ЀŸß)A\Þt@EiÅd±g?Ïf*˜n=Ý Iiž\}öÔv×äÙhœ†î©a-½«#õ¹V°†éNÏÓù±œ ìCZ¾ì£îô. Ô]Ý+•¨&TO)1gGÈã\É$¾|&âЬTvâÕEœ|&è„°½ ÏÂÑÆÓ$4Œj½ ‘tVÔÉY¨ìµEu²Š§&.žNÅ$b]µ@Ÿ§ÂH!s<Ëö6‡úÊœ´ÍDíp@L#ø'±PûÐíÛ‰Ð!õcN3Em©þbV'˘Èz7ÚˆBýÿ¦•JŒX:Sg",;s-ØB\'Ò; ø/d&ÈŸÌÜMk‚Ûù)Õ(ªeBä¡ Ô©B˜†ÝEŸê‰ÈÚ6Ù»„ðL3y´y¬ì̈á“)%ÀT FFðz¥'8/sîBHa†›{ æñhyºÊyÍrƒ®ÒŽÈ¢MdLa¡~,U& ñDˆS•05ÉOaNe™¯[™ËÀÞ ûBg\ è“UPv´ZˆçÊߨÊq¤‚bP+…‘™X§qŸQÕfƯâCoJ‹A<éÉÆM93Î(c5ȪÝéÊ –êÚÙÙºWÔ„ƒuŸHYÒðýçm^!8}¿£3Њm ư5» Bþ“v#Œ8PžŸ‚™Ëp¡Upzwµ±*VŠ ë»áí ‚Ì%AÊ®ìà5ò iŸèõ.ç©$¦=–@} ¸>Yá Æ.b®ž’8ÞÒªøâGÇ22á¢ø<泫…RÏ7ËÜæZÑÒÓ}ÇÝåÿž.âÄ&9‹IEND®B`‚kramdown-1.10.0/doc/documentation.template0000644000175000017500000000161512672246616020441 0ustar uwabamiuwabami--- name:sidebar pipeline:erb,tags,kramdown

Documentation

* Parsers * [kramdown](parser/kramdown.html) * [Markdown](parser/markdown.html) * [GFM](parser/gfm.html) * [HTML](parser/html.html) * Converters * [HTML](converter/html.html) * [LaTeX](converter/latex.html) * [kramdown](converter/kramdown.html) * [RemoveHtmlTags](converter/remove_html_tags.html) * Syntax Highlighters * [Coderay](syntax_highlighter/coderay.html) * [Rouge](syntax_highlighter/rouge.html) * Math Engines * [MathJax](math_engine/mathjax.html) * [Ritex](math_engine/ritex.html) * [itex2MML](math_engine/itex2mml.html) * [Mathjax-Node](math_engine/mathjaxnode.html) * [Configuration Options](options.html) * [Tests](tests.html) <% if context.node.children.first && context.node.children.first.children.length > 1 %>

Contents

<% end %> {menu: {options: {descendants: true, levels: [3,6]}}} kramdown-1.10.0/doc/quickref.page0000644000175000017500000003646012672246616016510 0ustar uwabamiuwabami--- title: Quick Reference in_menu: true sort_info: 9 --- name:sidebar

Contents

{menu: {options: {descendants: true, levels: [2,6]}}} --- name:content # Quick Reference Below are examples of all available structural elements that can be used in a kramdown text. Since the kramdown syntax is a superset of the Markdown syntax, only a small part of the available syntax is not available in standard Markdown syntax. Note, that only the most basic syntax information is given. However, a link to the detailed syntax for each element is provided (which also details the differences to the standard Markdown syntax). The quick reference is for version **<%= ::Kramdown::VERSION %>** of the syntax documentation. kramdown has two main classes of elements: block and span-level elements. Block-level elements are used to create paragraphs, headers, lists and so on whereas span-level elements are used to markup text phrases as emphasized, as a link and so on. All examples below feature the kramdown source, the converted HTML source (shown when hovering over the kramdown source) and the output as it appears in the browser. This looks like this:
kramdown example code
Example code converted to HTML
Live browser view of example code
# Block-level Elements - Main Structural Elements ## Paragraphs {kdlink: {oid: paragraphs, part: "paragraphs"}} Consecutive lines of text are considered to be one paragraph. As with other block level elements you have to add a blank line to separate it from the following block-level element: {kdexample::} The first paragraph. Another paragraph {kdexample} Explicit line breaks in a paragraph can be made by using two spaces or two backslashes at the end of a line: {kdexample::} This is a paragraph which contains a hard line break. {kdexample} ## Headers {kdlink: {oid: headers, part: "headers"}} kramdown supports Setext style headers and atx style headers. A header must always be preceded by a blank line except at the beginning of the document: {kdexample::} First level header ================== Second level header ------------------- {kdexample} {kdexample::} # H1 header ## H2 header ### H3 header #### H4 header ##### H5 header ###### H6 header {kdexample} If you set the option `auto_ids` to `false` (for example, by using the `options` extension, see [Extensions](#extensions)), then the automatic header ID generation is turned off: {kdexample::} {::options auto_ids="false" /} # A header without an ID {kdexample} ## Blockquotes {kdlink: {oid: blockquotes, part: "blockquotes"}} A blockquote is started using the `>` marker followed by an optional space; all following lines that are also started with the blockquote marker belong to the blockquote. You can use any block-level elements inside a blockquote: {kdexample::} > A sample blockquote. > > >Nested blockquotes are > >also possible. > > ## Headers work too > This is the outer quote again. {kdexample} You may also be lazy with the `>` markers as long as there is no blank line: {kdexample::} > This is a blockquote continued on this and this line. But this is a separate paragraph. {kdexample} ## Code Blocks {kdlink: {oid: code-blocks, part: "code blocks"}} kramdown supports two different code block styles. One uses lines indented with either four spaces or one tab whereas the other uses lines with tilde characters as delimiters -- therefore the content does not need to be indented: {kdexample::} This is a sample code block. Continued here. {kdexample} {kdexample::} ~~~~~~ This is also a code block. ~~~ Ending lines must have at least as many tildes as the starting line. ~~~~~~~~~~~~ {kdexample} The following is a code block with a language specified: {kdexample::} ~~~ ruby def what? 42 end ~~~ {kdexample} ## Horizontal Rules {kdlink: {oid: horizontal-rules, part: "horizontal rules"}} It is easy to insert a horizontal rule in kramdown: just use three or more asterisks, dashes or underscores, optionally separated by spaces or tabs, on an otherwise blank line: {kdexample::} * * * \--- _ _ _ _ --------------- {kdexample} ## Lists {kdlink: {oid: lists, part: "lists"}} kramdown supports ordered and unordered lists. Ordered lists are started by using a number followed by a period, a space and then the list item text. The content of a list item consists of block-level elements. All lines which have the same indent as the text of the line with the list marker belong to the list item: {kdexample::} 1. This is a list item 2. And another item 2. And the third one with additional text {kdexample} As with block quotes, you may be lazy when using the list item marker: {kdexample::} * A list item with additional text {kdexample} As the content consists of block-level elements you can do things like the following: {kdexample::} 1. This is a list item > with a blockquote # And a header 2. Followed by another item {kdexample} Nested lists are also easy to create: {kdexample::} 1. Item one 1. sub item one 2. sub item two 3. sub item three 2. Item two {kdexample} Lists can occur directly after other block-level elements, however, there has to be at least one blank line if you want to follow a paragraph with a list: {kdexample::} This is a paragraph. 1. This is NOT a list. 1. This is a list! {kdexample} Unordered lists are started by using an asterisk, a dash or a plus sign (they can be mixed) and a space. Apart from that unordered lists follow the same rules as ordered lists: {kdexample::} * Item one + Item two - Item three {kdexample} ## Definition Lists {kdlink: {oid: definition-lists, part: "definition lists"}} A definition list works similar to a normal list and is used to associate definitions with terms. Definition lists are started when a normal paragraph is followed by a line starting with a colon and then the definition text. One term can have many definitions and multiple terms can have the same definition. Each line of the preceding paragraph is assumed to contain one term, for example: {kdexample::} term : definition : another definition another term and another term : and a definition for the term {kdexample} If you insert a blank line before a definition (note: there must only be one blank line between the terms and the first definition), the definition will be wrapped in a paragraph: {kdexample::} term : definition : definition {kdexample} Each term can be styled using span-level elements and each definition is parsed as block-level elements, i.e. you can use any block-level in a definition. Just use the same indent for the lines following the definition line: {kdexample::} This *is* a term : This will be a para > a blockquote # A header {kdexample} ## Tables {kdlink: {oid: tables, part: "tables"}} kramdown supports a syntax for creating simple tables. A line starting with a pipe character (`|`) starts a table row. However, if the pipe characters is immediately followed by a dash (`-`), a separator line is created. Separator lines are used to split the table header from the table body (and optionally align the table columns) and to split the table body into multiple parts. If the pipe character is followed by an equal sign (`=`), the tables rows below it are part of the table footer. {kdexample::} | A simple | table | | with multiple | lines| {kdexample} {kdexample::} | Header1 | Header2 | Header3 | |:--------|:-------:|--------:| | cell1 | cell2 | cell3 | | cell4 | cell5 | cell6 | |---- | cell1 | cell2 | cell3 | | cell4 | cell5 | cell6 | |===== | Foot1 | Foot2 | Foot3 {: rules="groups"} {kdexample} ## HTML elements {kdlink: {oid: html-blocks, part: "HTML blocks"}} kramdown allows you to use block-level HTML tags (`div`, `p`, `pre`, ...) to markup whole blocks of text -- just start a line with a block-level HTML tag. kramdown syntax is normally not processed inside an HTML tag but this can be changed with the `parse_block_html` option. If this options is set to `true`, then the content of a block-level HTML tag is parsed by kramdown either as block level or span-level text, depending on the tag: {kdexample::}
Something that stays right and is not wrapped in a para.
{::options parse_block_html="true" /}
This is wrapped in a para.

This can contain only *span* level elements.

{kdexample} ## Block Attributes {kdlink: {oid: block-ials, part: "block IALs"}} {kdlink: {oid: attribute-list-definitions, part: "ALDs"}} You can assign any attribute to a block-level element. Just directly follow the block with a *block inline attribute list* (or short: block IAL). A block IAL consists of a left curly brace, followed by a colon, the attribute definitions and a right curly brace. Here is a simple example which sets the `title` attribute of a block quote: {kdexample::} > A nice blockquote {: title="Blockquote title"} {kdexample} As one often wants to set one or more CSS classes on an element, there is an easy shortcut: {kdexample::} > A nice blockquote {: .class1 .class2} {kdexample} A shortcut for setting the ID is also provided. Just prefix the ID with a hash symbol: {kdexample::} > A nice blockquote {: #with-an-id} {kdexample} Sometimes one wants to use the same attributes for many elements. kramdown allows you to define the attributes in one place with an *attribute list definition* (or short: ALD) and just reference this definition in a block IAL. An ALD has the same structure as a block IAL but the colon has to be replace with a colon, the reference name and another colon. By just using the reference name as-is in a block IAL, one can include the attributes of the referenced ALD: {kdexample::} {:refdef: .c1 #id .c2 title="title"} paragraph {: refdef} {kdexample} The order in a block IAL or ALD is important because later defined attributes overwrite (with the exception of the shortcut for CSS classes) prior defined attributes: {kdexample::} {:refdef: .c1 #id .c2 title="title"} paragraph {: refdef .c3 title="t" #para} {kdexample} ## Extensions {kdlink: {oid: extensions, part: "extensions"}} kramdown provides some less used functionality through a common syntax. This will allow the easy addition of other extensions if need arises. Currently, there are extensions for ignoring text (i.e. treating text as comment), for inserting arbitrary text as-is into the output and for setting kramdown options. Here is an example that shows how to insert comments into text: {kdexample::} This is a paragraph {::comment} This is a comment which is completely ignored. {:/comment} ... paragraph continues here. Extensions can also be used inline {::nomarkdown}**see**{:/}! {kdexample} As one can see from the above example, the syntax for extensions is nearly identical to that of ALDs. However, there is no trailing colon after the extension name and the extension end tag needs a slash between the colon and the extension name. One can also use the short form of the end tag, i.e. `{:/}`. Attribute definitions can be specified on the start tag by separating them with a space from the extension name. Also, if the extension does not have a body, there needs to be a slash right before the closing brace: {kdexample::} {::options auto_ids="false" /} # Header without id {kdexample} # Span-Level Elements - Text Modifiers ## Emphasis {kdlink: {oid: emphasis, part: "emphasis"}} Emphasis can be added to text by surrounding the text with either asterisks or underscores: {kdexample::} This is *emphasized*, _this_ too! {kdexample} Strong emphasis can be done by doubling the delimiters: {kdexample::} This is **strong**, __this__ too! {kdexample} The form with the asterisks can also be used to markup parts of words: {kdexample::} This w**ork**s as expected! {kdexample} ## Links and Images {kdlink: {oid: links-and-images, part: "links and images"}} A simple link can be created by surrounding the text with square brackets and the link URL with parentheses: {kdexample::} A [link](http://kramdown.gettalong.org) to the kramdown homepage. {kdexample} You can also add title information to the link: {kdexample::} A [link](http://kramdown.gettalong.org "hp") to the homepage. {kdexample} There is another way to create links which does not interrupt the text flow. The URL and title are defined using a reference name and this reference name is then used in square brackets instead of the link URL: {kdexample::} A [link][kramdown hp] to the homepage. [kramdown hp]: http://kramdown.gettalong.org "hp" {kdexample} If the link text itself is the reference name, the second set of square brackets can be omitted: {kdexample::} A link to the [kramdown hp]. [kramdown hp]: http://kramdown.gettalong.org "hp" {kdexample} Images can be created in a similar way: just use an exclamation mark before the square brackets. The link text will become the alternative text of the image and the link URL specifies the image source: {kdexample::} An image: ![gras](img/image.jpg) {kdexample} ## Inline Code {kdlink: {oid: code-spans, part: "code spans"}} Text phrases can be easily marked up as code by surrounding them with backticks: {kdexample::} Use `Kramdown::Document.new(text).to_html` to convert the `text` in kramdown syntax to HTML. {kdexample} If you want to use literal backticks in your code, just use two or more backticks as delimiters. The space right after the beginning delimiter and the one right before the closing delimiter are ignore: {kdexample::} Use backticks to markup code, e.g. `` `code` ``. {kdexample} ## Footnotes {kdlink: {oid: footnotes, part: "footnotes"}} Footnotes can easily be used in kramdown. Just set a footnote marker (consists of square brackets with a caret and the footnote name inside) in the text and somewhere else the footnote definition (which basically looks like a reference link definition): {kdexample::} This is a text with a footnote[^1]. [^1]: And here is the definition. {kdexample} The footnote definition can contain any block-level element, all lines following a footnote definition indented with four spaces or one tab belong to the definition: {kdexample::} This is a text with a footnote[^2]. [^2]: And here is the definition. > With a quote! {kdexample} As can be seen above the footnote name is only used for the anchors and the numbering is done automatically in document order. Repeated footnote markers will link to the same footnote definition. ## Abbreviations {kdlink: {oid: abbreviations, part: "abbreviations"}} Abbreviations will work out of the box once you add an abbreviation definition. So you can just write the text and add the definitions later on. {kdexample::} This is an HTML example. *[HTML]: Hyper Text Markup Language {kdexample} ## HTML Elements {kdlink: {oid: html-spans, part: "HTML spans"}} HTML is not only supported on the block-level but also on the span-level: {kdexample::} This is written in red. {kdexample} ## Inline Attributes {kdlink: {oid: span-ials, part: "span IALs"}} As with a block-level element you can assign any attribute to a span-level elements using a *span inline attribute list* (or short: span IAL). A span IAL has the same syntax as a block IAL and must immediately follow the span-level element: {kdexample::} This is *red*{: style="color: red"}. {kdexample} kramdown-1.10.0/doc/news.feed0000644000175000017500000000037312672246616015634 0ustar uwabamiuwabami--- title: kramdown News description: kramdown - a fast, pure Ruby Markdown-superset converter author: Thomas Leitner author_url: http://kramdown.gettalong.org entries: {alcn: news/*.html, sort: sort_info, reverse: true, limit: 10} versions: atom: kramdown-1.10.0/doc/virtual0000644000175000017500000000065012672246616015442 0ustar uwabamiuwabamirdoc/index.html: title: API Documentation /options.en.html#option-syntax-highlighter: dest_path: options.html#option-syntax-highlighter /options.en.html#option-syntax-highlighter-opts: dest_path: options.html#option-syntax-highlighter-opts /options.en.html#option-math-engine: dest_path: options.html#option-math-engine /options.en.html#option-math-engine-opts: dest_path: options.html#option-math-engine-opts kramdown-1.10.0/doc/sitemap.sitemap0000644000175000017500000000010112672246616017046 0ustar uwabamiuwabami--- entries: alcn: /**/*.html default_change_freq: monthly --- kramdown-1.10.0/doc/options.page0000644000175000017500000000257212672246616016367 0ustar uwabamiuwabami--- title: Options --- ## Options The behaviour of kramdown can be adjusted via the available options. Options can be specified in multiple ways: On the command line : The `kramdown` binary allows setting any option by using command line switches. For example, the following command will disable automatic header ID generation and defines the first footnote number as 5: ~~~ $ kramdown --no-auto-ids --footnote-nr 5 ~~~ As you can see all underscores in option names have to be replaced with dashes. The built-in help of the binary as well as the man-page show all available options. Within a kramdown document : By using the special extension syntax, it is possible to set options within a document. Using the above example, the options would be set like this within a document: ~~~ {::options auto_ids="false" footnote_nr="5" /} ~~~ Using Ruby code : If you are using kramdown as a library, you can pass any options as second parameter to the `Kramdown::Document.new` method. Again, using the above example you would initalize the kramdown document class as follows: ~~~ ruby Kramdown::Document.new(source_text, \{auto_ids: false, footnote_nr: 5}) ~~~ ## Available Options Below is a list of all currently available options. Have a look at the documentation of a converter or parser to see directly which options they support! {options: {items: all}} kramdown-1.10.0/doc/_design.scss0000644000175000017500000002215212672246616016337 0ustar uwabamiuwabami/* Based on the Less Framework 4 http://lessframework.com by Joni Korpi License: http://opensource.org/licenses/mit-license.php */ /***** Variables for easy customization *****/ /* the baseline height in px */ $baseline-height: 24; /* The overlay color for the background image */ $bg-grad-color: rgba(255,255,128,0.1); /* The font size of the logo in px */ $logo-size: 36; /* Color settings */ $link-color: #1666A3; /* Resets ------ */ html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, hr, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figure, figcaption, hgroup, menu, footer, header, nav, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; } article, aside, canvas, figure, figure img, figcaption, hgroup, footer, header, nav, section, audio, video { display: block; } a img {border: 0;} /* Typography presets ------------------ */ .gigantic { font-size: 59px; line-height: 72px; } .huge { font-size: 36px; line-height: 48px; } .large { font-size: 23px; line-height: 24px; } .bigger { font-size: 18px; line-height: 24px; } .big { font-size: 14px; line-height: 24px; } body { font: 14px/24px 'Palatino Linotype', 'Book Antiqua', Palatino, serif; } .small, small { font-size: 12px; line-height: 24px; } *:target::after { content: " ☜"; } /* Typographics grid overlay */ .grid{ background-image: -moz-linear-gradient(top, rgba(0,0,0,0) 95%, rgba(0,0,0,0.3) 100%); /* FF3.6+ */ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(95%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0.3))); /* Chrome,Safari4+ */ background-image: -webkit-linear-gradient(top, rgba(0,0,0,0) 95%,rgba(0,0,0,0.3) 100%); /* Chrome10+,Safari5.1+ */ background-image: -o-linear-gradient(top, rgba(0,0,0,0) 95%, rgba(0,0,0,0.3) 100%); /* Opera11.10+ */ background-image: -ms-linear-gradient(top, rgba(0,0,0,0) 95%,rgba(0,0,0,0.3) 100%); /* IE10+ */ background-image: linear-gradient(top, rgba(0,0,0,0.3) 95%,rgba(0,0,0,0.3) 100%); /* W3C */ -webkit-background-size: 100% #{$baseline-height}px; -o-background-size: 100% #{$baseline-height}px; background-size: 100% #{$baseline-height}px; } /* Basic mixins */ @mixin background { background-image: -moz-linear-gradient($bg-grad-color, $bg-grad-color), url('bg.png'); background-image: -webkit-linear-gradient($bg-grad-color, $bg-grad-color), url('bg.png'); background-image: -o-linear-gradient($bg-grad-color, $bg-grad-color), url('bg.png'); background-image: -ms-linear-gradient($bg-grad-color, $bg-grad-color), url('bg.png'); background-image: linear-gradient($bg-grad-color, $bg-grad-color), url('bg.png'); } @mixin typography($size: big) { h3, h4, h5, h6, p, ul, ol, dl, pre, blockquote, table { margin-top: 24px; margin-bottom: 24px; } @if $size == big { h1 { @extend .huge } h2 { @extend .large } h3 { @extend .bigger } h4,h5,h6 { @extend .big } } @else { h1 { @extend .large } h2 { @extend .bigger } h3,h4,h5,h6 { @extend .big } } h1, h2, h3, h4, h5, h6 { font-weight: normal; padding-left: 48px; margin-left: -48px; margin-top: 36px; margin-bottom: -12px; } ul, ol, dd { padding-left: 24px; } ul ul, ul ol, ol ul, ol ol { margin-top: 0; margin-bottom: 0; } pre { padding-left: 12px; padding-right: 12px; border: 1px solid #ccc; font-family: "Bitstream Vera Sans Mono", Consolas, monospace; } dt { font-weight: bold; } a { color: $link-color; text-decoration: underline; } a:hover, a:link { color: $link-color / 2; } } /* Default Layout: 992px. Gutters: 24px. Outer margins: 48px. Leftover space for scrollbars @1024px: 32px. ------------------------------------------------------------------------------- cols 1 2 3 4 5 6 7 8 9 10 px 68 160 252 344 436 528 620 712 804 896 */ body { width: 992px; margin: 0 auto 48px; color: rgb(60,60,60); -webkit-text-size-adjust: 100%; /* Stops Mobile Safari from auto-adjusting font-sizes */ @include background; } body > header { position: relative; padding: 12px; font-family: Verdana; color: #eee; -moz-box-shadow: 0 0 24px rgba(0,0,0,0.6); -webkit-box-shadow: 0 0 24px rgba(0,0,0,0.6); box-shadow: 0 0 24px rgba(0,0,0,0.6); z-index: 1; } #logo { font-size: #{$logo-size}px; line-height: #{$baseline-height * (floor($logo-size / $baseline-height) + 1)}px; margin: 12px; text-shadow: 0px 2px 5px rgba(0, 0, 0, 0.5); a { color: #eee; text-decoration: none; &:hover { color: #fff; } } } #slogan { font-size: 100%; margin: 12px; text-shadow: 0px 2px 5px rgba(0, 0, 0, 0.5); } nav { position: absolute; bottom: 0px; right: 0px; background-color: rgba(255,255,255,0.1); li { display: inline-block; } ul { margin: 0; padding: 0; } a, span { display: block; padding: 12px; color: #ccc; text-decoration: none; } span { background-color: rgba(255,255,255,0.3); } a:hover { background-color: rgba(255,255,255,0.3); } } #wrapper { clear: both; position: relative; background-color: white; -moz-box-shadow: 0 0 24px rgba(0,0,0,0.6); -webkit-box-shadow: 0 0 24px rgba(0,0,0,0.6); box-shadow: 0 0 24px rgba(0,0,0,0.6); } aside { float: right; right: 0; background-color: white; width: 252px; padding: 24px; @include typography(small); h1, h2, h3, h4, h5, h6 { padding-left: 48px; margin-left: -48px; } } aside.banner { @include background; position: relative; width: inherit; margin: 0; float: none; padding: 24px; border: 10px solid rgba(255,255,255,0.1); color: #ccc; font-size: 36px; line-height: 48px; a { color: #ccc; text-decoration: underline; } a:hover { background-color: rgba(255,255,255,0.3); } p { margin: 0; } p + p { margin-top: 24px; } } #content { width: 620px; padding: 24px 48px; @include typography(big); } footer { background-color: rgba(255,255,255,0.1); min-height: 24px; color: #eee; } /* Tablet Layout: 768px. Gutters: 24px. Outer margins: 28px. Inherits styles from: Default Layout. ----------------------------------------------------------------- cols 1 2 3 4 5 6 7 8 px 68 160 252 344 436 528 620 712 */ @media only screen and (min-width: 768px) and (max-width: 1005px) { body { width: 716px; } body > header { padding: 0; } aside { position: static; float: right; } nav { position: relative; margin-top: 12px; } } /* Mobile Layout: 320px. Gutters: 24px. Outer margins: 34px. Inherits styles from: Default Layout. --------------------------------------------- cols 1 2 3 px 68 160 252 */ @media only screen and (max-width: 767px) { body { width: 320px; } body > header { padding: 0; } nav { position: relative; margin-top: 12px; } aside { position: relative; } #content, aside { width: 296px; padding: 24px 12px; } #content { h1, h2, h3, h4, h5, h6 { padding-left: 12px; margin-left: -12px; } } } /* Wide Mobile Layout: 480px. Gutters: 24px. Outer margins: 22px. Inherits styles from: Default Layout, Mobile Layout. ------------------------------------------------------------ cols 1 2 3 4 5 px 68 160 252 344 436 */ @media only screen and (min-width: 480px) and (max-width: 767px) { body { width: 90%; } aside { position: relative; } #content, aside { width: inherit; padding: 24px 48px; } #content { h1, h2, h3, h4, h5, h6 { padding-left: 48px; margin-left: -48px; } } } /* Retina media query. Overrides styles for devices with a device-pixel-ratio of 2+, such as iPhone 4. ----------------------------------------------- */ @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2) { body { } } kramdown-1.10.0/doc/index.page0000644000175000017500000001072212672246616015777 0ustar uwabamiuwabami--- title: Home in_menu: true sort_info: 1 --- ## Overview If you want to get started with kramdown, have a look at the [installation page](installation.html) to see how you can install it on your system. Then look through the [documentation](documentation.html) for finding information about how to actually use kramdown and its parsers/converters. The [quick reference](quickref.html) provides a overview of the syntax -- if you need a more detailed description of the superset of Markdown which kramdown supports the [syntax page](syntax.html) is the place to go! {tikz:: path: overview.png img_attr: {style: 'background:transparent'} content_processor.tikz.libraries: [mindmap, trees, arrows] content_processor.tikz.transparent: true content_processor.tikz.resolution: 300 100 content_processor.tikz.opts: | mindmap, concept color=black, text=white, root concept/.append style={font=\Large}, level 1 concept/.append style={font=\Large, minimum size=2.6cm}, level 2 concept/.append style={font=\Large}, } \node[concept, font=\Large] (lib) {kramdown's internal representation} child[concept color=orange, grow=120, ->] {node[concept] (i-kramdown) {kramdown}} child[concept color=orange, grow=160] {node[concept] (i-html) {HTML}} child[concept color=orange, grow=200] {node[concept] (i-gfm) {GFM}} child[concept color=orange, grow=240] {node[concept] (i-markdown) {Markdown}} child[concept color=green!50!black, grow=60] {node[concept] (o-html) {HTML}} child[concept color=green!50!black, grow=20] {node[concept] (o-kramdown) {kramdown}} child[concept color=green!50!black, grow=-20] { node[concept] (o-latex) {\LaTeX} child[grow=0] { node[concept] (o-latex-pdf) {PDF} } } child[concept color=green!50!black, grow=-60] {node[concept] (o-pdf) {PDF}} ; \draw [dash pattern=on 0pt off 2pt,line width=5pt,arrows=-angle 60,shorten >=15pt,shorten <=10pt,color=orange] (i-kramdown) edge(lib) (i-markdown) edge(lib) (i-html) edge (lib) (i-gfm) edge (lib); \draw [dash pattern=on 0pt off 2pt,line width=5pt,arrows=-angle 60,shorten >=10pt,shorten <=15pt,color=green!50!black] (lib) edge(o-html) (lib) edge (o-kramdown) (lib) edge (o-latex) (lib) edge (o-pdf); {tikz} {: style="text-align: center"} ## Bugs, Forums, Mailing Lists If you have found a bug, you should [report it here][bug_report]. Also, there is the [kramdown-users google group][ml] available if you have any questions! [bug_report]: http://github.com/gettalong/kramdown/issues [ml]: https://groups.google.com/forum/#!forum/kramdown-users ## Thanks kramdown would not be possible without the prior work of many other people. I want to thank everyone involved with making Markdown such a nice markup language and especially the developers of other Markdown implementations because kramdown borrowed many ideas from existing packages. ## Author * Thomas Leitner * e-Mail: [PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ [Maruku]: http://maruku.rubyforge.org [BlueFeather]: http://ruby.morphball.net/bluefeather/index_en.html --- intro
**kramdown**{:itemprop="name"} (sic, not Kramdown or KramDown, just kramdown) is a *free* [MIT](https://github.com/gettalong/kramdown/blob/master/COPYING){:itemprop="license"}-licensed [Ruby](http://www.ruby-lang.org) library for parsing and converting a superset of Markdown. It is completely written in Ruby, supports standard Markdown (with some minor modifications) and various extensions that have been made popular by the [PHP Markdown Extra] package and [Maruku]. {:itemprop="description"} It is probably the fastest pure-Ruby Markdown converter available (September 2014), being about 3x faster than [Maruku] and about 4.5x faster than [BlueFeather]. Version **1.10.0**{:itemprop="softwareVersion"} released on **2016-03-02**{:itemprop="datePublished"}, [more news](news.html) {: style="text-align: center; font-size: 80%"}
[PHP Markdown Extra]: http://michelf.com/projects/php-markdown/extra/ [Maruku]: http://maruku.rubyforge.org [BlueFeather]: http://ruby.morphball.net/bluefeather/index_en.html kramdown-1.10.0/doc/syntax.page0000644000175000017500000021754712672246616016234 0ustar uwabamiuwabami--- title: Syntax in_menu: true sort_info: 10 --- name:sidebar

Contents

{menu: {options: {descendants: true, levels: [2,6]}}} --- name:content # kramdown Syntax This is version **<%= ::Kramdown::VERSION %>** of the syntax documentation. The kramdown syntax is based on the Markdown syntax and has been enhanced with features that are found in other Markdown implementations like [Maruku], [PHP Markdown Extra] and [Pandoc]. However, it strives to provide a strict syntax with definite rules and therefore isn't completely compatible with Markdown. Nonetheless, most Markdown documents should work fine when parsed with kramdown. All places where the kramdown syntax differs from the Markdown syntax are highlighted. Following is the complete syntax definition for all elements kramdown supports. Together with the documentation on the available converters, it is clearly specified what you will get when a kramdown document is converted. ## Source Text Formatting A kramdown document may be in any encoding, for example ASCII, UTF-8 or ISO-8859-1, and the output will have the same encoding as the source. The document consists of two types of elements, block-level elements and span-level elements: * Block-level elements define the main structure of the content, for example, what part of the text should be a paragraph, a list, a blockquote and so on. * Span-level elements mark up small text parts as, for example, emphasized text or a link. Thus span-level elements can only occur inside block-level elements or other span-level elements. You will often find references to the "first column" or "first character" of a line in a block-level element descriptions. Such a reference is always to be taken relative to the current indentation level because some block-level elements open up a new indentation level (e.g. blockquotes). The beginning of a kramdown document opens up the default indentation level which begins at the first column of the text. ### Line Wrapping Some lightweight markup syntax don't work well in environments where lines are hard-wrapped. For example, this is the case with many email programs. Therefore kramdown allows content like paragraphs or blockquotes to be hard-wrapped, i.e. broken across lines. This is sometimes referred to as "lazy syntax" since the indentation or line prefix required for the first line of content is not required for the consecutive lines. Block-level elements that support line wrapping always end when one of the following conditions is met: * a [blank line](#blank-lines), an [EOB marker line](#eob-marker), a [block IAL](#block-ials) or the end of the document (i.e. a [block boundary](#block-boundaries)), * or an [HTML block](#html-blocks). Line wrapping is allowed throughout a kramdown document but there are some block-level elements that do *not* support being hard-wrapped: [headers](#headers) : This is not an issue in most situations since headers normally fit on one line. If a header text gets too long for one line, you need to use HTML syntax instead. [fenced code blocks](#fenced-code-blocks) : The delimiting lines of a fenced code block do not support hard-wrapping. Since everything between the delimiting lines is taken as is, the content of a fenced code block does also not support hard-wrapping. [definition list terms](#definition-lists) : Each definition term has to appear on a separate line. Hard-wrapping would therefore introduce additional definition terms. The definitions themselves, however, do support hard-wrapping. [tables](#tables) : Since each line of a kramdown table describes one table row or a separator, it is not possible to hard-wrap tables. **Note** that it is **NOT** recommended to use lazy syntax to write a kramdown document. The flexibility that the kramdown syntax offers due to the issue of line wrapping hinders readability and should therefore not be used. ### Usage of Tabs kramdown assumes that tab stops are set at multiples of four. This is especially important when using tabs for indentation in lists. Also, tabs may only be used at the beginning of a line when indenting text and must not be preceded by spaces. Otherwise the results may be unexpected. ### Automatic and Manual Escaping Depending on the output format, there are often characters that need special treatment. For example, when converting a kramdown document to HTML one needs to take care of the characters `<`, `>` and `&`. To ease working with these special characters, they are automatically and correctly escaped depending on the output format. This means, for example, that you can just use `<`, `>` and `&` in a kramdown document and need not think about when to use their HTML entity counterparts. However, if you *do use* HTML entities or HTML tags which use one of the characters, the result will be correct nonetheless! Since kramdown also uses some characters to mark-up the text, there needs to be a way to escape these special characters so that they can have their normal meaning. This can be done by using backslash escapes. For example, you can use a literal back tick like this: This \`is not a code\` span! Following is a list of all the characters (character sequences) that can be escaped: \ backslash . period * asterisk _ underscore + plus - minus = equal sign ` back tick ()[]{}<> left and right parens/brackets/braces/angle brackets # hash ! bang << left guillemet >> right guillemet : colon | pipe " double quote ' single quote $ dollar sign ## Block Boundaries Some block-level elements have to start and/or end on so called block boundaries, as stated in their documentation. There are two cases where block boundaries come into play: * If a block-level element has to start on a block boundary, it has to be preceded by either a [blank line](#blank-lines), an [EOB marker](#eob-marker), a [block IAL](#block-ials) or it has to be the first element. * If a block-level element has to end on a block boundary, it has to be followed by either a [blank line](#blank-lines), an [EOB marker](#eob-marker), a [block IAL](#block-ials) or it has to be the last element. # Structural Elements All structural elements are block-level elements and they are used to structure the content. They can mark up some text as, for example, a simple paragraph, a quote or as a list item. ## Blank lines Any line that just contains white space characters such as spaces and tabs is considered a blank line by kramdown. One or more consecutive blank lines are handled as one empty blank line. Blank lines are used to separate block-level elements from each other and in this case they don't have semantic meaning. However, there are some cases where blank lines do have a semantic meaning: * When used in headers -- see the [headers section](#headers) * When used in code blocks -- see the [code blocks section](#code-blocks) * When used in lists -- see the [lists section](#lists) * When used in math blocks -- see the [math blocks section](#math-blocks) * When used for elements that have to start/end on [block boundaries](#block-boundaries) ## Paragraphs Paragraphs are the most used block-level elements. One or more consecutive lines of text are interpreted as one paragraph. The first line of a paragraph may be indented up to three spaces, the other lines can have any amount of indentation because paragraphs support [line wrapping](#line-wrapping). In addition to the rules outlined in the section about line wrapping, a paragraph ends when a [definition list line](#definition-lists) is encountered. You can separate two consecutive paragraphs from each other by using one or more blank lines. Notice that a line break in the source does not mean a line break in the output (due to the [lazy syntax](#line-wrapping))!. If you want to have an explicit line break (i.e. a `
` tag) you need to end a line with two or more spaces or two backslashes! Note, however, that a line break on the last text line of a paragraph is not possible and will be ignored. Leading and trailing spaces will be stripped from the paragraph text. The following gives you an example of how paragraphs look like: This para line starts at the first column. However, the following lines can be indented any number of spaces/tabs. The para continues here. This is another paragraph, not connected to the above one. But with a hard line break. \\ And another one. {: .show-whitespaces .ws-lr} ## Headers kramdown supports so called Setext style and atx style headers. Both forms can be used inside a single document. ### Setext Style Setext style headers have to start on a [block boundary](#block-boundaries) with a line of text (the header text) and a line with only equal signs (for a first level header) or dashes (for a second level header). The header text may be indented up to three spaces but any leading or trailing spaces are stripped from the header text. The amount of equal signs or dashes is not significant, just one is enough but more may look better. The equal signs or dashes have to begin at the first column. For example: First level header ================== Second level header ------ Other first level header = Since Setext headers start on block boundaries, this means in most situations that they have to be preceded by a blank line. However, blank lines are not necessary after a Setext header: This is a normal paragraph. And A Header ------------ And a paragraph > This is a blockquote. And A Header ------------ However, it is generally a good idea to also use a blank line after a Setext header because it looks more appropriate and eases reading of the document. > The original Markdown syntax allows one to omit the blank line before a Setext header. However, > this leads to ambiguities and makes reading the document harder than necessary. Therefore it is > not allowed in a kramdown document. {: .markdown-difference} An edge case worth mentioning is the following: header --- para One might ask if this represents two paragraphs separated by a [horizontal rule](#horizontal-rules) or a second level header and a paragraph. As suggested by the wording in the example, the latter is the case. The general rule is that Setext headers are processed before horizontal rules. ### atx Style atx style headers have to start on a [block boundary](#block-boundaries) with a line that contains one or more hash characters and then the header text. No spaces are allowed before the hash characters. The number of hash characters specifies the heading level: one hash character gives you a first level heading, two a second level heading and so on until the maximum of six hash characters for a sixth level heading. You may optionally use any number of hashes at the end of the line to close the header. Any leading or trailing spaces are stripped from the header text. For example: # First level header ### Third level header ### ## Second level header ###### > Again, the original Markdown syntax allows one to omit the blank line before an atx style header. {: .markdown-difference} ### Specifying a Header ID kramdown supports a nice way for explicitly setting the header ID which is taken from [PHP Markdown Extra] and [Maruku]: If you follow the header text with an opening curly bracket (separated from the text with a least one space), a hash, the ID and a closing curly bracket, the ID is set on the header. If you use the trailing hash feature of atx style headers, the header ID has to go after the trailing hashes. For example: Hello {#id} ----- # Hello {#id} # Hello # {#id} > This additional syntax is not part of standard Markdown. {: .markdown-difference} ## Blockquotes A blockquote is started using the `>` marker followed by an optional space and the content of the blockquote. The marker itself may be indented up to three spaces. All following lines, whether they are started with the blockquote marker or just contain text, belong to the blockquote because blockquotes support [line wrapping](#line-wrapping). The contents of a blockquote are block-level elements. This means that if you are just using text as content that it will be wrapped in a paragraph. For example, the following gives you one blockquote with two paragraphs in it: > This is a blockquote. > on multiple lines that may be lazy. > > This is the second paragraph. Since the contents of a blockquote are block-level elements, you can nest blockquotes and use other block-level elements (this is also the reason why blockquotes need to support line wrapping): > This is a paragraph. > > > A nested blockquote. > > ## Headers work > > * lists too > > and all other block-level elements Note that the first space character after the `>` marker does *not* count when counting spaces for the indentation of the block-level elements inside the blockquote! So [code blocks](#code-blocks) will have to be indented with five spaces or one space and one tab, like this: > A code block: > > ruby -e 'puts :works' [Line wrapping](#line-wrapping) allows one to be lazy but hinders readability and should therefore be avoided, especially with blockquotes. Here is an example of using blockquotes with line wrapping: > This is a paragraph inside a blockquote. > > > This is a nested paragraph that continues here > and here > > and here ## Code Blocks Code blocks can be used to represent verbatim text like markup, HTML or a program fragment because no syntax is parsed within a code block. ### Standard Code Blocks A code block can be started by using four spaces or one tab and then the text of the code block. All following lines containing text, whether they adhere to this syntax or not, belong to the code block because code blocks support [line wrapping](#line-wrapping)). A wrapped code line is automatically appended to the preceding code line by substituting the line break with a space character. The indentation (four spaces or one tab) is stripped from each line of the code block. > The original Markdown syntax does not allow line wrapping in code blocks. {: .markdown-difference} Note that consecutive code blocks that are only separate by [blank lines](#blank-lines) are merged together into one code block: Here comes some code This text belongs to the same code block. If you want to have one code block directly after another one, you need to use an [EOB marker](#eob-marker) to separate the two: Here comes some code ^ This one is separate. ### Fenced Code Blocks > This alternative syntax is not part of the original Markdown syntax. The idea and syntax comes > from the [PHP Markdown Extra] package. {: .markdown-difference} kramdown also supports an alternative syntax for code blocks which does not use indented blocks but delimiting lines. The starting line needs to begin with three or more tilde characters (`~`) and the closing line needs to have at least the number of tildes the starting line has. Everything between is taken literally as with the other syntax but there is no need for indenting the text. For example: ~~~~~~~~ Here comes some code. ~~~~~~~~ If you need lines of tildes in such a code block, just start the code block with more tildes. For example: ~~~~~~~~~~~~ ~~~~~~~ code with tildes ~~~~~~~~ ~~~~~~~~~~~~~~~~~~ This type of code block is especially useful for copy-pasted code since you don't need to indent the code. ### Language of Code Blocks You can tell kramdown the language of a code block by using an [IAL](#inline-attribute-lists): ~~~ def what? 42 end ~~~ {: .language-ruby} The specially named class `language-ruby` tells kramdown that this code block is written in the Ruby language. Such information can be used, for example, by converters to do syntax highlighting on the code block. Fenced code blocks provide an easier way to specify the language, namely by appending the language of the code block to the end of the starting line: ~~~ ruby def what? 42 end ~~~ ## Lists kramdown provides syntax elements for creating ordered and unordered lists as well as definition lists. ### Ordered and Unordered lists Both ordered and unordered lists follow the same rules. A list is started with a list marker (in case of unordered lists one of `+`, `-` or `*` -- you can mix them -- and in case of ordered lists a number followed by a period) followed by one tab or at least one space, optionally followed by an [IAL](#inline-attribute-lists) that should be applied to the list item and then the first part of the content of the list item. The leading tabs or spaces are stripped away from this first line of content to allow for a nice alignment with the following content of a list item (see below). All following list items with the same marker type (unordered or ordered) are put into the same list. The numbers used for ordered lists are irrelevant, an ordered list always starts at 1. The following gives you an unordered list and an ordered list: * kram + down - now 1. kram 2. down 3. now > The original Markdown syntax allows the markers of ordered and unordered lists to be mixed, the > first marker specifying the list type (ordered or unordered). This is not allowed in kramdown. As > stated, the above example will give you two lists (an unordered and an ordered) in kramdown and > only one unordered list in Markdown. {: .markdown-difference} The first list marker in a list may be indented up to three spaces. The column number of the first non-space character which appears after the list item marker on the same line specifies the indentation that has to be used for the following lines of content of the list item. If there is no such character, the indentation that needs to be used is four spaces or one tab. Indented lines may be followed by lines containing text with any amount of indentation due to [line wrapping](#line-wrapping). Note, however, that in addition to the rules outlined in the section about line wrapping, a list item also ends when a line with another list item marker is encountered -- see the next paragraph. The indentation is stripped from the content and the content (note that the content naturally also contains the content of the line with the item marker) is processed as text containing block-level elements. All other list markers in the list may be indented up to three spaces or the number of spaces used for the indentation of the last list item minus one, whichever number is smaller. For example: * This is the first line. Since the first non-space characters appears in column 3, all other indented lines have to be indented 2 spaces. However, one could be lazy and not indent a line but this is not recommended. * This is the another item of the list. It uses a different number of spaces for indentation which is okay but should generally be avoided. * The list item marker is indented 3 spaces which is allowed but should also be avoided and starts the third list item. Note that the lazy line in the second list item may make you believe that this is a sub-list which it isn't! So avoid being lazy! So, while the above is possible and creates one list with three items, it is not advised to use different (marker and list content) indents for same level list items as well as lazy indentation! It is much better to write such a list in the following way: * This is the first list item bla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla bla * This is the another item of the list. bla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla blabla > The original Markdown syntax also allows you to indent the marker, however, the behaviour of what > happens with the list items is not clearly specified and may surprise you. > > Also, Markdown uses a fixed number of spaces/tabs to indent the lines that belong to a list item! {: .markdown-difference} When using tabs for indenting the content of a list item, remember that tab stops occur at multiples of four for kramdown. Tabs are correctly converted to spaces for calculating the indentation. For example: * Using a tab to indent this line, the tab only counts as three spaces and therefore the overall indentation is four spaces. 1. The tab after the marker counts here as three spaces. Since the indentation of the marker is three spaces and the marker itself takes two characters, the overall indentation needed for the following lines is eight spaces or two tabs. It is clear that you might get unexpected results if you mix tabs and spaces or if you don't have the tab stops set to multiples of four in your editor! Therefore this should be avoided! The content of a list item is made up of either text or block-level elements. Simple list items only contain text like in the above examples. They are not even wrapped in a paragraph tag. If the first list text is followed by one or more blank lines, it will be wrapped in a paragraph tag: * kram * down * now In the above example, the first list item text will be wrapped in a paragraph tag since it is followed by a blank line whereas the second list item contains just text. There is obviously a problem for doing this with the last list item when it contains only text. You can circumvent this by leaving a blank line after the last list item and using an EOB marker: * Not wrapped in a paragraph * Wrapped in a paragraph due to the following blank line. * Also wrapped in a paragraph due to the following blank line and the EOB marker. ^ The text of the last list item is also wrapped in a paragraph tag if *all* other list items contain a proper paragraph as first element. This makes the following use case work like expected, i.e. *all* the list items are wrapped in paragraphs: * First list item * Second list item * Last list item > The original Markdown syntax page specifies that list items which are separated by one or more > blank lines are wrapped in paragraph tags. This means that the first text will also be wrapped in > a paragraph if you have block-level elements in a list which are separated by blank lines. The > above rule is easy to remember and lets you exactly specify when the first list text should be > wrapped in a paragraph. The idea for the above rule comes from the [Pandoc] package. {: .markdown-difference} As seen in the examples above, blank lines between list items are allowed. Since the content of a list item can contain block-level elements, you can do the following: * First item A second paragraph * nested list > blockquote * Second item However, there is a problem when you want to have a code block immediately after a list item. You can use an EOB marker to circumvent this problem: * This is a list item. The second para of the list item. ^ A code block following the list item. You can have any block-level element as first element in a list item. However, as described above, the leading tabs or spaces of the line with the list item marker are stripped away. This leads to a problem when you want to have a code block as first element. The solution to this problem is the following construct: * This is a code block (indentation needs to be 4(1)+4(1) spaces (tabs)). {: .show-whitespaces .ws-lr} Note that the list marker needs to be followed with at least one space or tab! Otherwise the line is not recognized as the start of a list item but interpreted as a paragraph containing the list marker. If you want to have one list directly after another one (both with the same list type, i.e. ordered or unordered), you need to use an EOB marker to separate the two: * List one ^ * List two Since paragraphs support [line wrapping](#line-wrapping), it would usually not be possible to create compact nested list, i.e. a list where the text is not wrapped in paragraphs because there is no blank line but a sub list after it: * This is just text. * this is a sub list item * this is a sub sub list item * This is just text, spanning two lines * this is a nested list item. However, this is an often used syntax and is therefore support by kramdown. If you want to start a paragraph with something that looks like a list item marker, you need to escape it. This is done by escaping the period in an ordered list or the list item marker in an unordered list: 1984\. It was great \- others say that, too! As mentioned at the beginning, an optional IAL for applying attributes to a list item can be used after the list item marker: * {:.cls} This item has the class "cls". Here continues the above paragraph. * This is a normal list item. ### Definition Lists > This syntax feature is not part of the original Markdown syntax. The idea and syntax comes from > the [PHP Markdown Extra] package. {: .markdown-difference} Definition lists allow you to assign one or more definitions to one or more terms. A definition list is started when a normal paragraph is followed by a line with a definition marker (a colon which may be optionally indented up to three spaces), then at least one tab or one space, optionally followed by an [IAL](#inline-attribute-lists) that should be applied to the list item and then the first part of the definition. The line with the definition marker may optionally be separated from the preceding paragraph by a blank line. The leading tabs or spaces are stripped away from this first line of the definition to allow for a nice alignment with the following definition content. Each line of the preceding paragraph is taken to be a term and the lines separately parsed as span-level elements. The following is a simple definition list: kramdown : A Markdown-superset converter Maruku : Another Markdown-superset converter The column number of the first non-space character which appears after a definition marker on the same line specifies the indentation that has to be used for the following lines of the definition. If there is no such character, the indentation that needs to be used is four spaces or one tab. Indented lines may be followed by lines containing text with any amount of indentation due to [line wrapping](#line-wrapping). Note, however, that in addition to the rules outlined in the section about line wrapping, a list item also ends when a line with another definition marker is encountered. The indentation is stripped from the definition and it (note that the definition naturally also contains the content of the line with the definition marker) is processed as text containing block level elements. If there is more than one definition, all other definition markers for the term may be indented up to three spaces or the number of spaces used for the indentation of the last definition minus one, whichever number is smaller. For example: definition term 1 definition term 2 : This is the first line. Since the first non-space characters appears in column 3, all other lines have to be indented 2 spaces (or lazy syntax may be used after an indented line). This tells kramdown that the lines belong to the definition. : This is the another definition for the same term. It uses a different number of spaces for indentation which is okay but should generally be avoided. : The definition marker is indented 3 spaces which is allowed but should also be avoided. So, while the above is possible and creates a definition list with two terms and three definitions for them, it is not advised to use different (definition marker and definition) indents in the same definition list as well as lazy indentation! The definition for a term is made up of text and/or block-level elements. If a definition is *not* preceded by a blank line, the first part of the definition will just be text if it would be a paragraph otherwise: definition term : This definition will just be text because it would normally be a paragraph and the there is no preceding blank line. > although the definition contains other block-level elements : This definition *will* be a paragraph since it is preceded by a blank line. The rules about having any block-level element as first element in a list item also apply to a definition. ## Tables > This syntax feature is not part of the original Markdown syntax. The syntax is based on the one > from the [PHP Markdown Extra] package. {: .markdown-difference} Sometimes one wants to include simple tabular data in a kramdown document for which using a full-blown HTML table is just too much. kramdown supports this with a simple syntax for ASCII tables. Tables can be created with or without a leading pipe character: If the first line of a table contains a pipe character at the start of the line (optionally indented up to three spaces), then all leading pipe characters (i.e. pipe characters that are only preceded by whitespace) are ignored on all table lines. Otherwise they are not ignored and count when dividing a table line into table cells. There are four different line types that can be used in a table: * *Table rows* define the content of a table. A table row is any line that contains at least one pipe character and is not identified as any other type of table line! The table row is divided into individual table cells by pipe characters. An optional trailing pipe character is ignored. Note that literal pipe characters need to be escaped *except* if they occur in code spans or HTML `` elements! Header rows, footer rows and normal rows are all done using these table rows. Table cells can only contain a single line of text, no multi-line text is supported. The text of a table cell is parsed as span-level elements. Here are some example table rows: | First cell|Second cell|Third cell | First | Second | Third | First | Second | | Fourth | * *Separator lines* are used to split the table body into multiple body parts. A separator line is any line that contains only pipes, dashes, pluses, colons and spaces and which contains at least one dash and one pipe character. The pipe and plus characters can be used to visually separate columns although this is not needed. Multiple separator lines after another are treated as one separator line. Here are some example separator lines: |----+----| +----|----+ |---------| |- | :-----: | -|- * The first separator line after at least one table row is treated specially, namely as *header separator line*. It is used to demarcate header rows from normal table rows and/or to set column alignments. All table rows above the header separator line are considered to be header rows. The header separator line can be specially formatted to contain column alignment definitions: An alignment definition consists of an optional space followed by an optional colon, one or more dashes, an optional colon and another optional space. The colons of an alignment definition are used to set the alignment of a column: if there are no colons, the column uses the default alignment, if there is a colon only before the dashes, the column is left aligned, if there are colons before and after the dashes, the column is center aligned and if there is only a colon after the dashes, the column is right aligned. Each alignment definition sets the alignment for one column, the first alignment definition for the first column, the second alignment definition for the second column and so on. Here are some example header separator lines with alignment definitions: |---+---+---| + :-: |:------| ---:| | :-: :- -: - :-: | :- * A *footer separator line* is used to demarcate footer rows from normal table rows. All table rows below the footer separator line are considered to be footer rows. A footer separator line is like a normal separator line except that dashes are replaced by equal signs. A footer separator line may only appear once in a table. If multiple footer separator lines are used in one table, only the last is treated as footer separator line, all others are treated as normal separator lines. Normal separator lines that are used after the footer separator line are ignored. Here are some example footer separator lines: |====+====| +====|====+ |=========| |= Trailing spaces or tabs are ignored in all cases. To simplify table creation and maintenance, header, footer and normal separator lines need not specify the same number of columns as table rows; even `|-` and `|=` are a valid separators. Given the above components, a table is specified by * an optional separator line, * optionally followed by zero, one or more table rows followed by a header separator line, * one or more table rows, optionally interspersed with separator lines, * optionally followed by a footer separator line and zero, one or more table rows and * an optional trailing separator line. Also note * that the first line of a table must not have more than three spaces of indentation before the first non-space character, * that each line of a table needs to have at least one not escaped pipe character so that kramdown recognizes it as a line belonging to the table and * that tables have to start and end on [block boundaries](#block-boundaries)! > The table syntax differs from the one used in [PHP Markdown Extra] as follows: > > * kramdown tables do not need to have a table header. > * kramdown tables can be structured using separator lines. > * kramdown tables can contain a table footer. > * kramdown tables need to be separated from other block-level elements. {: .markdown-difference} Here is an example for a kramdown table with a table header row, two table bodies and a table footer row: |-----------------+------------+-----------------+----------------| | Default aligned |Left aligned| Center aligned | Right aligned | |-----------------|:-----------|:---------------:|---------------:| | First body part |Second cell | Third cell | fourth cell | | Second line |foo | **strong** | baz | | Third line |quux | baz | bar | |-----------------+------------+-----------------+----------------| | Second body | | | | | 2 line | | | | |=================+============+=================+================| | Footer row | | | | |-----------------+------------+-----------------+----------------| The above example table is rather time-consuming to create without the help of an ASCII table editor. However, the table syntax is flexible and the above table could also be written like this: |--- | Default aligned | Left aligned | Center aligned | Right aligned |-|:-|:-:|-: | First body part | Second cell | Third cell | fourth cell | Second line |foo | **strong** | baz | Third line |quux | baz | bar |--- | Second body | 2 line |=== | Footer row ## Horizontal Rules A horizontal rule for visually separating content is created by using three or more asterisks, dashes or underscores (these may not be mixed on a line), optionally separated by spaces or tabs, on an otherwise blank line. The first asterisk, dash or underscore may optionally be indented up to three spaces. The following examples show different possibilities to create a horizontal rule: * * * --- _ _ _ _ --------------- ## Math Blocks > This syntax feature is not part of the original Markdown syntax. The idea comes from the [Maruku] > and [Pandoc] packages. {: .markdown-difference} kramdown has built-in support for block and span-level mathematics written in LaTeX. A math block needs to start and end on [block boundaries](#block-boundaries). It is started using two dollar signs, optionally indented up to three spaces. The math block continues until the next two dollar signs (which may be on the same line or on one of the next lines) that appear at the end of a line, i.e. they may only be followed by whitespace characters. The content of a math block has to be valid LaTeX math. It is always wrapped inside a `\begin{displaymath}...\end{displaymath}` enviroment except if it begins with a `\begin` statement. The following kramdown fragment $$ \begin{align*} & \phi(x,y) = \phi \left(\sum_{i=1}^n x_ie_i, \sum_{j=1}^n y_je_j \right) = \sum_{i=1}^n \sum_{j=1}^n x_i y_j \phi(e_i, e_j) = \\ & (x_1, \ldots, x_n) \left( \begin{array}{ccc} \phi(e_1, e_1) & \cdots & \phi(e_1, e_n) \\ \vdots & \ddots & \vdots \\ \phi(e_n, e_1) & \cdots & \phi(e_n, e_n) \end{array} \right) \left( \begin{array}{c} y_1 \\ \vdots \\ y_n \end{array} \right) \end{align*} $$ renders (using Javascript library [MathJax](http://www.mathjax.org/)) as $$ \begin{align*} & \phi(x,y) = \phi \left(\sum_{i=1}^n x_ie_i, \sum_{j=1}^n y_je_j \right) = \sum_{i=1}^n \sum_{j=1}^n x_i y_j \phi(e_i, e_j) = \\ & (x_1, \ldots, x_n) \left( \begin{array}{ccc} \phi(e_1, e_1) & \cdots & \phi(e_1, e_n) \\ \vdots & \ddots & \vdots \\ \phi(e_n, e_1) & \cdots & \phi(e_n, e_n) \end{array} \right) \left( \begin{array}{c} y_1 \\ \vdots \\ y_n \end{array} \right) \end{align*} $$ Using inline math is also easy: just surround your math content with two dollar signs, like with a math block. If you don't want to start an inline math statement, just escape the dollar signs and they will be treated as simple dollar signs. > **Note** that LaTeX code that uses the pipe symbol `|` in inline math statements may lead to a > line being recognized as a table line. This problem can be avoided by using the `\vert` command > instead of `|`! {:.information} If you have a paragraph that looks like a math block but should actually be a paragraph with just an inline math statement, you need to escape the first dollar sign: The following is a math block: $$ 5 + 5 $$ But next comes a paragraph with an inline math statement: \$$ 5 + 5 $$ If you don't even want the inline math statement, escape the first two dollar signs: \$\$ 5 + 5 $$ ## HTML Blocks > The original Markdown syntax specifies that an HTML block must start at the left margin, i.e. no > indentation is allowed. Also, the HTML block has to be surrounded by blank lines. Both > restrictions are lifted for kramdown documents. Additionally, the original syntax does not allow > you to use Markdown syntax in HTML blocks which is allowed with kramdown. {: .markdown-difference} An HTML block is potentially started if a line is encountered that begins with a non-span-level HTML tag or a general XML tag (opening or closing) which may be indented up to three spaces. The following HTML tags count as span-level HTML tags and *won't* start an HTML block if found at the beginning of an HTML block line: a abbr acronym b big bdo br button cite code del dfn em i img input ins kbd label option q rb rbc rp rt rtc ruby samp select small span strong sub sup textarea tt var Further parsing of a found start tag depends on the tag and in which of three possible ways its content is parsed: * Parse as raw HTML block: If the HTML/XML tag content should be handled as raw HTML, then only HTML/XML tags are parsed from this point onwards and text is handled as raw, unparsed text until the matching end tag is found or until the end of the document. Each found tag will be parsed as raw HTML again. However, if a tag has a `markdown` attribute, this attribute controls parsing of this one tag (see below). Note that the parser basically supports only correct XHTML! However, there are some exceptions. For example, attributes without values (i.e. boolean attributes) are also supported and elements without content like `
` can be written as `
`. If an invalid closing tag is found, it is ignored. * Parse as block-level elements: If the HTML/XML tag content should be parsed as text containing block-level elements, the remaining text on the line will be parsed by the block-level parser as if it appears on a separate line (**Caution**: This also means that if the line consists of the start tag, text and the end tag, the end tag will not be found!). All following lines are parsed as block-level elements until an HTML block line with the matching end tag is found or until the end of the document. * Parse as span-level elements: If the HTML/XML tag content should be parsed as text containing span level elements, then all text until the *next* matching end tag or until the end of the document will be the content of the tag and will later be parsed by the span-level parser. This also means that if the matching end tag is inside what appears to be a code span, it is still used! If there is text after an end tag, it will be parsed as if it appears on a separate line except when inside a raw HTML block. Also, if an invalid closing tag is found, it is ignored. Note that all HTML tag and attribute names are converted to lowercase! By default, kramdown parses all block HTML tags and all XML tags as raw HTML blocks. However, this can be configured with the `parse_block_html`. If this is set to `true`, then syntax parsing in HTML blocks is globally enabled. It is also possible to enable/disable syntax parsing on a tag per tag basis using the `markdown` attribute: * If an HTML tag has an attribute `markdown="0"`, then the tag is parsed as raw HTML block. * If an HTML tag has an attribute `markdown="1"`, then the default mechanism for parsing syntax in this tag is used. * If an HTML tag has an attribute `markdown="block"`, then the content of the tag is parsed as block level elements. * If an HTML tag has an attribute `markdown="span"`, then the content of the tag is parsed as span level elements. The following list shows which HTML tags are parsed in which mode by default when `markdown="1"` is applied or `parse_block_html` is `true`: Parse as raw HTML : script style math option textarea pre code kbd samp var Also, all general XML tags are parsed as raw HTML blocks. Parse as block-level elements : applet button blockquote body colgroup dd div dl fieldset form iframe li map noscript object ol table tbody thead tfoot tr td ul Parse as span-level elements : a abbr acronym address b bdo big cite caption code del dfn dt em h1 h2 h3 h4 h5 h6 i ins kbd label legend optgroup p pre q rb rbc rp rt rtc ruby samp select small span strong sub sup th tt var > Remember that all span-level HTML tags like `a` or `b` do not start a HTML block! However, the > above lists also include span-level HTML tags in the case the `markdown` attribute is used on a > tag inside a raw HTML block. Here is a simple example input and its HTML output with `parse_block_html` set to `false`: This is a para.
Something in here.
Other para. ^

This is a para.

Something in here.

Other para.

As one can see the content of the `div` tag will be parsed as raw HTML block and left alone. However, if the `markdown="1"` attribute was used on the `div` tag, the content would be parsed as block-level elements and therefore converted to a paragraph. You can also use several HTML tags at once:
This is some text in the `layer1` div.
This is some text in the `layers` div.
This is a para outside the HTML block. However, remember that if the content of a tag is parsed as block-level elements, the content that appears after a start/end tag but on the same line, is processed as if it appears on a new line:
This is the first part of a para, which is continued here.

This works without problems because it is parsed as span-level elements

The end tag is not found because this line is parsed as a paragraph
Since setting `parse_block_html` to `true` can lead to some not wanted behaviour, it is generally better to selectively enable or disable block/span-level elements parsing by using the `markdown` attribute! Unclosed block-level HTML tags are correctly closed at the end of the document to ensure correct nesting and invalidly used end tags are removed from the output: This is a para.
Another para.

^

This is a para.

Another para.

The parsing of processing instructions and XML comments is also supported. The content of both, PIs and XML comments, may span multiple lines. The start of a PI/XML comment may only appear at the beginning of a line, optionally indented up to three spaces. If there is text after the end of a PI or XML comment, it will be parsed as if it appears on a separate line. kramdown syntax in PIs/XML comments is not processed: This is a para. First part of para, continues here. # Text Markup These elements are all span-level elements and used inside block-level elements to markup text fragments. For example, one can easily create links or apply emphasis to certain text parts. Note that empty span-level elements are not converted to empty HTML tags but are copied as-is to the output. ## Links and Images Three types of links are supported: automatic links, inline links and reference links. ### Automatic Links This is the easiest one to create: Just surround a web address or an email address with angle brackets and the address will be turned into a proper link. The address will be used as link target and as link text. For example: Information can be found on the homepage. You can also mail me: It is not possible to specify a different link text using automatic links -- use the other link types for this! ### Inline Links As the wording suggests, inline links provide all information inline in the text flow. Reference style links only provide the link text in the text flow and everything else is defined elsewhere. This also allows you to reuse link definitions. An inline style link can be created by surrounding the link text with square brackets, followed immediately by the link URL (and an optional title in single or double quotes preceded by at least one space) in normal parentheses. For example: This is [a link](http://rubyforge.org) to a page. A [link](../test "local URI") can also have a title. And [spaces](link with spaces.html)! Notes: * The link text is treated like normal span-level text and therefore is parsed and converted. However, if you use square brackets within the link text, you have to either properly nest them or to escape them. It is not possible to create nested links! The link text may also be omitted, e.g. for creating link anchors. * The link URL has to contain properly nested parentheses if no title is specified, or the link URL must be contained in angle brackets (incorrectly nested parentheses are allowed). * The link title may not contain its delimiters and may not be empty. * Additional link attributes can be added by using a [span IAL](#span-ials) after the inline link, for example: This is a [link](http://example.com){:hreflang="de"} ### Reference Links To create a reference style link, you need to surround the link text with square brackets (as with inline links), followed by optional spaces/tabs/line breaks and then optionally followed with another set of square brackets with the link identifier in them. A link identifier may not contain a closing bracket and, when specified in a link definition, newline characters; it is also not case sensitive, line breaks and tabs are converted to spaces and multiple spaces are compressed into one. For example: This is a [reference style link][linkid] to a page. And [this] [linkid] is also a link. As is [this][] and [THIS]. If you don't specify a link identifier (i.e. only use empty square brackets) or completely omit the second pair of square brackets, the link text is converted to a valid link identifier by removing all invalid characters and inserting spaces for line breaks. If there is a link definition found for the link identifier, a link will be created. Otherwise the text is not converted to a link. As with inline links, additional link attributes can be added by using a [span IAL](#span-ials) after the reference link. ### Link Definitions The link definition can be put anywhere in the document. It does not appear in the output. A link definition looks like this: [linkid]: http://www.example.com/ "Optional Title" > Link definitions are, despite being described here, non-content block-level elements. {: .information} The link definition has the following structure: * The link identifier in square brackets, optionally indented up to three spaces, * then a colon and one or more optional spaces/tabs, * then the link URL which must contain at least one non-space character, or a left angle bracket, the link URL and a right angle bracket, * then optionally the title in single or double quotes, separated from the link URL by one or more spaces or on the next line by itself indented any number of spaces/tabs. > The original Markdown syntax also allowed the title to be specified in parenthesis. This is not > allowed for consistency with the inline title. {: .markdown-difference} If you have some text that looks like a link definition but should really be a link and some text, you can escape the colon after the link identifier: The next paragraph contains a link and some text. [Room 100]\: There you should find everything you need! [Room 100]: link_to_room_100.html Although link definitions are non-content block-level elements, [block IALs](#block-ials) can be used on them to specify additional attributes for the links: [linkid]: http://example.com {:hreflang="de"} ### Images Images can be specified via a syntax that is similar to the one used by links. The difference is that you have to use an exclamation mark before the first square bracket and that the link text of a normal link becomes the alternative text of the image link. As with normal links, image links can be written inline or reference style. For example: Here comes a ![smiley](../images/smiley.png)! And here ![too](../images/other.png 'Title text'). Or ![here]. With empty alt text ![](see.jpg) The link definition for images is exactly the same as the link definition for normal links. Since additional attributes can be added via span and block IALs, it is possible, for example, to specify image width and height: Here is an inline ![smiley](smiley.png){:height="36px" width="36px"}. And here is a referenced ![smile] [smile]: smile.png {: height="36px" width="36px"} ## Emphasis kramdown supports two types of emphasis: light and strong emphasis. Text parts that are surrounded with single asterisks `*` or underscores `_` are treated as text with light emphasis, text parts surrounded with two asterisks or underscores are treated as text with strong emphasis. Surrounded means that the starting delimiter must not be followed by a space and that the stopping delimiter must not be preceded by a space. Here is an example for text with light and strong emphasis: *some text* _some text_ **some text** __some text__ The asterisk form is also allowed within a single word: This is un*believe*able! This d_oe_s not work! Text can be marked up with both light and strong emphasis, possibly using different delimiters. However, it is not possible to nest strong within strong or light within light emphasized text: This is a ***text with light and strong emphasis***. This **is _emphasized_ as well**. This *does _not_ work*. This **does __not__ work either**. If one or two asterisks or underscores are surrounded by spaces, they are treated literally. If you want to force the literal meaning of an asterisk or an underscore you can backslash-escape it: This is a * literal asterisk. These are ** two literal asterisk. As \*are\* these! ## Code Spans This is the span-level equivalent of the [code block](#code-blocks) element. You can markup a text part as code span by surrounding it with backticks `` ` ``. For example: Use `` tags for this. Note that all special characters in a code span are treated correctly. For example, when a code span is converted to HTML, the characters `<`, `>` and `&` are substituted by their respective HTML counterparts. To include a literal backtick in a code span, you need to use two or more backticks as delimiters. You can insert one optional space after the starting and before the ending delimiter (these spaces are not used in the output). For example: Here is a literal `` ` `` backtick. And here is `` `some` `` text (note the two spaces so that one is left in the output!). A single backtick surrounded by spaces is treated as literal backtick. If you want to force the literal meaning of a backtick you can backslash-escape it: This is a ` literal backtick. As \`are\` these! As with [code blocks](#language-of-code-blocks) you can set the language of a code span by using an [IAL](#inline-attribute-lists): This is a Ruby code fragment `x = Class.new`{:.language-ruby} ## HTML Spans HTML tags cannot only be used on the block-level but also on the span-level. Span-level HTML tags can only be used inside one block-level element, it is not possible to use a start tag in one block level element and the end tag in another. Note that only correct XHTML is supported! This means that you have to use, for example, `
` instead of `
` (although kramdown tries to fix such errors if possible). By default, kramdown parses kramdown syntax inside span HTML tags. However, this behaviour can be configured with the `parse_span_html` option. If this is set to `true`, then syntax parsing in HTML spans is enabled, if it is set to `false`, parsing is disabled. It is also possible to enable/disable syntax parsing on a tag per tag basis using the `markdown` attribute: * If an HTML tag has an attribute `markdown="0"`, then no parsing (except parsing of HTML span tags) is done inside that HTML tag. * If an HTML tag has an attribute `markdown="1"`, then the content of the tag is parsed as span level elements. * If an HTML tag has an attribute `markdown="block"`, then a warning is issued because HTML spans cannot contain block-level elements and the attribute is ignored. * If an HTML tag has an attribute `markdown="span"`, then the content of the tag is parsed as span level elements. The content of a span-level HTML tag is normally parsed as span-level elements. Note, however, that some tags like `