diff --git a/test/functional/wiki_controller_test.rb b/test/functional/wiki_controller_test.rb index 9d67db89..ac6a72e3 100644 --- a/test/functional/wiki_controller_test.rb +++ b/test/functional/wiki_controller_test.rb @@ -955,7 +955,7 @@ class WikiControllerTest < ActionController::TestCase end def test_recursive_include - @wiki.write_page('wiki1', 'HomePage', 'Self-include: [[!include HomePage]]', Time.now, + @wiki.write_page('wiki1', 'HomePage', "Self-include:\n\n [[!include HomePage]] ", Time.now, Author.new('AnotherAuthor', '127.0.0.2'), x_test_renderer) r = process('show', 'id' => 'HomePage', 'web' => 'wiki1') diff --git a/vendor/plugins/maruku/data/entities.xml b/vendor/plugins/maruku/data/entities.xml new file mode 100644 index 00000000..cc72ca55 --- /dev/null +++ b/vendor/plugins/maruku/data/entities.xml @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vendor/plugins/maruku/lib/maruku.rb b/vendor/plugins/maruku/lib/maruku.rb index 7e5e9b73..8407a089 100644 --- a/vendor/plugins/maruku/lib/maruku.rb +++ b/vendor/plugins/maruku/lib/maruku.rb @@ -1,78 +1,68 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ + +dir = File.dirname(__FILE__) +$LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir) require 'rexml/document' -# :include:MaRuKu.txt module MaRuKu + module In + module Markdown + module SpanLevelParser; end + module BlockLevelParser; end + end + end - module In - module Markdown - module SpanLevelParser; end - module BlockLevelParser; end - end - # more to come? - end + module Out + module Markdown; end + module HTML; end + module Latex; end + end - module Out - # Functions for exporting to MarkDown. - module Markdown; end - # Functions for exporting to HTML. - module HTML; end - # Functions for exporting to Latex - module Latex; end - end - - # These are strings utilities. - module Strings; end + module Strings; end - module Helpers; end + module Helpers; end - module Errors; end - - class MDElement - include REXML - include MaRuKu - include Out::Markdown - include Out::HTML - include Out::Latex - include Strings - include Helpers - include Errors - end - - - class MDDocument < MDElement - include In::Markdown - include In::Markdown::SpanLevelParser - include In::Markdown::BlockLevelParser - end + module Errors; end + + class MDElement + include REXML + include MaRuKu + include Out::Markdown + include Out::HTML + include Out::Latex + include Strings + include Helpers + include Errors + end + + + class MDDocument < MDElement + include In::Markdown + include In::Markdown::SpanLevelParser + include In::Markdown::BlockLevelParser + end end -# This is the public interface class Maruku < MaRuKu::MDDocument; end - -require 'rexml/document' - # Structures definition require 'maruku/structures' require 'maruku/structures_inspect' @@ -106,7 +96,7 @@ require 'maruku/attributes' require 'maruku/structures_iterators' -require 'maruku/errors_management' +require 'maruku/errors' # Code for creating a table of contents require 'maruku/toc' @@ -140,4 +130,3 @@ require 'maruku/output/to_s' # class Maruku is the global interface require 'maruku/maruku' - diff --git a/vendor/plugins/maruku/lib/maruku/attic/parse_span.rb.txt b/vendor/plugins/maruku/lib/maruku/attic/parse_span.rb.txt deleted file mode 100644 index 71c57711..00000000 --- a/vendor/plugins/maruku/lib/maruku/attic/parse_span.rb.txt +++ /dev/null @@ -1,462 +0,0 @@ -# Copyright (C) 2006 Andrea Censi -# -# This file is part of Maruku. -# -# Maruku is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Maruku is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Maruku; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - - - -# NOTE: this is the old span-level regexp-based parser. -# -# The new parser is a real parser and is defined with functions in parse_span_better.rb -# The new parser is faster, handles syntax errors, but it's absolutely not readable. -# -# Also, regexp parsers simply CANNOT handle inline HTML properly. - - - -# There are two black-magic methods `match_couple_of` and `map_match`, -# defined at the end of the file, that make the function -# `parse_lines_as_span` so elegant. - -class Maruku - - # Takes care of all span-level formatting, links, images, etc. - # - # Lines must not contain block-level elements. - def parse_lines_as_span(lines) - - # first, get rid of linebreaks - res = resolve_linebreaks(lines) - - span = MDElement.new(:dummy, res) - - # encode all escapes - span.replace_each_string { |s| s.escape_md_special } - - -# The order of processing is significant: -# 1. inline code -# 2. immediate links -# 3. inline HTML -# 4. everything else - - # search for ``code`` markers - span.match_couple_of('``') { |children, match1, match2| - e = create_md_element(:inline_code) - # this is now opaque to processing - e.meta[:raw_code] = children.join('').it_was_a_code_block - e - } - - # Search for `single tick` code markers - span.match_couple_of('`') { |children, match1, match2| - e = create_md_element(:inline_code) - # this is now opaque to processing - e.meta[:raw_code] = children.join('').it_was_a_code_block - # this is now opaque to processing - e - } - - # Detect any immediate link: - # we expect an http: or something: at the beginning - span.map_match( /<(\w+:[^\>]+)>/) { |match| - url = match[1] - - e = create_md_element(:immediate_link, []) - e.meta[:url] = url - e - } - - # Search for inline HTML (the support is pretty basic for now) - - # this searches for a matching block - inlineHTML1 = %r{ - ( # put everything in 1 - < # open - (\w+) # opening tag in 2 - > # close - .* # anything - # match closing tag - ) - }x - - # this searches for only one block - inlineHTML2 = %r{ - ( # put everything in 1 - < # open - \w+ # - # close - [^<>]* # anything except - /> # closing tag - ) - }x - - for reg in [inlineHTML1, inlineHTML2] - span.map_match(reg) { |match| - raw_html = match[1] - convert_raw_html_in_list(raw_html) - } - end - - # Detect footnotes references: [^1] - span.map_match(/\[(\^[^\]]+)\]/) { |match| - id = match[1].strip.downcase - e = create_md_element(:footnote_reference) - e.meta[:footnote_id] = id - e - } - - # Detect any image like ![Alt text][url] - span.map_match(/\!\[([^\]]+)\]\s?\[([^\]]*)\]/) { |match| - alt = match[1] - id = match[2].strip.downcase - - if id.size == 0 - id = text.strip.downcase - end - - e = create_md_element(:image) - e.meta[:ref_id] = id - e - } - - # Detect any immage with immediate url: ![Alt](url "title") - # a dummy ref is created and put in the symbol table - link1 = /!\[([^\]]+)\]\s?\(([^\s\)]*)(?:\s+["'](.*)["'])?\)/ - span.map_match(link1) { |match| - alt = match[1] - url = match[2] - title = match[3] - - url = url.strip - # create a dummy id - id="dummy_#{@refs.size}" - @refs[id] = {:url=>url, :title=>title} - - e = create_md_element(:image) - e.meta[:ref_id] = id - e - } - - # an id reference: "[id]", "[ id ]" - reg_id_ref = %r{ - \[ # opening bracket - ([^\]]*) # 0 or more non-closing bracket (this is too permissive) - \] # closing bracket - }x - - - # validates a url, only $1 is set to the url - reg_url = - /((?:\w+):\/\/(?:\w+:{0,1}\w*@)?(?:\S+)(?::[0-9]+)?(?:\/|\/([\w#!:.?+=&%@!\-\/]))?)/ - reg_url = %r{([^\s\]\)]+)} - - # A string enclosed in quotes. - reg_title = %r{ - " # opening - [^"]* # anything = 1 - " # closing - }x - - # [bah](http://www.google.com "Google.com"), - # [bah](http://www.google.com), - # [empty]() - reg_url_and_title = %r{ - \( # opening - \s* # whitespace - #{reg_url}? # url = 1 might be empty - (?:\s+["'](.*)["'])? # optional title = 2 - \s* # whitespace - \) # closing - }x - - # Detect a link like ![Alt text][id] - span.map_match(/\[([^\]]+)\]\s?\[([^\]]*)\]/) { |match| - text = match[1] - id = match[2].strip.downcase - - if id.size == 0 - id = text.strip.downcase - end - - children = parse_lines_as_span(text) - e = create_md_element(:link, children) - e.meta[:ref_id] = id - e - } - - # Detect any immage with immediate url: ![Alt](url "title") - # a dummy ref is created and put in the symbol table - link1 = /!\[([^\]]+)\]\s?\(([^\s\)]*)(?:\s+["'](.*)["'])?\)/ - span.map_match(link1) { |match| - text = match[1] - children = parse_lines_as_span(text) - - url = match[2] - title = match[3] - - url = url.strip - # create a dummy id - id="dummy_#{@refs.size}" - @refs[id] = {:url=>url, :title=>title} - @refs[id][:title] = title if title - - e = create_md_element(:link, children) - e.meta[:ref_id] = id - e - } - - - # Detect any link like [Google engine][google] - span.match_couple_of('[', # opening bracket - %r{\] # closing bracket - [ ]? # optional whitespace - #{reg_id_ref} # ref id, with $1 being the reference - }x - ) { |children, match1, match2| - id = match2[1] - id = id.strip.downcase - - if id.size == 0 - id = children.join.strip.downcase - end - - e = create_md_element(:link, children) - e.meta[:ref_id] = id - e - } - - # Detect any link with immediate url: [Google](http://www.google.com) - # XXX Note that the url can be empty: [Empty]() - # a dummy ref is created and put in the symbol table - span.match_couple_of('[', # opening bracket - %r{\] # closing bracket - [ ]? # optional whitespace - #{reg_url_and_title} # ref id, with $1 being the url and $2 being the title - }x - ) { |children, match1, match2| - - url = match2[1] - title = match2[3] # XXX? Is it a bug? I would use [2] - - # create a dummy id - id="dummy_#{@refs.size}" - @refs[id] = {:url=>url} - @refs[id][:title] = title if title - - e = create_md_element(:link, children) - e.meta[:ref_id] = id - e - } - - # Detect an email address - span.map_match(EMailAddress) { |match| - email = match[1] - e = create_md_element(:email_address, []) - e.meta[:email] = email - e - } - - # Detect HTML entitis - span.map_match(/&([\w\d]+);/) { |match| - entity_name = match[1] - - e = create_md_element(:entity, []) - e.meta[:entity_name] = entity_name - e - } - - - # And now the easy stuff - - # search for ***strong and em*** - span.match_couple_of('***') { |children,m1,m2| - create_md_element(:strong, [create_md_element(:emphasis, children)] ) } - - span.match_couple_of('___') { |children,m1,m2| - create_md_element(:strong, [create_md_element(:emphasis, children)] ) } - - # search for **strong** - span.match_couple_of('**') { |children,m1,m2| create_md_element(:strong, children) } - - # search for __strong__ - span.match_couple_of('__') { |children,m1,m2| create_md_element(:strong, children) } - - # search for *emphasis* - span.match_couple_of('*') { |children,m1,m2| create_md_element(:emphasis, children) } - - # search for _emphasis_ - span.match_couple_of('_') { |children,m1,m2| create_md_element(:emphasis, children) } - - # finally, unescape the special characters - span.replace_each_string { |s| s.unescape_md_special} - - span.children - end - - # returns array containing Strings or :linebreak elements - def resolve_linebreaks(lines) - res = [] - s = "" - lines.each do |l| - s += (s.size>0 ? " " : "") + l.strip - if force_linebreak?(l) - res << s - res << create_md_element(:linebreak) - s = "" - end - end - res << s if s.size > 0 - res - end - - # raw_html is something like - # A dopwkk *maruk* A - def convert_raw_html_in_list(raw_html) - e = create_md_element(:raw_html) - e.meta[:raw_html] = raw_html - begin - e.meta[:parsed_html] = Document.new(raw_html) - rescue - $stderr.puts "convert_raw_html_in_list Malformed HTML:\n#{raw_html}" - end - e - end - -end - -# And now the black magic that makes the part above so elegant -class MDElement - - # Try to match the regexp to each string in the hierarchy - # (using `replace_each_string`). If the regexp match, eliminate - # the matching string and substitute it with the pre_match, the - # result of the block, and the post_match - # - # ..., matched_string, ... -> ..., pre_match, block.call(match), post_match - # - # the block might return arrays. - # - def map_match(regexp, &block) - replace_each_string { |s| - processed = [] - while (match = regexp.match(s)) - # save the pre_match - processed << match.pre_match if match.pre_match && match.pre_match.size>0 - # transform match - result = block.call(match) - # and append as processed - [*result].each do |e| processed << e end - # go on with the rest of the string - s = match.post_match - end - processed << s if s.size > 0 - processed - } - end - - # Finds couple of delimiters in a hierarchy of Strings and MDElements - # - # Open and close are two delimiters (like '[' and ']'), or two Regexp. - # - # If you don't pass close, it defaults to open. - # - # Each block is called with |contained children, match1, match2| - def match_couple_of(open, close=nil, &block) - close = close || open - open_regexp = open.kind_of?(Regexp) ? open : Regexp.new(Regexp.escape(open)) - close_regexp = close.kind_of?(Regexp) ? close : Regexp.new(Regexp.escape(close)) - - # Do the same to children first - for c in @children; if c.kind_of? MDElement - c.match_couple_of(open_regexp, close_regexp, &block) - end end - - processed_children = [] - - until @children.empty? - c = @children.shift - if c.kind_of? String - match1 = open_regexp.match(c) - if not match1 - processed_children << c - else # we found opening, now search closing -# puts "Found opening (#{marker}) in #{c.inspect}" - # pre match is processed - processed_children.push match1.pre_match if - match1.pre_match && match1.pre_match.size > 0 - # we will process again the post_match - @children.unshift match1.post_match if - match1.post_match && match1.post_match.size>0 - - contained = []; found_closing = false - until @children.empty? || found_closing - c = @children.shift - if c.kind_of? String - match2 = close_regexp.match(c) - if not match2 - contained << c - else - # we found closing - found_closing = true - # pre match is contained - contained.push match2.pre_match if - match2.pre_match && match2.pre_match.size>0 - # we will process again the post_match - @children.unshift match2.post_match if - match2.post_match && match2.post_match.size>0 - - # And now we call the block - substitute = block.call(contained, match1, match2) - processed_children << substitute - -# puts "Found closing (#{marker}) in #{c.inspect}" -# puts "Children: #{contained.inspect}" -# puts "Substitute: #{substitute.inspect}" - end - else - contained << c - end - end - - if not found_closing - # $stderr.puts "##### Could not find closing for #{open}, #{close} -- ignoring" - processed_children << match1.to_s - contained.reverse.each do |c| - @children.unshift c - end - end - end - else - processed_children << c - end - end - - raise "BugBug" unless @children.empty? - - rebuilt = [] - # rebuild strings - processed_children.each do |c| - if c.kind_of?(String) && rebuilt.last && rebuilt.last.kind_of?(String) - rebuilt.last << c - else - rebuilt << c - end - end - @children = rebuilt - end -end diff --git a/vendor/plugins/maruku/lib/maruku/attributes.rb b/vendor/plugins/maruku/lib/maruku/attributes.rb index 71dd1c6a..a1f901cd 100644 --- a/vendor/plugins/maruku/lib/maruku/attributes.rb +++ b/vendor/plugins/maruku/lib/maruku/attributes.rb @@ -1,175 +1,138 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ -class String - def quote_if_needed - if /[\s\'\"]/.match self - inspect - else - self - end - end +module MaRuKu + # This represents a list of attributes specified in the Markdown document + # that apply to a Markdown-generated tag. + # What was `{#id .class key="val" ref}` in the Markdown + # is parsed into `[[:id, 'id'], [:class, 'id'], ['key', 'val'], [:ref, 'ref']]`. + class AttributeList < Array + def to_s + map do |k, v| + case k + when :id; "#" + quote_if_needed(v) + when :class; "." + quote_if_needed(v) + when :ref; quote_if_needed(v) + else quote_if_needed(k) + "=" + quote_if_needed(v) + end + end.join(' ') + end + alias to_md to_s + + private + + def quote_if_needed(str) + return str unless str =~ /[\s'"]/ + str.inspect + end + end + + module In::Markdown::SpanLevelParser + def md_al(s = []); AttributeList.new(s); end + + # @return [AttributeList, nil] + def read_attribute_list(src, con, break_on_chars) + separators = break_on_chars + [?=, ?\s, ?\t] + escaped = Maruku::EscapedCharInQuotes + + al = AttributeList.new + loop do + src.consume_whitespace + break if break_on_chars.include? src.cur_char + + case src.cur_char + when nil + maruku_error "Attribute list terminated by EOF:\n #{al.inspect}", src, con + tell_user "Returning partial attribute list:\n #{al.inspect}" + break + when ?= # error + src.ignore_char + maruku_error "In attribute lists, cannot start identifier with `=`." + tell_user "Ignoring and continuing." + when ?# # id definition + src.ignore_char + if id = read_quoted_or_unquoted(src, con, escaped, separators) + al << [:id, id] + else + maruku_error 'Could not read `id` attribute.', src, con + tell_user 'Ignoring bad `id` attribute.' + end + when ?. # class definition + src.ignore_char + if klass = read_quoted_or_unquoted(src, con, escaped, separators) + al << [:class, klass] + else + maruku_error 'Could not read `class` attribute.', src, con + tell_user 'Ignoring bad `class` attribute.' + end + else + unless key = read_quoted_or_unquoted(src, con, escaped, separators) + maruku_error 'Could not read key or reference.' + next + end + + if src.cur_char != ?= + al << [:ref, key] + next + end + + src.ignore_char # skip the = + if val = read_quoted_or_unquoted(src, con, escaped, separators) + al << [key, val] + else + maruku_error "Could not read value for key #{key.inspect}.", src, con + tell_user "Ignoring key #{key.inspect}" + end + end + end + al + end + + def merge_ial(elements, src, con) + # Apply each IAL to the element before + (elements + [nil]).each_cons(3) do |before, e, after| + next unless ial?(e) + + if before.kind_of? MDElement + before.al = e.ial + elsif after.kind_of? MDElement + after.al = e.ial + else + maruku_error <= 1 then - before = elements[i-1] - after = elements[i+1] - if before.kind_of? MDElement - before.al = e.ial - elsif after.kind_of? MDElement - after.al = e.ial - else - maruku_error "It is not clear to me what element this IAL {:#{e.ial.to_md}} \n"+ - "is referring to. The element before is a #{before.class.to_s}, \n"+ - "the element after is a #{after.class.to_s}.\n"+ - "\n before: #{before.inspect}"+ - "\n after: #{after.inspect}", - src, con - # xxx dire se c'รจ empty vicino - end - end - end - - if not Globals[:debug_keep_ials] - elements.delete_if {|x| is_ial(x) unless x == elements.first} - end - end - -end end end end -#module MaRuKu; module In; module Markdown; module SpanLevelParser diff --git a/vendor/plugins/maruku/lib/maruku/defaults.rb b/vendor/plugins/maruku/lib/maruku/defaults.rb index 7e1ce2a0..b0203b02 100644 --- a/vendor/plugins/maruku/lib/maruku/defaults.rb +++ b/vendor/plugins/maruku/lib/maruku/defaults.rb @@ -1,71 +1,64 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ module MaRuKu - -Globals = { - :unsafe_features => false, - :on_error => :warning, - - - :use_numbered_headers => false, - - :maruku_signature => false, - :code_background_color => '#fef', - :code_show_spaces => false, - - :filter_html => false, - - :html_math_output_mathml => true, # also set :html_math_engine - :html_math_engine => 'itex2mml', #ritex, itex2mml, none - - :html_math_output_png => false, - :html_png_engine => 'none', - :html_png_dir => 'pngs', - :html_png_url => 'pngs/', - :html_png_resolution => 200, - - :html_use_syntax => true, - - :latex_use_listings => false, - :latex_cjk => false, - :latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter - - :debug_keep_ials => false, - :doc_prefix => '' -} -class MDElement - def get_setting(sym) - if self.attributes.has_key?(sym) then - return self.attributes[sym] - elsif self.doc && self.doc.attributes.has_key?(sym) then - return self.doc.attributes[sym] - elsif MaRuKu::Globals.has_key?(sym) - return MaRuKu::Globals[sym] - else - $stderr.puts "Bug: no default for #{sym.inspect}" - nil - end - end -end + Globals = { + :unsafe_features => false, + :on_error => :warning, + + :use_numbered_headers => false, + + :maruku_signature => false, + :code_background_color => '#fef', + :code_show_spaces => false, + + :filter_html => false, + + :html_math_output_mathml => true, # also set :html_math_engine + :html_math_engine => 'itex2mml', #ritex, itex2mml, none + + :html_math_output_png => false, + :html_png_engine => 'none', + :html_png_dir => 'pngs', + :html_png_url => 'pngs/', + :html_png_resolution => 200, + + :html_use_syntax => true, + + :latex_use_listings => false, + :latex_cjk => false, + :latex_cache_file => "blahtex_cache.pstore", # cache file for blahtex filter + + :debug_keep_ials => false, + :doc_prefix => '' + } + + class MDElement + def get_setting(sym) + return attributes[sym] if attributes.has_key?(sym) + return doc.attributes[sym] if doc && doc.attributes.has_key?(sym) + return MaRuKu::Globals[sym] if MaRuKu::Globals.has_key?(sym) + + $stderr.puts "Bug: no default for #{sym.inspect}" + nil + end + end end diff --git a/vendor/plugins/maruku/lib/maruku/errors.rb b/vendor/plugins/maruku/lib/maruku/errors.rb new file mode 100644 index 00000000..bbdcc102 --- /dev/null +++ b/vendor/plugins/maruku/lib/maruku/errors.rb @@ -0,0 +1,89 @@ +# Copyright (C) 2006 Andrea Censi +# +# This file is part of Maruku. +# +# Maruku is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Maruku is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Maruku; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +module MaRuKu + class Exception < RuntimeError; end + + module Errors + FRAME_WIDTH = 75 + + # Properly handles a formatting error. + # All such errors go through this method. + # + # The behavior depends on {MaRuKu::Globals `MaRuKu::Globals[:on_error]`}. + # If this is `:warning`, this prints the error to stderr + # (or `@error_stream if` it's defined) and tries to continue. + # If `:on_error` is `:ignore`, this doesn't print anything + # and tries to continue. If it's `:raise`, this raises a {MaRuKu::Exception}. + # + # By default, `:on_error` is set to `:warning`. + # + # @overload def maruku_error(s, src = nil, con = nil) + # @param s [String] The text of the error + # @param src [#describe, nil] The source of the error + # @param con [#describe, nil] The context of the error + # @raise [MaRuKu::Exception] If `:on_error` is set to `:raise` + def maruku_error(*args) + policy = get_setting(:on_error) + + case policy + when :ignore + when :raise + raise_error create_frame(describe_error(*args)) + when :warning + tell_user create_frame(describe_error(*args)) + else + raise "Unknown on_error policy: #{policy.inspect}" + end + end + + def maruku_recover(*args) + tell_user create_frame(describe_error(*args)) + end + alias error maruku_error + + def raise_error(s) + raise MaRuKu::Exception, s, caller + end + + def tell_user(s) + (self.attributes[:error_stream] || $stderr) << s + end + + private + + def create_frame(s) + "\n" + < -# -# This file is part of Maruku. -# -# Maruku is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Maruku is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Maruku; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ - - - -#m Any method that detects formatting error calls the -#m maruku_error() method. -#m if @meta[:on_error] == -#m -#m - :warning write on the standard err (or @error_stream if defined), -#m then do your best. -#m - :ignore be shy and try to continue -#m - :raise raises a MarukuException -#m -#m default is :raise - -module MaRuKu - - class Exception < RuntimeError - end - -module Errors - - def maruku_error(s,src=nil,con=nil) - policy = get_setting(:on_error) - - case policy - when :ignore - when :raise - raise_error create_frame(describe_error(s,src,con)) - when :warning - tell_user create_frame(describe_error(s,src,con)) - else - raise "BugBug: policy = #{policy.inspect}" - end - end - - def maruku_recover(s,src=nil,con=nil) - tell_user create_frame(describe_error(s,src,con)) - end - - alias error maruku_error - - def raise_error(s) - raise MaRuKu::Exception, s, caller - end - - def tell_user(s) - error_stream = self.attributes[:error_stream] || $stderr - error_stream << s - end - - def create_frame(s) - n = 75 - "\n" + - " "+"_"*n + "\n"+ - "| Maruku tells you:\n" + - "+" + ("-"*n) +"\n"+ - add_tabs(s,1,'| ') + "\n" + - "+" + ("-"*n) + "\n" + - add_tabs(caller[0, 5].join("\n"),1,'!') + "\n" + - "\\" + ("_"*n) + "\n" - end - - def describe_error(s,src,con) - t = s - src && (t += "\n#{src.describe}\n") - con && (t += "\n#{con.describe}\n") - t - end - -end # Errors -end # MaRuKu - - diff --git a/vendor/plugins/maruku/lib/maruku/ext/div.rb b/vendor/plugins/maruku/lib/maruku/ext/div.rb index c308a24e..e378fb23 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/div.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/div.rb @@ -1,5 +1,3 @@ - - #+-----------------------------------{.warning}------ #| this is the last warning! #| @@ -10,123 +8,114 @@ #| +-------------------------------------------------- #+--------------------------------------------------- -#OpenDiv = /^[ ]{0,3}\+\-\-+\s*(.*)$/ -#CloseDiv = /^[ ]{0,3}\=\-\-+\s*(.*)$/ +# TODO: Scope these properly OpenDiv = /^[ ]{0,3}\+\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/ CloseDiv = /^[ ]{0,3}\=\-\-+\s*(\{([^{}]*?|".*?"|'.*?')*\})?\s*\-*\s*$/ StartPipe = /^[ ]{0,3}\|(.*)$/ # $1 is rest of line DecorativeClosing = OpenDiv -MaRuKu::In::Markdown::register_block_extension( - :regexp => OpenDiv, - :handler => lambda { |doc, src, context| - # return false if not doc.is_math_enabled? - first = src.shift_line - first =~ OpenDiv - ial_at_beginning = $1 - ial_at_end = nil - - lines = [] - # if second line starts with "|" - if src.cur_line =~ StartPipe - # then we read until no more "|" - while src.cur_line && (src.cur_line =~ StartPipe) - content = $1 - lines.push content - src.shift_line - end - if src.cur_line =~ DecorativeClosing - ial_at_end = $1 - src.shift_line - end - else - # else we read until CloseDiv - divs_open = 1 - while src.cur_line && (divs_open>0) - if src.cur_line =~ CloseDiv - divs_open -= 1 - if divs_open == 0 - ial_at_end = $1 - src.shift_line - break - else - lines.push src.shift_line - end - else - if src.cur_line =~ OpenDiv - divs_open += 1 - end - lines.push src.shift_line - end - end - - if divs_open > 0 - e = "At end of input, I still have #{divs_open} DIVs open." - doc.maruku_error(e, src, context) - return true - end - end - - ial_at_beginning = nil unless - (ial_at_beginning&&ial_at_beginning.size > 0) - ial_at_end = nil unless (ial_at_end && ial_at_end.size > 0) +MaRuKu::In::Markdown.register_block_extension( + :regexp => OpenDiv, + :handler => lambda do |doc, src, context| + first = src.shift_line + ial_at_beginning = first[OpenDiv, 1] + ial_at_end = nil - if ial_at_beginning && ial_at_end - e = "Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}" - doc.maruku_error(e, src, context) - end - - al_string = ial_at_beginning || ial_at_end - al = nil - - if al_string =~ /^\{(.*)\}\s*$/ - inside = $1 - cs = MaRuKu::In::Markdown::SpanLevelParser::CharSource - al = al_string && - doc.read_attribute_list(cs.new(inside), its_context=nil, break_on=[nil]) - end - - src = MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines) - children = doc.parse_blocks(src) + lines = [] + # if second line starts with "|" + if src.cur_line =~ StartPipe + # then we read until no more "|" + while src.cur_line && src.cur_line =~ StartPipe + lines.push $1 + src.shift_line + end + if src.cur_line =~ DecorativeClosing + ial_at_end = $1 + src.shift_line + end + else + # else we read until CloseDiv + divs_open = 1 + while src.cur_line && divs_open > 0 + if src.cur_line =~ CloseDiv + divs_open -= 1 + if divs_open == 0 + ial_at_end = $1 + src.shift_line + break + else + lines.push src.shift_line + end + else + if src.cur_line =~ OpenDiv + divs_open += 1 + end + lines.push src.shift_line + end + end - context.push doc.md_div(children, al) - true - }) - + if divs_open > 0 + doc.maruku_error("At end of input, I still have #{divs_open} DIVs open.", + src, context) + next true + end + end -module MaRuKu; class MDElement + ial_at_beginning = nil unless ial_at_beginning && ial_at_beginning.size > 0 + ial_at_end = nil unless ial_at_end && ial_at_end.size > 0 - def md_div(children, al=nil) - type = label = num = nil - doc.refid2ref ||= {} - if al - al.each do |k, v| - case k - when :class - type = $1 if v =~ /^num_(\w*)/ - when :id - label = v - end - end - end - if type - doc.refid2ref[type] ||= {} - num = doc.refid2ref[type].length + 1 || 1 - end - e = self.md_el(:div, children, meta={:label => label, :type => type, :num => num}, al) - if type && label - doc.refid2ref[type].update({label => e}) - end - e - end - -end end + if ial_at_beginning && ial_at_end + doc.maruku_error("Found two conflicting IALs: #{ial_at_beginning.inspect} and #{ial_at_end.inspect}", + src, context) + end + al_string = ial_at_beginning || ial_at_end + al = nil -module MaRuKu; module Out; module HTML + if al_string =~ /^\{(.*)\}\s*$/ + al = al_string && doc.read_attribute_list( + MaRuKu::In::Markdown::SpanLevelParser::CharSource.new($1), + nil, [nil]) + end - def to_html_div - add_ws wrap_as_element('div') - end - -end end end + context.push( + doc.md_div( + doc.parse_blocks( + MaRuKu::In::Markdown::BlockLevelParser::LineSource.new(lines)), + al)) + true + end) + +module MaRuKu + class MDElement + def md_div(children, al = nil) + type = label = num = nil + doc.refid2ref ||= {} + if al + al.each do |k, v| + case k + when :class; type = $1 if v =~ /^num_(\w*)/ + when :id; label = v + end + end + end + + if type + doc.refid2ref[type] ||= {} + num = doc.refid2ref[type].length + 1 + end + + e = self.md_el(:div, children, {:label => label, :type => type, :num => num}, al) + doc.refid2ref[type].update(label => e) if type && label + e + end + end + + module Out + module HTML + def to_html_div + add_ws wrap_as_element('div') + end + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/ext/math.rb b/vendor/plugins/maruku/lib/maruku/ext/math.rb index 8f65371c..4f9773b3 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math.rb @@ -1,5 +1,3 @@ - - require 'maruku/ext/math/elements' require 'maruku/ext/math/parsing' require 'maruku/ext/math/to_latex' @@ -10,7 +8,6 @@ require 'maruku/ext/math/mathml_engines/ritex' require 'maruku/ext/math/mathml_engines/itex2mml' require 'maruku/ext/math/mathml_engines/blahtex' - =begin maruku_doc Attribute: math_enabled Scope: global, document @@ -37,5 +34,4 @@ Array containing any of `'\\['`, `'\\begin{equation}'`, `'$$'`. =end - MaRuKu::Globals[:math_numbered] = [] diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/elements.rb b/vendor/plugins/maruku/lib/maruku/ext/math/elements.rb index f0ba3c08..e3d75f03 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/elements.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/elements.rb @@ -1,27 +1,21 @@ -module MaRuKu; class MDElement - - def md_inline_math(math) - self.md_el(:inline_math, [], meta={:math=>math}) - end +module MaRuKu + class MDElement + def md_inline_math(math) + self.md_el(:inline_math, [], :math => math) + end - def md_equation(math, label, numerate) - reglabel= /\\label\{(\w+)\}/ - if math =~ reglabel - label = $1 - math.gsub!(reglabel,'') - end -# puts "Found label = #{label} math #{math.inspect} " - num = nil - if (label || numerate) && @doc #take number - @doc.eqid2eq ||= {} - num = @doc.eqid2eq.size + 1 - label = "eq#{num}" if not label # FIXME do id for document - end - e = self.md_el(:equation, [], meta={:math=>math, :label=>label,:num=>num}) - if label && @doc #take number - @doc.eqid2eq[label] = e - end - e - end - -end end \ No newline at end of file + def md_equation(math, label, numerate) + reglabel = /\\label\{(\w+)\}/ + math = math.gsub(reglabel, '') if label = math[reglabel, 1] + num = nil + if (label || numerate) && @doc # take number + @doc.eqid2eq ||= {} + num = @doc.eqid2eq.size + 1 + label = "eq#{num}" if not label # TODO do id for document + end + e = self.md_el(:equation, [], :math => math, :label => label, :num => num) + @doc.eqid2eq[label] = e if label && @doc # take number + e + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/blahtex.rb b/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/blahtex.rb index b6cb30e8..4f99796a 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/blahtex.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/blahtex.rb @@ -1,107 +1,93 @@ - require 'tempfile' require 'fileutils' require 'digest/md5' require 'pstore' -module MaRuKu; module Out; module HTML - - PNG = Struct.new(:src,:depth,:height) - - def convert_to_png_blahtex(kind, tex) - begin - FileUtils::mkdir_p get_setting(:html_png_dir) +module MaRuKu + module Out + module HTML + PNG = Struct.new(:src, :depth, :height) - # first, we check whether this image has already been processed - md5sum = Digest::MD5.hexdigest(tex+" params: ") - result_file = File.join(get_setting(:html_png_dir), md5sum+".txt") + def convert_to_png_blahtex(kind, tex) + FileUtils.mkdir_p get_setting(:html_png_dir) - if not File.exists?(result_file) - tmp_in = Tempfile.new('maruku_blahtex') - f = tmp_in.open - f.write tex - f.close + # first, we check whether this image has already been processed + md5sum = Digest::MD5.hexdigest(tex + " params: ") + result_file = File.join(get_setting(:html_png_dir), md5sum + ".txt") - resolution = get_setting(:html_png_resolution) + if not File.exists?(result_file) + Tempfile.open('maruku_blahtex') do |tmp_in| + tmp_in.write tex + tmp_in.close - options = "--png --use-preview-package --shell-dvipng 'dvipng -D #{resolution}' " - options += "--displaymath " if kind == :equation - options += ("--temp-directory '%s' " % get_setting(:html_png_dir)) - options += ("--png-directory '%s'" % get_setting(:html_png_dir)) + # It's important taht we don't replace *all* newlines, + # because newlines in arguments get escaped as "'\n'". + system < #{shellescape(result_file)} +COMMAND + end + end - cmd = "blahtex #{options} < #{tmp_in.path} > #{result_file}" - #$stderr.puts "$ #{cmd}" - system cmd - tmp_in.delete - end - - result = File.read(result_file) - if result.nil? || result.empty? - raise "Blahtex error: empty output" + result = File.read(result_file) + if result.nil? || result.empty? + maruku_error "Blahtex error: empty output" + return + end + + doc = Document.new(result, :respect_whitespace => :all) + png = doc.root.elements[1] + if png.name != 'png' + maruku_error "Blahtex error: \n#{doc}" + return + end + + raise "No depth element in:\n #{doc}" unless depth = png.elements['depth'] + raise "No height element in:\n #{doc}" unless height = png.elements['height'] + raise "No md5 element in:\n #{doc}" unless md5 = png.elements['md5'] + + depth = depth.text.to_f + height = height.text.to_f # TODO: check != 0 + md5 = md5.text + + PNG.new("#{get_setting(:html_png_url)}#{md5}.png", depth, height) + rescue Exception => e + maruku_error "Error: #{e}" end - - doc = Document.new(result, {:respect_whitespace =>:all}) - png = doc.root.elements[1] - if png.name != 'png' - raise "Blahtex error: \n#{doc}" - end - depth = png.elements['depth'] || (raise "No depth element in:\n #{doc}") - height = png.elements['height'] || (raise "No height element in:\n #{doc}") - md5 = png.elements['md5'] || (raise "No md5 element in:\n #{doc}") - - depth = depth.text.to_f - height = height.text.to_f # XXX check != 0 - md5 = md5.text - - dir_url = get_setting(:html_png_url) - return PNG.new("#{dir_url}#{md5}.png", depth, height) - rescue Exception => e - maruku_error "Error: #{e}" - end - nil - end - - def convert_to_mathml_blahtex(kind, tex) - @@BlahtexCache = PStore.new(get_setting(:latex_cache_file)) - - begin - @@BlahtexCache.transaction do - if @@BlahtexCache[tex].nil? - tmp_in = Tempfile.new('maruku_blahtex') - f = tmp_in.open - f.write tex - f.close - tmp_out = Tempfile.new('maruku_blahtex') - - options = "--mathml" - cmd = "blahtex #{options} < #{tmp_in.path} > #{tmp_out.path}" - #$stderr.puts "$ #{cmd}" - system cmd - tmp_in.delete - - result = nil - File.open(tmp_out.path) do |f| result=f.read end - puts result - - @@BlahtexCache[tex] = result - end - - blahtex = @@BlahtexCache[tex] - doc = Document.new(blahtex, {:respect_whitespace =>:all}) - mathml = doc.root.elements['mathml'] - if not mathml - maruku_error "Blahtex error: \n#{doc}" - return nil - else - return mathml - end - end - - rescue Exception => e - maruku_error "Error: #{e}" - end - nil - end -end end end + def convert_to_mathml_blahtex(kind, tex) + @@BlahtexCache ||= PStore.new(get_setting(:latex_cache_file)) + + @@BlahtexCache.transaction do + if @@BlahtexCache[tex].nil? + Tempfile.open('maruku_blahtex') do |tmp_in| + tmp_in.write tex + + Tempfile.new('maruku_blahtex') do |tmp_out| + system "blahtex --mathml < #{shellescape(tmp_in.path)} > #{shellescape(tmp_out.path)}" + @@BlahtexCache[tex] = tmp_out.read + end + end + end + + blahtex = @@BlahtexCache[tex] + doc = Document.new(blahtex, :respect_whitespace => :all) + unless mathml = doc.root.elements['mathml'] + maruku_error "Blahtex error: \n#{doc}" + return + end + + return mathml + end + rescue Exception => e + maruku_error "Error: #{e}" + end + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/itex2mml.rb b/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/itex2mml.rb index b884863c..3ea4c394 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/itex2mml.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/mathml_engines/itex2mml.rb @@ -1,30 +1,34 @@ +module MaRuKu + module Out + module HTML + def convert_to_mathml_itex2mml(kind, tex) + return if $already_warned_itex2mml + require 'itextomml' + require 'stringsupport' -module MaRuKu; module Out; module HTML + parser = Itex2MML::Parser.new + mathml = + case kind + when :equation; parser.block_filter(tex) + when :inline; parser.inline_filter(tex) + else + maruku_error "Unknown itex2mml kind: #{kind}" + return + end - def convert_to_mathml_itex2mml(kind, tex) - begin - if not $itex2mml_parser - require 'stringsupport' - require 'itextomml' - $itex2mml_parser = Itex2MML::Parser.new - end - - itex_method = {:equation=>:block_filter,:inline=>:inline_filter} - - mathml = $itex2mml_parser.send(itex_method[kind], tex).to_utf8 - doc = Document.new(mathml, {:respect_whitespace =>:all}).root - return doc - rescue LoadError => e - maruku_error "Could not load package 'itex2mml'.\n"+ "Please install it." unless $already_warned_itex2mml - $already_warned_itex2mml = true - rescue REXML::ParseException => e - maruku_error "Invalid MathML TeX: \n#{add_tabs(tex,1,'tex>')}"+ - "\n\n #{e.inspect}" - rescue - maruku_error "Could not produce MathML TeX: \n#{tex}"+ - "\n\n #{e.inspect}" - end - nil - end - -end end end + return Document.new(mathml.to_utf8, :respect_whitespace => :all).root + rescue LoadError => e + # TODO: Properly scope this global + maruku_error "Could not load package 'itex2mml'.\nPlease install it." unless $already_warned_itex2mml + $already_warned_itex2mml = true + nil + rescue REXML::ParseException => e + maruku_error "Invalid MathML TeX: \n#{tex.gsub(/^/, 'tex>')}\n\n #{e.inspect}" + nil + rescue + maruku_error "Could not produce MathML TeX: \n#{tex}\n\n #{e.inspect}" + nil + end + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb b/vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb index b8ba6052..f7460d34 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/parsing.rb @@ -1,119 +1,111 @@ module MaRuKu - - class MDDocument - # Hash equation id (String) to equation element (MDElement) - attr_accessor :eqid2eq - - def is_math_enabled? - get_setting :math_enabled - end - end + class MDDocument + # A hash of equation ids to equation elements + # + # @return [String => MDElement] + attr_accessor :eqid2eq + + def is_math_enabled? + get_setting :math_enabled + end + end end +# TODO: Properly scope all these regexps +# Everything goes; takes care of escaping the "\$" inside the expression +RegInlineMath = /\${1}((?:[^\$]|\\\$)+)\$/ - # Everything goes; takes care of escaping the "\$" inside the expression - RegInlineMath = /\${1}((?:[^\$]|\\\$)+)\$/ - - MaRuKu::In::Markdown::register_span_extension( - :chars => ?$, - :regexp => RegInlineMath, - :handler => lambda { |doc, src, con| - return false if not doc.is_math_enabled? - - if m = src.read_regexp(RegInlineMath) - math = m.captures.compact.first - con.push doc.md_inline_math(math) - true - else - #puts "not math: #{src.cur_chars 10}" - false - end - } - ) - - - MathOpen1 = Regexp.escape('\\begin{equation}') - MathClose1 = Regexp.escape('\\end{equation}') - MathOpen2 = Regexp.escape('\\[') - MathClose2 = Regexp.escape('\\]') - MathOpen3 = Regexp.escape('$$') - MathClose3 = Regexp.escape('$$') - - EqLabel = /(?:\((\w+)\))/ - EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/ - EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/ - - # $1 is opening, $2 is tex - EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/ - # $1 is tex, $2 is closing, $3 is tex - EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/ - # $1 is opening, $2 is tex, $3 is closing, $4 is label - OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/ +MaRuKu::In::Markdown.register_span_extension( + :chars => ?$, + :regexp => RegInlineMath, + :handler => lambda do |doc, src, con| + next false unless doc.is_math_enabled? + next false unless m = src.read_regexp(RegInlineMath) + math = m.captures.compact.first + con.push doc.md_inline_math(math) + true + end) - MaRuKu::In::Markdown::register_block_extension( - :regexp => EquationStart, - :handler => lambda { |doc, src, con| - return false if not doc.is_math_enabled? - first = src.shift_line - if first =~ OneLineEquation - opening, tex, closing, label = $1, $2, $3, $4 - numerate = doc.get_setting(:math_numbered).include?(opening) - con.push doc.md_equation(tex, label, numerate) - else - first =~ EquationStart - opening, tex = $1, $2 - - numerate = doc.get_setting(:math_numbered).include?(opening) - label = nil - while true - if not src.cur_line - doc.maruku_error("Stream finished while reading equation\n\n"+ - doc.add_tabs(tex,1,'$> '), src, con) - break - end - line = src.shift_line - if line =~ EquationEnd - tex_line, closing = $1, $2 - label = $3 if $3 - tex += tex_line + "\n" - break - else - tex += line + "\n" - end - end - con.push doc.md_equation(tex, label, numerate) - end - true - }) - - - # This adds support for \eqref - RegEqrefLatex = /\\eqref\{(\w+)\}/ - RegEqPar = /\(eq:(\w+)\)/ - RegEqref = Regexp::union(RegEqrefLatex, RegEqPar) - - MaRuKu::In::Markdown::register_span_extension( - :chars => [?\\, ?(], - :regexp => RegEqref, - :handler => lambda { |doc, src, con| - return false if not doc.is_math_enabled? - eqid = src.read_regexp(RegEqref).captures.compact.first - r = doc.md_el(:eqref, [], meta={:eqid=>eqid}) - con.push r - true - } - ) - # This adds support for \ref - RegRef = /\\ref\{(\w*)\}/ - MaRuKu::In::Markdown::register_span_extension( - :chars => [?\\, ?(], - :regexp => RegRef, - :handler => lambda { |doc, src, con| - return false if not doc.is_math_enabled? - refid = src.read_regexp(RegRef).captures.compact.first - r = doc.md_el(:divref, [], meta={:refid=>refid}) - con.push r - true - } - ) +MathOpen1 = Regexp.escape('\\begin{equation}') +MathClose1 = Regexp.escape('\\end{equation}') +MathOpen2 = Regexp.escape('\\[') +MathClose2 = Regexp.escape('\\]') +MathOpen3 = Regexp.escape('$$') +MathClose3 = Regexp.escape('$$') + +EqLabel = /(?:\((\w+)\))/ +EquationOpen = /#{MathOpen1}|#{MathOpen2}|#{MathOpen3}/ +EquationClose = /#{MathClose1}|#{MathClose2}|#{MathClose3}/ + +# $1 is opening, $2 is tex +EquationStart = /^[ ]{0,3}(#{EquationOpen})(.*)$/ +# $1 is tex, $2 is closing, $3 is tex +EquationEnd = /^(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/ +# $1 is opening, $2 is tex, $3 is closing, $4 is label +OneLineEquation = /^[ ]{0,3}(#{EquationOpen})(.*)(#{EquationClose})\s*#{EqLabel}?\s*$/ + +MaRuKu::In::Markdown.register_block_extension( + :regexp => EquationStart, + :handler => lambda do |doc, src, con| + next false unless doc.is_math_enabled? + first = src.shift_line + if first =~ OneLineEquation + opening, tex, closing, label = $1, $2, $3, $4 + numerate = doc.get_setting(:math_numbered).include?(opening) + con.push doc.md_equation(tex, label, numerate) + next true + end + + opening, tex = first.scan(EquationStart).first + numerate = doc.get_setting(:math_numbered).include?(opening) + label = nil + loop do + unless src.cur_line + doc.maruku_error( + "Stream finished while reading equation\n\n" + tex.gsub(/^/, '$> '), + src, con) + break + end + + line = src.shift_line + if line =~ EquationEnd + tex_line, closing = $1, $2 + label = $3 if $3 + tex << tex_line << "\n" + break + end + + tex << line << "\n" + end + con.push doc.md_equation(tex, label, numerate) + true + end) + + +# This adds support for \eqref +RegEqrefLatex = /\\eqref\{(\w+)\}/ +RegEqPar = /\(eq:(\w+)\)/ +RegEqref = Regexp.union(RegEqrefLatex, RegEqPar) + +MaRuKu::In::Markdown.register_span_extension( + :chars => [?\\, ?(], + :regexp => RegEqref, + :handler => lambda do |doc, src, con| + return false unless doc.is_math_enabled? + eqid = src.read_regexp(RegEqref).captures.compact.first + con.push doc.md_el(:eqref, [], :eqid => eqid) + true + end) + +# This adds support for \ref +RegRef = /\\ref\{(\w*)\}/ +MaRuKu::In::Markdown.register_span_extension( + :chars => [?\\, ?(], + :regexp => RegRef, + :handler => lambda do |doc, src, con| + return false unless doc.is_math_enabled? + refid = src.read_regexp(RegRef).captures.compact.first + con.push doc.md_el(:divref, [], :refid => refid) + true + end) diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb b/vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb index 7baba2bd..602226ba 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/to_html.rb @@ -1,4 +1,3 @@ - =begin maruku_doc Extension: math Attribute: html_math_engine @@ -11,14 +10,14 @@ Select the rendering engine for math. If you want to use your custom engine `foo`, then set: - HTML math engine: foo + HTML math engine: foo {:lang=markdown} and then implement two functions: - def convert_to_mathml_foo(kind, tex) - ... - end + def convert_to_mathml_foo(kind, tex) + ... + end =end =begin maruku_doc @@ -31,165 +30,159 @@ Default: Same thing as `html_math_engine`, only for PNG output. - def convert_to_png_foo(kind, tex) - # same thing - ... - end + def convert_to_png_foo(kind, tex) + # same thing + ... + end {:lang=ruby} =end -module MaRuKu; module Out; module HTML +module MaRuKu + module Out + module HTML + # Creates an xml Mathml document of this node's TeX code. + # + # @return [REXML::Document] + def render_mathml(kind, tex) + engine = get_setting(:html_math_engine) + method = "convert_to_mathml_#{engine}" + if self.respond_to? method + mathml = self.send(method, kind, tex) + return mathml || convert_to_mathml_none(kind, tex) + end + # TODO: Warn here + puts "A method called #{method} should be defined." + return convert_to_mathml_none(kind, tex) + end - - # Creates an xml Mathml document of self.math - def render_mathml(kind, tex) - engine = get_setting(:html_math_engine) - method = "convert_to_mathml_#{engine}".to_sym - if self.respond_to? method - mathml = self.send(method, kind, tex) - return mathml || convert_to_mathml_none(kind, tex) - else - puts "A method called #{method} should be defined." - return convert_to_mathml_none(kind, tex) - end - end + # Renders a PNG image of this node's TeX code. + # Returns + # + # @return [MaRuKu::Out::HTML::PNG, nil] + # A struct describing the location and size of the image, + # or nil if no library is loaded that can render PNGs. + def render_png(kind, tex) + engine = get_setting(:html_png_engine) + method = "convert_to_png_#{engine}".to_sym + return self.send(method, kind, tex) if self.respond_to? method - # Creates an xml Mathml document of self.math - def render_png(kind, tex) - engine = get_setting(:html_png_engine) - method = "convert_to_png_#{engine}".to_sym - if self.respond_to? method - return self.send(method, kind, tex) - else - puts "A method called #{method} should be defined." - return nil - end - end - - def pixels_per_ex - if not $pixels_per_ex - x = render_png(:inline, "x") - $pixels_per_ex = x.height # + x.depth - end - $pixels_per_ex - end - - def adjust_png(png, use_depth) - src = png.src - - height_in_px = png.height - depth_in_px = png.depth - height_in_ex = height_in_px / pixels_per_ex - depth_in_ex = depth_in_px / pixels_per_ex - total_height_in_ex = height_in_ex + depth_in_ex - style = "" - style += "vertical-align: -#{depth_in_ex}ex;" if use_depth - style += "height: #{total_height_in_ex}ex;" - img = Element.new 'img' - img.attributes['src'] = src - img.attributes['style'] = style - img.attributes['alt'] = "$#{self.math.strip}$" - img - end - - def to_html_inline_math - mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.math) - png = get_setting(:html_math_output_png) && render_png(:inline, self.math) + puts "A method called #{method} should be defined." + return nil + end - span = create_html_element 'span' - add_class_to(span, 'maruku-inline') - - if mathml - add_class_to(mathml, 'maruku-mathml') - return mathml - end - - if png - img = adjust_png(png, use_depth=true) - add_class_to(img, 'maruku-png') - span << img - end - span - - end + def pixels_per_ex + $pixels_per_ex ||= render_png(:inline, "x").height + end - def to_html_equation - mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math) - png = get_setting(:html_math_output_png) && render_png(:equation, self.math) - - div = create_html_element 'div' - add_class_to(div, 'maruku-equation') - if mathml - if self.label # then numerate - span = Element.new 'span' - span.attributes['class'] = 'maruku-eq-number' - num = self.num - span << Text.new("(#{num})") - div << span - div.attributes['id'] = "eq:#{self.label}" - end - add_class_to(mathml, 'maruku-mathml') - div << mathml - end - - if png - img = adjust_png(png, use_depth=false) - add_class_to(img, 'maruku-png') - div << img - if self.label # then numerate - span = Element.new 'span' - span.attributes['class'] = 'maruku-eq-number' - num = self.num - span << Text.new("(#{num})") - div << span - div.attributes['id'] = "eq:#{self.label}" - end - end - - source_span = Element.new 'span' - add_class_to(source_span, 'maruku-eq-tex') - code = convert_to_mathml_none(:equation, self.math.strip) - code.attributes['style'] = 'display: none' - source_span << code - div << source_span - - div - end - - def to_html_eqref - if eq = self.doc.eqid2eq[self.eqid] - num = eq.num - a = Element.new 'a' - a.attributes['class'] = 'maruku-eqref' - a.attributes['href'] = "#eq:#{self.eqid}" - a << Text.new("(#{num})") - a - else - maruku_error "Cannot find equation #{self.eqid.inspect}" - Text.new "(eq:#{self.eqid})" - end - end + def adjust_png(png, use_depth) + src = png.src - def to_html_divref - ref= nil - self.doc.refid2ref.each_value { |h| - ref = h[self.refid] if h.has_key?(self.refid) - } - if ref - num = ref.num - a = Element.new 'a' - a.attributes['class'] = 'maruku-ref' - a.attributes['href'] = "#" + self.refid - a << Text.new(num.to_s) - a - else - maruku_error "Cannot find div #{self.refid.inspect}" - Text.new "\\ref{#{self.refid}}" - end - end - -end end end + height_in_px = png.height + depth_in_px = png.depth + height_in_ex = height_in_px / pixels_per_ex + depth_in_ex = depth_in_px / pixels_per_ex + total_height_in_ex = height_in_ex + depth_in_ex + style = "" + style << "vertical-align: -#{depth_in_ex}ex;" if use_depth + style << "height: #{total_height_in_ex}ex;" + img = Element.new 'img' + img.attributes['src'] = src + img.attributes['style'] = style + img.attributes['alt'] = "$#{self.math.strip}$" + img + end + def to_html_inline_math + mathml = get_setting(:html_math_output_mathml) && render_mathml(:inline, self.math) + png = get_setting(:html_math_output_png) && render_png(:inline, self.math) + + span = create_html_element 'span' + add_class_to(span, 'maruku-inline') + + if mathml + add_class_to(mathml, 'maruku-mathml') + return mathml + end + + if png + img = adjust_png(png, true) + add_class_to(img, 'maruku-png') + span << img + end + + span + end + + def to_html_equation + mathml = get_setting(:html_math_output_mathml) && render_mathml(:equation, self.math) + png = get_setting(:html_math_output_png) && render_png(:equation, self.math) + + div = create_html_element 'div' + add_class_to(div, 'maruku-equation') + if mathml + if self.label # then numerate + span = Element.new 'span' + span.attributes['class'] = 'maruku-eq-number' + span << Text.new("(#{self.num})") + div << span + div.attributes['id'] = "eq:#{self.label}" + end + add_class_to(mathml, 'maruku-mathml') + div << mathml + end + + if png + img = adjust_png(png, false) + add_class_to(img, 'maruku-png') + div << img + if self.label # then numerate + span = Element.new 'span' + span.attributes['class'] = 'maruku-eq-number' + span << Text.new("(#{self.num})") + div << span + div.attributes['id'] = "eq:#{self.label}" + end + end + + source_span = Element.new 'span' + add_class_to(source_span, 'maruku-eq-tex') + code = convert_to_mathml_none(:equation, self.math.strip) + code.attributes['style'] = 'display: none' + source_span << code + div << source_span + + div + end + + def to_html_eqref + unless eq = self.doc.eqid2eq[self.eqid] + maruku_error "Cannot find equation #{self.eqid.inspect}" + return Text.new("(eq:#{self.eqid})") + end + + a = Element.new 'a' + a.attributes['class'] = 'maruku-eqref' + a.attributes['href'] = "#eq:#{self.eqid}" + a << Text.new("(#{eq.num})") + a + end + + def to_html_divref + unless hash = self.doc.refid2ref.values.find {|h| h.has_key?(self.refid)} + maruku_error "Cannot find div #{self.refid.inspect}" + return Text.new("\\ref{#{self.refid}}") + end + ref= hash[self.refid] + + a = Element.new 'a' + a.attributes['class'] = 'maruku-ref' + a.attributes['href'] = "#" + self.refid + a << Text.new(ref.num.to_s) + a + end + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/ext/math/to_latex.rb b/vendor/plugins/maruku/lib/maruku/ext/math/to_latex.rb index 7eba4ef3..287a1cb4 100644 --- a/vendor/plugins/maruku/lib/maruku/ext/math/to_latex.rb +++ b/vendor/plugins/maruku/lib/maruku/ext/math/to_latex.rb @@ -1,26 +1,36 @@ require 'maruku/ext/math/latex_fix' -module MaRuKu; module Out; module Latex +module MaRuKu + module Out + module Latex + def to_latex_inline_math + fix_latex("$#{self.math.strip}$") + end - def to_latex_inline_math - "$#{self.math.strip}$".fix_latex - end + def to_latex_equation + if self.label + fix_latex("\\begin{equation}\n#{self.math.strip}\n\\label{#{self.label}}\\end{equation}\n") + else + fix_latex("\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n") + end + end - def to_latex_equation - if self.label - l = "\\label{#{self.label}}" - "\\begin{equation}\n#{self.math.strip}\n#{l}\\end{equation}\n".fix_latex - else - "\\begin{displaymath}\n#{self.math.strip}\n\\end{displaymath}\n".fix_latex - end - end - - def to_latex_eqref - "\\eqref{#{self.eqid}}" - end + def to_latex_eqref + "\\eqref{#{self.eqid}}" + end - def to_latex_divref - "\\ref{#{self.refid}}" - end + def to_latex_divref + "\\ref{#{self.refid}}" + end -end end end + private + + def fix_latex(str) + return str unless self.get_setting(:html_math_engine) == 'itex2mml' + s = str.gsub("\\mathop{", "\\operatorname{") + s.gsub!(/\\begin\{svg\}.*?\\end\{svg\}/m, " ") + s.gsub("\\space{", "\\itexspace{") + end + end + end +end diff --git a/vendor/plugins/maruku/lib/maruku/helpers.rb b/vendor/plugins/maruku/lib/maruku/helpers.rb index 5f90c7c8..4fcf4130 100644 --- a/vendor/plugins/maruku/lib/maruku/helpers.rb +++ b/vendor/plugins/maruku/lib/maruku/helpers.rb @@ -1,260 +1,214 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ - - -# A series of helper functions for creating elements: they hide the -# particular internal representation. -# -# Please, always use these instead of creating MDElement. -# - module MaRuKu -module Helpers + # A collection of helper functions for creating Markdown elements. + # They hide the particular internal representations. + # + # Always use these rather than creating an {MDElement} directly. + module Helpers + # @param children [Array] + # The child nodes. + # If the first child is a \{#md\_ial}, it's merged with `al` + def md_el(node_type, children = [], meta = {}, al = nil) + first = children.first + if first.is_a?(MDElement) && first.node_type == :ial + if al + al += first.ial + else + al = first.ial + end + children.shift + end - # if the first is a md_ial, it is used as such - def md_el(node_type, children=[], meta={}, al=nil) - if (e=children.first).kind_of?(MDElement) and - e.node_type == :ial then - if al - al += e.ial - else - al = e.ial - end - children.shift - end - e = MDElement.new(node_type, children, meta, al) - e.doc = @doc - return e - end + e = MDElement.new(node_type, children, meta, al) + e.doc = @doc + e + end - def md_header(level, children, al=nil) - md_el(:header, children, {:level => level}, al) - end - - # Inline code - def md_code(code, al=nil) - md_el(:inline_code, [], {:raw_code => code}, al) - end + def md_header(level, children, al = nil) + md_el(:header, children, {:level => level}, al) + end - # Code block - def md_codeblock(source, al=nil) - md_el(:code, [], {:raw_code => source}, al) - end + # Inline code + def md_code(code, al = nil) + md_el(:inline_code, [], {:raw_code => code}, al) + end - def md_quote(children, al=nil) - md_el(:quote, children, {}, al) - end + # Code block + def md_codeblock(source, al = nil) + md_el(:code, [], {:raw_code => source}, al) + end - def md_li(children, want_my_par, al=nil) - md_el(:li, children, {:want_my_paragraph=>want_my_par}, al) - end + def md_quote(children, al = nil) + md_el(:quote, children, {}, al) + end - def md_footnote(footnote_id, children, al=nil) - md_el(:footnote, children, {:footnote_id=>footnote_id}, al) - end + def md_li(children, want_my_par, al = nil) + md_el(:li, children, {:want_my_paragraph => want_my_par}, al) + end - def md_abbr_def(abbr, text, al=nil) - md_el(:abbr_def, [], {:abbr=>abbr, :text=>text}, al) - end + def md_footnote(footnote_id, children, al = nil) + md_el(:footnote, children, {:footnote_id => footnote_id}, al) + end - def md_abbr(abbr, title) - md_el(:abbr, [abbr], {:title=>title}) - end - - def md_html(raw_html, al=nil) - e = md_el(:raw_html, [], {:raw_html=>raw_html}) - begin - # remove newlines and whitespace at begin - # end end of string, or else REXML gets confused - raw_html = raw_html.gsub(/\A\s*[\s\n]*\Z/,'>') - - raw_html = "#{raw_html}" - e.instance_variable_set :@parsed_html, - REXML::Document.new(raw_html) - rescue REXML::ParseException => ex - e.instance_variable_set :@parsed_html, nil - maruku_recover "REXML cannot parse this block of HTML/XML:\n"+ - add_tabs(raw_html,1,'|') + "\n"+ex.inspect -# " #{raw_html.inspect}\n\n"+ex.inspect - end - e - end - - def md_link(children, ref_id, al=nil) - md_el(:link, children, {:ref_id=>ref_id.downcase}, al) - end - - def md_im_link(children, url, title=nil, al=nil) - md_el(:im_link, children, {:url=>url,:title=>title}, al) - end - - def md_image(children, ref_id, al=nil) - md_el(:image, children, {:ref_id=>ref_id}, al) - end - - def md_im_image(children, url, title=nil, al=nil) - md_el(:im_image, children, {:url=>url,:title=>title},al) - end + def md_abbr_def(abbr, text, al = nil) + md_el(:abbr_def, [], {:abbr => abbr, :text => text}, al) + end - def md_em(children, al=nil) - md_el(:emphasis, [children].flatten, {}, al) - end + def md_abbr(abbr, title) + md_el(:abbr, [abbr], :title => title) + end - def md_br() - md_el(:linebreak, [], {}, nil) - end + def md_html(raw_html, al = nil) + e = md_el(:raw_html, [], :raw_html => raw_html) + begin + e.instance_variable_set("@parsed_html", + REXML::Document.new("#{raw_html.strip}")) + rescue REXML::ParseException => ex + e.instance_variable_set "@parsed_html", nil + maruku_recover < ref_id.downcase}, al) + end - def md_strong(children, al=nil) - md_el(:strong, [children].flatten, {}, al) - end + def md_im_link(children, url, title = nil, al = nil) + md_el(:im_link, children, {:url => url, :title => title}, al) + end - def md_emstrong(children, al=nil) - md_strong(md_em(children), al) - end + def md_image(children, ref_id, al = nil) + md_el(:image, children, {:ref_id => ref_id}, al) + end - # - def md_url(url, al=nil) - md_el(:immediate_link, [], {:url=>url}, al) - end - - # - # - def md_email(email, al=nil) - md_el(:email_address, [], {:email=>email}, al) - end - - def md_entity(entity_name, al=nil) - md_el(:entity, [], {:entity_name=>entity_name}, al) - end - - # Markdown extra - def md_foot_ref(ref_id, al=nil) - md_el(:footnote_reference, [], {:footnote_id=>ref_id}, al) - end - - def md_par(children, al=nil) - md_el(:paragraph, children, meta={}, al) - end + def md_im_image(children, url, title = nil, al = nil) + md_el(:im_image, children, {:url => url, :title => title}, al) + end - # [1]: http://url [properties] - def md_ref_def(ref_id, url, title=nil, meta={}, al=nil) - meta[:url] = url - meta[:ref_id] = ref_id - meta[:title] = title if title - md_el(:ref_definition, [], meta, al) - end - - # inline attribute list - def md_ial(al) - al = Maruku::AttributeList.new(al) if - not al.kind_of?Maruku::AttributeList - md_el(:ial, [], {:ial=>al}) - end + def md_em(children, al = nil) + md_el(:emphasis, [children].flatten, {}, al) + end - # Attribute list definition - def md_ald(id, al) - md_el(:ald, [], {:ald_id=>id,:ald=>al}) - end - - # Server directive - def md_xml_instr(target, code) - md_el(:xml_instr, [], {:target=>target, :code=>code}) - end + def md_br + md_el(:linebreak, [], {}, nil) + end + def md_hrule + md_el(:hrule, [], {}, nil) + end + + def md_strong(children, al = nil) + md_el(:strong, [children].flatten, {}, al) + end + + def md_emstrong(children, al = nil) + md_strong(md_em(children), al) + end + + # A URL to be linkified (e.g. ``). + def md_url(url, al = nil) + md_el(:immediate_link, [], {:url => url}, al) + end + + # An email to be linkified + # (e.g. `` or ``). + def md_email(email, al = nil) + md_el(:email_address, [], {:email => email}, al) + end + + def md_entity(entity_name, al = nil) + md_el(:entity, [], {:entity_name => entity_name}, al) + end + + # Markdown extra + def md_foot_ref(ref_id, al = nil) + md_el(:footnote_reference, [], {:footnote_id => ref_id}, al) + end + + def md_par(children, al = nil) + md_el(:paragraph, children, meta = {}, al) + end + + # A definition of a reference (e.g. `[1]: http://url [properties]`). + def md_ref_def(ref_id, url, title = nil, meta = {}, al = nil) + meta[:url] = url + meta[:ref_id] = ref_id + meta[:title] = title if title + md_el(:ref_definition, [], meta, al) + end + + # inline attribute list + def md_ial(al) + al = Maruku::AttributeList.new(al) unless al.is_a?(Maruku::AttributeList) + md_el(:ial, [], :ial => al) + end + + # Attribute list definition + def md_ald(id, al) + md_el(:ald, [], :ald_id => id, :ald => al) + end + + # A server directive (e.g. ``) + def md_xml_instr(target, code) + md_el(:xml_instr, [], :target => target, :code => code) + end + end + + class MDElement + INSPECT2_FORMS = { + :paragraph => ["par", :children], + :footnote_reference => ["foot_ref", :footnote_id], + :entity => ["entity", :entity_name], + :email_address => ["email", :email], + :inline_code => ["code", :raw_code], + :raw_html => ["html", :raw_html], + :emphasis => ["em", :children], + :strong => ["strong", :children], + :immediate_link => ["url", :url], + :image => ["image", :children, :ref_id], + :im_image => ["im_image", :children, :url, :title], + :link => ["link", :children, :ref_id], + :im_link => ["im_link", :children, :url, :title], + :ref_definition => ["ref_def", :ref_id, :url, :title], + :ial => ["ial", :ial] + } + + # Outputs the abbreviated form of an element + # (this should be `eval`-able to get a copy of the original element). + def inspect2 + name, *params = INSPECT2_FORMS[@node_type] + return nil unless name + + params = params.map do |p| + next children_inspect if p == :children + send(p).inspect + end + params << @al.inspect if @al && !@al.empty? + + "md_#{name}(#{params.join(', ')})" + end + end end -end - -module MaRuKu - -class MDElement - # outputs abbreviated form (this should be eval()uable to get the document) - def inspect2 - s = - case @node_type - when :paragraph - "md_par(%s)" % children_inspect - when :footnote_reference - "md_foot_ref(%s)" % self.footnote_id.inspect - when :entity - "md_entity(%s)" % self.entity_name.inspect - when :email_address - "md_email(%s)" % self.email.inspect - when :inline_code - "md_code(%s)" % self.raw_code.inspect - when :raw_html - "md_html(%s)" % self.raw_html.inspect - when :emphasis - "md_em(%s)" % children_inspect - when :strong - "md_strong(%s)" % children_inspect - when :immediate_link - "md_url(%s)" % self.url.inspect - when :image - "md_image(%s, %s)" % [ - children_inspect, - self.ref_id.inspect] - when :im_image - "md_im_image(%s, %s, %s)" % [ - children_inspect, - self.url.inspect, - self.title.inspect] - when :link - "md_link(%s,%s)" % [ - children_inspect, self.ref_id.inspect] - when :im_link - "md_im_link(%s, %s, %s)" % [ - children_inspect, - self.url.inspect, - self.title.inspect, - ] - when :ref_definition - "md_ref_def(%s, %s, %s)" % [ - self.ref_id.inspect, - self.url.inspect, - self.title.inspect - ] - when :ial - "md_ial(%s)" % self.ial.inspect - else - return nil - end - if @al and not @al.empty? then - s = s.chop + ", #{@al.inspect})" - end - s - end - -end - -end - - - - - - - diff --git a/vendor/plugins/maruku/lib/maruku/input/charsource.rb b/vendor/plugins/maruku/lib/maruku/input/charsource.rb index d2d978d6..14a64735 100644 --- a/vendor/plugins/maruku/lib/maruku/input/charsource.rb +++ b/vendor/plugins/maruku/lib/maruku/input/charsource.rb @@ -122,7 +122,7 @@ class CharSourceManual def consume_whitespace while c = cur_char - if (c == ?\s || c == ?\t) + if (c == ?\s || c == ?\t) # puts "ignoring #{c}" ignore_char else @@ -191,7 +191,7 @@ def describe_pos(buffer, buffer_index) pre + "+--- Byte #{buffer_index}\n"+ "Shown bytes [#{index_start} to #{size}] of #{buffer.size}:\n"+ - add_tabs(buffer,1,">") + buffer.gsub(/^/, ">") # "CharSource: At character #{@buffer_index} of block "+ # " beginning with:\n #{@buffer[0,50].inspect} ...\n"+ diff --git a/vendor/plugins/maruku/lib/maruku/input/html_helper.rb b/vendor/plugins/maruku/lib/maruku/input/html_helper.rb index e6c43d5e..a5456a7d 100644 --- a/vendor/plugins/maruku/lib/maruku/input/html_helper.rb +++ b/vendor/plugins/maruku/lib/maruku/input/html_helper.rb @@ -168,9 +168,9 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser "match=#{@m.to_s.inspect}\n"+ "Tag stack = #{@tag_stack.inspect} \n"+ "Before:\n"+ - add_tabs(@already,1,'|')+"\n"+ + @already.gsub(/^/, '|')+"\n"+ "After:\n"+ - add_tabs(@rest,1,'|')+"\n" + @rest.gsub(/^/, '|')+"\n" end diff --git a/vendor/plugins/maruku/lib/maruku/input/linesource.rb b/vendor/plugins/maruku/lib/maruku/input/linesource.rb index e7adf3fc..10642b57 100644 --- a/vendor/plugins/maruku/lib/maruku/input/linesource.rb +++ b/vendor/plugins/maruku/lib/maruku/input/linesource.rb @@ -71,7 +71,7 @@ class LineSource # if @parent # s << "Parent context is: \n" -# s << add_tabs(@parent.describe,1,'|') +# s << @parent.describe.gsub(/^/, '|') # end s end diff --git a/vendor/plugins/maruku/lib/maruku/input/parse_block.rb b/vendor/plugins/maruku/lib/maruku/input/parse_block.rb index e08cb708..6907f13c 100644 --- a/vendor/plugins/maruku/lib/maruku/input/parse_block.rb +++ b/vendor/plugins/maruku/lib/maruku/input/parse_block.rb @@ -198,8 +198,8 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser ial = $2 al = read_attribute_list(CharSource.new(ial,src), context=nil, break_on=[nil]) end - level = num_leading_hashes(line) - text = parse_lines_as_span [strip_hashes(line)] + level = line[/^#+/].size + text = parse_lines_as_span [line.gsub(/\A#+|#+\Z/, '')] return md_header(level, text, al) end @@ -214,7 +214,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser if not code =~ (/\?>\s*$/) garbage = (/\?>(.*)$/.match(code))[1] maruku_error "Trailing garbage on last line: #{garbage.inspect}:\n"+ - add_tabs(code, 1, '|'), src + code.gsub(/^/, '|'), src end code.gsub!(/\?>\s*$/, '') @@ -244,7 +244,7 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser end rescue Exception => e ex = e.inspect + e.backtrace.join("\n") - maruku_error "Bad block-level HTML:\n#{add_tabs(ex,1,'|')}\n", src + maruku_error "Bad block-level HTML:\n#{ex.gsub(/^/, '|')}\n", src end if not (h.rest =~ /^\s*$/) maruku_error "Could you please format this better?\n"+ @@ -271,7 +271,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser lines << src.shift_line end -# dbg_describe_ary(lines, 'PAR') children = parse_lines_as_span(lines, src) return md_par(children) @@ -296,7 +295,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser stripped = first[indentation, first.size-1] lines.unshift stripped - # dbg_describe_ary(lines, 'LIST ITEM ') src2 = LineSource.new(lines, src, parent_offset) children = parse_blocks(src2) @@ -347,7 +345,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser # add first line if text && text.strip != "" then lines.unshift text end -# dbg_describe_ary(lines, 'FOOTNOTE') src2 = LineSource.new(lines, src, parent_offset) children = parse_blocks(src2) @@ -405,7 +402,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser want_my_paragraph = saw_anything_after || (saw_empty && (src.cur_line && (src.cur_line.md_type == item_type))) -# dbg_describe_ary(lines, 'LI') # create a new context while lines.last && (lines.last.md_type == :empty) @@ -424,7 +420,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser while src.cur_line && src.cur_line.md_type == :quote lines << unquote(src.shift_line) end -# dbg_describe_ary(lines, 'QUOTE') src2 = LineSource.new(lines, src, parent_offset) children = parse_blocks(src2) @@ -451,7 +446,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser source = lines.join("\n") -# dbg_describe_ary(lines, 'CODE') return md_codeblock(source) end @@ -568,7 +562,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser while src.cur_line && src.cur_line.md_type == :text terms << md_el(:definition_term, parse_lines_as_span([src.shift_line])) end -# dbg_describe_ary(terms, 'DT') want_my_paragraph = false @@ -599,7 +592,6 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser lines.unshift first -# dbg_describe_ary(lines, 'DD') src2 = LineSource.new(lines, src, parent_offset) children = parse_blocks(src2) definitions << md_el(:definition_data, children) @@ -613,4 +605,4 @@ module MaRuKu; module In; module Markdown; module BlockLevelParser end # BlockLevelParser end # MaRuKu end -end \ No newline at end of file +end diff --git a/vendor/plugins/maruku/lib/maruku/input/parse_doc.rb b/vendor/plugins/maruku/lib/maruku/input/parse_doc.rb index f4a4909a..7808ed22 100644 --- a/vendor/plugins/maruku/lib/maruku/input/parse_doc.rb +++ b/vendor/plugins/maruku/lib/maruku/input/parse_doc.rb @@ -141,19 +141,19 @@ Disabled by default because of security concerns. return object.instance_eval(code) rescue Exception => e maruku_error "Exception while executing this:\n"+ - add_tabs(code, 1, ">")+ + code.gsub(/^/, ">")+ "\nThe error was:\n"+ - add_tabs(e.inspect+"\n"+e.caller.join("\n"), 1, "|") + (e.inspect+"\n"+e.caller.join("\n")).gsub(/^/, "|") rescue RuntimeError => e maruku_error "2: Exception while executing this:\n"+ - add_tabs(code, 1, ">")+ + code.gsub(/^/, ">")+ "\nThe error was:\n"+ - add_tabs(e.inspect, 1, "|") + e.inspect.gsub(/^/, "|") rescue SyntaxError => e maruku_error "2: Exception while executing this:\n"+ - add_tabs(code, 1, ">")+ + code.gsub(/^/, ">")+ "\nThe error was:\n"+ - add_tabs(e.inspect, 1, "|") + e.inspect.gsub(/^/, "|") end nil end diff --git a/vendor/plugins/maruku/lib/maruku/input/parse_span_better.rb b/vendor/plugins/maruku/lib/maruku/input/parse_span_better.rb index 1bab9c50..b9317b41 100644 --- a/vendor/plugins/maruku/lib/maruku/input/parse_span_better.rb +++ b/vendor/plugins/maruku/lib/maruku/input/parse_span_better.rb @@ -500,7 +500,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser # end rescue Exception => e maruku_error "Bad html: \n" + - add_tabs(e.inspect+e.backtrace.join("\n"),1,'>'), + (e.inspect+e.backtrace.join("\n")).gsub(/^/, '>'), src,con maruku_recover "I will try to continue after bad HTML.", src, con con.push_char src.shift_char @@ -733,7 +733,7 @@ module MaRuKu; module In; module Markdown; module SpanLevelParser def describe lines = @elements.map{|x| x.inspect}.join("\n") s = "Elements read in span: \n" + - add_tabs(lines,1, ' -')+"\n" + lines.gsub(/^/, ' -')+"\n" if @cur_string.size > 0 s += "Current string: \n #{@cur_string.inspect}\n" diff --git a/vendor/plugins/maruku/lib/maruku/maruku.rb b/vendor/plugins/maruku/lib/maruku/maruku.rb index 6be6bfa8..1256ed7c 100644 --- a/vendor/plugins/maruku/lib/maruku/maruku.rb +++ b/vendor/plugins/maruku/lib/maruku/maruku.rb @@ -1,33 +1,31 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ -# The Maruku class is the public interface +# The public interface for Maruku. # - -class Maruku - def initialize(s=nil, meta={}) - super(nil) - self.attributes.merge! meta - if s - parse_doc(s) - end - end +# @example Render a document fragment +# Maruku.new("## Header ##").to_html +# # => "" +class Maruku < MaRuKu::MDDocument + def initialize(s = nil, meta = {}) + super(nil) + self.attributes.merge! meta + parse_doc(s) if s + end end diff --git a/vendor/plugins/maruku/lib/maruku/output/to_html.rb b/vendor/plugins/maruku/lib/maruku/output/to_html.rb index 45b1093d..b5f27aae 100644 --- a/vendor/plugins/maruku/lib/maruku/output/to_html.rb +++ b/vendor/plugins/maruku/lib/maruku/output/to_html.rb @@ -578,7 +578,7 @@ and code = Document.new(html, {:respect_whitespace =>:all}).root code.name = 'code' code.attributes['lang'] = lang - + pre = Element.new 'pre' pre.attributes['class'] = lang pre << code @@ -828,7 +828,7 @@ If true, raw HTML is discarded from the output. else # invalid # Creates red box with offending HTML tell_user "Wrapping bad html in a PRE with class 'markdown-html-error'\n"+ - add_tabs(raw_html,1,'|') + raw_html.gsub(/^/, '|') pre = Element.new('pre') pre.attributes['style'] = 'border: solid 3px red; background-color: pink' pre.attributes['class'] = 'markdown-html-error' diff --git a/vendor/plugins/maruku/lib/maruku/output/to_latex_entities.rb b/vendor/plugins/maruku/lib/maruku/output/to_latex_entities.rb index ae314541..35f751ce 100644 --- a/vendor/plugins/maruku/lib/maruku/output/to_latex_entities.rb +++ b/vendor/plugins/maruku/lib/maruku/output/to_latex_entities.rb @@ -55,10 +55,10 @@ module MaRuKu; module Out; module Latex end class LatexEntity - safe_attr_accessor :html_num, Fixnum - safe_attr_accessor :html_entity, String - safe_attr_accessor :latex_string, String - safe_attr_accessor :latex_packages, Array + attr_accessor :html_num + attr_accessor :html_entity + attr_accessor :latex_string + attr_accessor :latex_packages end def Latex.need_entity_table @@ -69,7 +69,7 @@ module MaRuKu; module Out; module Latex def Latex.init_entity_table # $stderr.write "Creating entity table.." # $stderr.flush - doc = Document.new XML_TABLE + doc = Document.new(File.read(File.dirname(__FILE__) + "/../../../data/entities.xml")) doc.elements.each("//char") do |c| num = c.attributes['num'].to_i name = c.attributes['name'] @@ -97,271 +97,5 @@ module MaRuKu; module Out; module Latex ENTITY_TABLE = {} -# The following is a conversion chart for html elements, courtesy of -# text2html - - XML_TABLE =" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " - - end end end diff --git a/vendor/plugins/maruku/lib/maruku/output/to_markdown.rb b/vendor/plugins/maruku/lib/maruku/output/to_markdown.rb index 98d9322d..869afdd8 100644 --- a/vendor/plugins/maruku/lib/maruku/output/to_markdown.rb +++ b/vendor/plugins/maruku/lib/maruku/output/to_markdown.rb @@ -47,7 +47,7 @@ module MaRuKu; module Out; module Markdown def to_md_li_span(context) len = (context[:line_length] || DefaultLineLength) - 2 - s = add_tabs(wrap(@children, len-2, context), 1, ' ') + s = wrap(@children, len-2, context).rstrip.gsub(/^/, ' ') s[0] = ?* s + "\n" end @@ -60,7 +60,7 @@ module MaRuKu; module Out; module Markdown len = (context[:line_length] || DefaultLineLength) - 2 md = "" self.children.each_with_index do |li, i| - s = add_tabs(w=wrap(li.children, len-2, context), 1, ' ')+"\n" + s = (w=wrap(li.children, len-2, context)).rstrip.gsub(/^/, ' ')+"\n" s[0,4] = "#{i+1}. "[0,4] # puts w.inspect md += s @@ -161,4 +161,4 @@ module MaRuKu; class MDDocument # puts s s end -end end \ No newline at end of file +end end diff --git a/vendor/plugins/maruku/lib/maruku/string_utils.rb b/vendor/plugins/maruku/lib/maruku/string_utils.rb index f229cfab..6b3b1d70 100644 --- a/vendor/plugins/maruku/lib/maruku/string_utils.rb +++ b/vendor/plugins/maruku/lib/maruku/string_utils.rb @@ -2,166 +2,192 @@ # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #++ +require 'strscan' -# Boring stuff with strings. -module MaRuKu; module Strings - - def add_tabs(s,n=1,char="\t") - s.split("\n").map{|x| char*n+x }.join("\n") - end - - TabSize = 4; - - def split_lines(s) - s.gsub("\r","").split("\n") - end - - # This parses email headers. Returns an hash. - # - # +hash['data']+ is the message. - # - # Keys are downcased, space becomes underscore, converted to symbols. - # - # My key: true - # - # becomes: - # - # {:my_key => true} - # - def parse_email_headers(s) - keys={} - match = (s =~ /\A((\w[\w \t\_\-]+: .*?\n)+)\s*?\n/) - if match != 0 - keys[:data] = s - else - keys[:data] = $' - headers = $1 - headers.split("\n").each do |l| -# Fails if there are other ':' characters. -# k, v = l.split(':') - k, v = l.split(':', 2) - k, v = normalize_key_and_value(k, v) - k = k.to_sym -# puts "K = #{k}, V=#{v}" - keys[k] = v - end - end - keys - end +module MaRuKu + # Utility functions for dealing with strings. + module Strings + TAB_SIZE = 4 - # Keys are downcased, space becomes underscore, converted to symbols. - def normalize_key_and_value(k,v) - v = v ? v.strip : true # no value defaults to true - k = k.strip - - # check synonyms - v = true if ['yes','true'].include?(v.to_s.downcase) - v = false if ['no','false'].include?(v.to_s.downcase) - - k = k.downcase.gsub(' ','_') - return k, v - end - - # Returns the number of leading spaces, considering that - # a tab counts as `TabSize` spaces. - def number_of_leading_spaces(s) - s[/^[ \t]*/].gsub("\t", ' '*TabSize).length - end + # Split a string into multiple lines, + # on line feeds and/or carriage returns. + # + # @param s [String] + # @return [String] + def split_lines(s) + s.split(/\r\n|\r|\n/) + end - # This returns the position of the first real char in a list item - # - # For example: - # '*Hello' # => 1 - # '* Hello' # => 2 - # ' * Hello' # => 3 - # ' * Hello' # => 5 - # '1.Hello' # => 2 - # ' 1. Hello' # => 5 - - def spaces_before_first_char(s) - case s.md_type - when :ulist - # whitespace, followed by ('*'|'+'|'-') followed by - # more whitespace, followed by an optional IAL, followed - # by yet more whitespace - h=s[/^\s*(\*|\+|\-)\s*(\{.*?\})?\s*/] - when :olist - # whitespace, followed by a number, followed by a period, - # more whitespace, an optional IAL, and more whitespace - h=s[/^\s*\d+\.\s*(\{.*?\})?\s*/] - else - tell_user "BUG (my bad): '#{s}' is not a list" - h='' - end - ial = h[/\{.*\}/] - return [h.length, ial] - end + # Parses email headers, returning a hash. + # `hash[:data]` is the message; + # that is, anything past the headers. + # + # Keys are downcased and converted to symbols; + # spaces become underscores. For example: + # + # !!!plain + # My key: true + # + # becomes: + # + # {:my_key => true} + # + # @param s [String] The email + # @return [Symbol => String] The header values + def parse_email_headers(s) + headers = {} + scanner = StringScanner.new(s) - # Counts the number of leading '#' in the string - def num_leading_hashes(s) - h = s[/^#*/] - h ? h.length : 0 - end - - # Strips initial and final hashes - def strip_hashes(s) - s.sub(/^#*(.*?)(#|\s)*$/, '\1').strip - end - - # change space to "_" and remove any non-word character - def sanitize_ref_id(x) - x.downcase.gsub(' ','_').gsub(/[^\w]/,'') - end + while scanner.scan(/(\w[\w\s\-]+): +(.*)\n/) + k, v = normalize_key_and_value(scanner[1], scanner[2]) + headers[k.to_sym] = v + end + headers[:data] = scanner.rest + headers + end - # removes initial quote - def unquote(s) - s.gsub(/^>\s?/,'') - end + # Returns the number of leading spaces, + # considering that a tab counts as {TAB_SIZE} spaces. + # + # @param s [String] + # @return [Fixnum] + def number_of_leading_spaces(s) + spaces = s.scan(/^\s*/).first + spaces.count(" ") + spaces.count("\t") * TAB_SIZE + end - # toglie al massimo n caratteri - def strip_indent(s, n) - i = 0 - while i < s.size && n>0 - c = s[i,1] - if c == ' ' - n-=1; - elsif c == "\t" - n-=TabSize; - else - break - end - i+=1 - end - s[i, s.size] - end + # This returns the position of the first non-list character + # in a list item. + # + # @example + # spaces_before_first_char('*Hello') #=> 1 + # spaces_before_first_char('* Hello') #=> 2 + # spaces_before_first_char(' * Hello') #=> 3 + # spaces_before_first_char(' * Hello') #=> 5 + # spaces_before_first_char('1.Hello') #=> 2 + # spaces_before_first_char(' 1. Hello') #=> 5 + # + # @param s [String] + # @return [Fixnum] + def spaces_before_first_char(s) + match = + case s.md_type + when :ulist + # whitespace, followed by ('*'|'+'|'-') followed by + # more whitespace, followed by an optional IAL, followed + # by yet more whitespace + s[/^\s*(\*|\+|\-)\s*(\{.*?\})?\s*/] + when :olist + # whitespace, followed by a number, followed by a period, + # more whitespace, an optional IAL, and more whitespace + s[/^\s*\d+\.\s*(\{.*?\})?\s*/] + else + tell_user "BUG (my bad): '#{s}' is not a list" + '' + end + ial = match[/\{.*\}/] + return [match.length, ial] + end - def dbg_describe_ary(a, prefix='') - i = 0 - a.each do |l| - puts "#{prefix} (#{i+=1})# #{l.inspect}" - end - end + # Replace spaces with underscores and remove non-word characters. + # + # @param s [String] + # @return [String] + def sanitize_ref_id(s) + s.strip.downcase.gsub(' ', '_').gsub(/[^\w]/, '') + end - def force_linebreak?(l) - l =~ / $/ - end + # Remove line-initial `>` characters for a quotation. + # + # @param s [String] + # @return [String] + def unquote(s) + s.gsub(/^>\s?/, '') + end -end + # Removes indentation from the beginning of `s`, + # up to at most `n` spaces. + # Tabs are counted as {TAB_SIZE} spaces. + # + # @param s [String] + # @param n [Fixnum] + # @return [String] + def strip_indent(s, n) + while n > 0 + case s[0] + when ?\s; n -= 1 + when ?\t; n -= TAB_SIZE + else; return s + end + s = s[1..-1] + end + return s + end + + # Escapes a string so that it can be safely used in a Bourne shell command line. + # + # Note that a resulted string should be used unquoted + # and is not intended for use in double quotes nor in single quotes. + # + # This is a copy of the Shellwords.shellescape function in Ruby 1.8.7. + # It's included for Ruby 1.8.6 compatibility. + # + # @param str [String] + # @return [String] + def shellescape(str) + # An empty argument will be skipped, so return empty quotes. + return "''" if str.empty? + + str = str.dup + + # Process as a single byte sequence because not all shell + # implementations are multibyte aware. + str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/n, "\\\\\\1") + + # A LF cannot be escaped with a backslash because a backslash + LF + # combo is regarded as line continuation and simply ignored. + str.gsub!(/\n/, "'\n'") + + return str + end + + private + + # Normalize the key/value pairs for email headers. + # Keys are downcased and converted to symbols; + # spaces become underscores. + # + # Values of `"yes"`, `"true"`, `"no"`, and `"false"` + # are converted to appropriate booleans. + # + # @param k [String] + # @param v [String] + # @return [Array(String, String or Boolean)] + def normalize_key_and_value(k, v) + k = k.strip.downcase.gsub(/\s+/, '_') + v = v.strip + + # check synonyms + return k, true if %w[yes true].include?(v.downcase) + return k, false if %w[no false].include?(v.downcase) + return k, v + end + end end diff --git a/vendor/plugins/maruku/lib/maruku/structures.rb b/vendor/plugins/maruku/lib/maruku/structures.rb index 0bb69e58..3920b772 100644 --- a/vendor/plugins/maruku/lib/maruku/structures.rb +++ b/vendor/plugins/maruku/lib/maruku/structures.rb @@ -1,170 +1,143 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ - -class Module - def safe_attr_accessor1(symbol, klass) - attr_reader symbol - code = <<-EOF - def #{symbol}=(val) - if not val.kind_of? #{klass} - s = "\nCould not assign an object of type \#{val.class} to #{symbol}.\n\n" - s += "Tried to assign object of class \#{val.class}:\n"+ - "\#{val.inspect}\n"+ - "to \#{self.class}::#{symbol} constrained to be of class #{klass}.\n" - raise s - end - @#{symbol} = val - end - -EOF - module_eval code - end - - def safe_attr_accessor2(symbol, klass) - attr_accessor symbol - end - - alias safe_attr_accessor safe_attr_accessor2 -end - module MaRuKu - -# I did not want to have a class for each possible element. -# Instead I opted to have only the class "MDElement" -# that represents eveything in the document (paragraphs, headers, etc). -# -# You can tell what it is by the variable `node_type`. -# -# In the instance-variable `children` there are the children. These -# can be of class 1) String or 2) MDElement. -# -# The @doc variable points to the document to which the MDElement -# belongs (which is an instance of Maruku, subclass of MDElement). -# -# Attributes are contained in the hash `attributes`. -# Keys are symbols (downcased, with spaces substituted by underscores) -# -# For example, if you write in the source document. -# -# Title: test document -# My property: value -# -# content content -# -# You can access `value` by writing: -# -# @doc.attributes[:my_property] # => 'value' -# -# from whichever MDElement in the hierarchy. -# -class MDElement - # See helpers.rb for the list of allowed #node_type values - safe_attr_accessor :node_type, Symbol - - # Children are either Strings or MDElement - safe_attr_accessor :children, Array - - # An attribute list, may not be nil - safe_attr_accessor :al, Array #Maruku::AttributeList + # Rather than having a separate class for every possible element, + # Maruku has a single {MDElement} class + # that represents eveything in the document (paragraphs, headers, etc). + # The type of each element is available via \{#node\_type}. + class MDElement + # The type of this node (e.g. `:quote`, `:image`, `:abbr`). + # See {Helpers} for a list of possible values. + # + # @return [Symbol] + attr_accessor :node_type - # These are the processed attributes - safe_attr_accessor :attributes, Hash - - # Reference of the document (which is of class Maruku) - attr_accessor :doc - - def initialize(node_type=:unset, children=[], meta={}, - al=MaRuKu::AttributeList.new ) - super(); - self.children = children - self.node_type = node_type - - @attributes = {} - - meta.each do |symbol, value| - self.instance_eval " - def #{symbol}; @#{symbol}; end - def #{symbol}=(val); @#{symbol}=val; end" - self.send "#{symbol}=", value - end - - self.al = al || AttributeList.new + # The child nodes of this element. + # + # @return [Array] + attr_accessor :children - self.meta_priv = meta - end - - attr_accessor :meta_priv - - def ==(o) - ok = o.kind_of?(MDElement) && - (self.node_type == o.node_type) && - (self.meta_priv == o.meta_priv) && - (self.children == o.children) - - if not ok -# puts "This:\n"+self.inspect+"\nis different from\n"+o.inspect+"\n\n" - end - ok - end + # An attribute list. May not be nil. + # + # @return [AttributeList] + attr_accessor :al + + # The processed attributes. + # + # For the {Maruku document root}, + # this contains properties listed + # at the beginning of the document. + # The properties will be downcased and any spaces + # will be converted to underscores. + # For example, if you write in the source document: + # + # !!!text + # Title: test document + # My property: value + # + # content content + # + # Then \{#attributes} will return: + # + # {:title => "test document", :my_property => "value"} + # + # @return [{Symbol => String}] + attr_accessor :attributes + + # The root element of the document + # to which this element belongs. + # + # @return [Maruku] + attr_accessor :doc + + def initialize(node_type = :unset, children = [], meta = {}, al = nil) + self.children = children + self.node_type = node_type + self.attributes = {} + + meta.each do |symbol, value| + self.instance_eval <"+self[k].inspect}.join(',')+"}" - end -end - module MaRuKu -class MDElement - def inspect(compact=true) - if compact - i2 = inspect2 - return i2 if i2 - end - - "md_el(:%s,%s,%s,%s)" % - [ - self.node_type, - children_inspect(compact), - @meta_priv.inspect_ordered, - self.al.inspect - ] - end + class MDElement + def inspect(compact=true) + if compact + i2 = inspect2 + return i2 if i2 + end - def children_inspect(compact=true) - s = @children.inspect_more(compact,', ') - if @children.empty? - "[]" - elsif s.size < 70 - s - else - "[\n"+ - add_tabs(@children.inspect_more(compact,",\n",false))+ - "\n]" - end - end - + # Make sure the attributes are lexically ordered + meta_ordered = "{" + @meta_priv.keys. + map {|x| x.to_s}.sort.map {|x| x.to_sym}. + map {|k| k.inspect + "=>" + @meta_priv[k].inspect}. + join(',') + "}" + + "md_el(%s,%s,%s,%s)" % [ + self.node_type.inspect, + children_inspect(compact), + meta_ordered, + self.al.inspect + ] + end + + def children_inspect(compact=true) + kids = @children.map {|x| x.is_a?(MDElement) ? x.inspect(compact) : x.inspect} + comma = kids.join(", ") + + return "[#{comma}]" if comma.size < 70 + "[\n\t#{kids.join(",\n\t")}\n]" + end + + end end - -end - diff --git a/vendor/plugins/maruku/lib/maruku/structures_iterators.rb b/vendor/plugins/maruku/lib/maruku/structures_iterators.rb index ff9c6b43..cc5c769c 100644 --- a/vendor/plugins/maruku/lib/maruku/structures_iterators.rb +++ b/vendor/plugins/maruku/lib/maruku/structures_iterators.rb @@ -1,61 +1,48 @@ -#-- # Copyright (C) 2006 Andrea Censi # # This file is part of Maruku. -# +# # Maruku is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # Maruku is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with Maruku; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ module MaRuKu + class MDElement + # Iterates through each {MDElement} child node of this element. + # This includes deeply-nested child nodes. + # If `e_node_type` is specified, only yields nodes of that type. + def each_element(e_node_type=nil, &block) + @children.each do |c| + next unless c.is_a? MDElement + yield c if e_node_type.nil? || c.node_type == e_node_type + c.each_element(e_node_type, &block) + end + end -class MDElement - - # Yields to each element of specified node_type - # All elements if e_node_type is nil. - def each_element(e_node_type=nil, &block) - @children.each do |c| - if c.kind_of? MDElement - if (not e_node_type) || (e_node_type == c.node_type) - block.call c - end - c.each_element(e_node_type, &block) - end - end - end - - # Apply passed block to each String in the hierarchy. - def replace_each_string(&block) - for c in @children - if c.kind_of? MDElement - c.replace_each_string(&block) - end - end - - processed = [] - until @children.empty? - c = @children.shift - if c.kind_of? String - result = block.call(c) - [*result].each do |e| processed << e end - else - processed << c - end - end - @children = processed - end - + # Iterates through each String child node of this element, + # replacing it with the result of the block. + # This includes deeply-nested child nodes. + # + # This destructively modifies this node and its children. + # + # @todo Make this non-destructive + def replace_each_string(&block) + @children.map! do |c| + next yield c unless c.is_a?(MDElement) + c.replace_each_string(&block) + c + end.flatten! + end + end end -end \ No newline at end of file diff --git a/vendor/plugins/maruku/lib/maruku/tests/benchmark.rb b/vendor/plugins/maruku/lib/maruku/tests/benchmark.rb deleted file mode 100644 index 21d4a935..00000000 --- a/vendor/plugins/maruku/lib/maruku/tests/benchmark.rb +++ /dev/null @@ -1,82 +0,0 @@ -#-- -# Copyright (C) 2006 Andrea Censi -# -# This file is part of Maruku. -# -# Maruku is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Maruku is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Maruku; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ - - -require 'maruku' -#require 'bluecloth' - - -data = $stdin.read - -num = 10 - -if ARGV.size > 0 && ((n=ARGV[0].to_i) != 0) - num = n -end - -methods = -[ - - [Maruku, :to_html], -# [BlueCloth, :to_html], - [Maruku, :to_latex] - -] - -#methods = [[Maruku, :class]] -#num = 10 - -stats = -methods .map do |c, method| - puts "Computing for #{c}" - - start = Time.now - doc = nil - for i in 1..num - $stdout.write "#{i} "; $stdout.flush - doc = c.new(data) - end - stop = Time.now - parsing = (stop-start)/num - - start = Time.now - for i in 1..num - $stdout.write "#{i} "; $stdout.flush - s = doc.send method - end - stop = Time.now - rendering = (stop-start)/num - - puts ("%s (%s): parsing %0.2f sec + rendering %0.2f sec "+ - "= %0.2f sec ") % [c, method, parsing,rendering,parsing+rendering] - - [c, method, parsing, rendering] -end - -puts "\n\n\n" -stats.each do |x| x.push(x[2]+x[3]) end -max = stats.map{|x|x[4]}.max -stats.sort! { |x,y| x[4] <=> y[4] } . reverse! -for c, method, parsing, rendering, tot in stats - puts ("%20s: parsing %0.2f sec + rendering %0.2f sec "+ - "= %0.2f sec (%0.2fx)") % - ["#{c} (#{method})", parsing,rendering,tot,max/tot] -end - diff --git a/vendor/plugins/maruku/lib/maruku/tests/new_parser.rb b/vendor/plugins/maruku/lib/maruku/tests/new_parser.rb deleted file mode 100644 index 8a014833..00000000 --- a/vendor/plugins/maruku/lib/maruku/tests/new_parser.rb +++ /dev/null @@ -1,373 +0,0 @@ -#-- -# Copyright (C) 2006 Andrea Censi -# -# This file is part of Maruku. -# -# Maruku is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# Maruku is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Maruku; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -#++ - - -require 'maruku' -require 'maruku/ext/math' - -module MaRuKu; module Tests - # 5 accented letters in italian, encoded as UTF-8 - AccIta8 = "\303\240\303\250\303\254\303\262\303\271" - - # Same letters, written in ISO-8859-1 (one byte per letter) - AccIta1 = "\340\350\354\362\371" - - # The word MA-RU-KU, written in katakana using UTF-8 - Maruku8 = "\343\203\236\343\203\253\343\202\257" - - def test_span_parser(verbose, break_on_first_error, quiet) - good_cases = [ - - ["", [], 'Empty string gives empty list'], - ["a", ["a"], 'Easy char'], - [" a", ["a"], 'First space in the paragraph is ignored'], - ["a\n \n", ["a"], 'Last spaces in the paragraphs are ignored'], - [' ', [], 'One char => nothing'], - [' ', [], 'Two chars => nothing'], - ['a b', ['a b'], 'Spaces are compressed'], - ['a b', ['a b'], 'Newlines are spaces'], - ["a\nb", ['a b'], 'Newlines are spaces'], - ["a\n b", ['a b'], 'Compress newlines 1'], - ["a \nb", ['a b'], 'Compress newlines 2'], - [" \nb", ['b'], 'Compress newlines 3'], - ["\nb", ['b'], 'Compress newlines 4'], - ["b\n", ['b'], 'Compress newlines 5'], - ["\n", [], 'Compress newlines 6'], - ["\n\n\n", [], 'Compress newlines 7'], - - [nil, :throw, "Should throw on nil input"], - - # Code blocks - ["`" , :throw, 'Unclosed single ticks'], - ["``" , :throw, 'Unclosed double ticks'], - ["`a`" , [md_code('a')], 'Simple inline code'], - ["`` ` ``" , [md_code('`')], ], - ["`` \\` ``" , [md_code('\\`')], ], - ["``a``" , [md_code('a')], ], - ["`` a ``" , [md_code('a')], ], - - # Newlines - ["a \n", ['a',md_el(:linebreak)], 'Two spaces give br.'], - ["a \n", ['a'], 'Newlines 2'], - [" \n", [md_el(:linebreak)], 'Newlines 3'], - [" \n \n", [md_el(:linebreak),md_el(:linebreak)],'Newlines 3'], - [" \na \n", [md_el(:linebreak),'a',md_el(:linebreak)],'Newlines 3'], - - # Inline HTML - ["a < b", ['a < b'], '< can be on itself'], - ["
", [md_html('
')], 'HR will be sanitized'], - ["
", [md_html('
')], 'Closed tag is ok'], - ["
", [md_html('
')], 'Closed tag is ok 2'], - ["
a", [md_html('
'),'a'], 'Closed tag is ok 2'], - ["a", [md_html(''),'a'], 'Inline HTML 1'], - ["ea", [md_html('e'),'a'], 'Inline HTML 2'], - ["aeb", ['a',md_html('e'),'b'], 'Inline HTML 3'], - ["eaf", - [md_html('e'),'a',md_html('f')], - 'Inline HTML 4'], - ["efa", - [md_html('e'),md_html('f'),'a'], - 'Inline HTML 5'], - - ["", [md_html("")], 'Attributes'], - [""], - - # emphasis - ["**", :throw, 'Unclosed double **'], - ["\\*", ['*'], 'Escaping of *'], - ["a *b* ", ['a ', md_em('b')], 'Emphasis 1'], - ["a *b*", ['a ', md_em('b')], 'Emphasis 2'], - ["a * b", ['a * b'], 'Emphasis 3'], - ["a * b*", :throw, 'Unclosed emphasis'], - # same with underscore - ["__", :throw, 'Unclosed double __'], - ["\\_", ['_'], 'Escaping of _'], - ["a _b_ ", ['a ', md_em('b')], 'Emphasis 4'], - ["a _b_", ['a ', md_em('b')], 'Emphasis 5'], - ["a _ b", ['a _ b'], 'Emphasis 6'], - ["a _ b_", :throw, 'Unclosed emphasis'], - ["_b_", [md_em('b')], 'Emphasis 7'], - ["_b_ _c_", [md_em('b'),' ',md_em('c')], 'Emphasis 8'], - ["_b__c_", [md_em('b'),md_em('c')], 'Emphasis 9'], - # underscores in word - ["mod_ruby", ['mod_ruby'], 'Word with underscore'], - # strong - ["**a*", :throw, 'Unclosed double ** 2'], - ["\\**a*", ['*', md_em('a')], 'Escaping of *'], - ["a **b** ", ['a ', md_strong('b')], 'Emphasis 1'], - ["a **b**", ['a ', md_strong('b')], 'Emphasis 2'], - ["a ** b", ['a ** b'], 'Emphasis 3'], - ["a ** b**", :throw, 'Unclosed emphasis'], - ["**b****c**", [md_strong('b'),md_strong('c')], 'Emphasis 9'], - # strong (with underscore) - ["__a_", :throw, 'Unclosed double __ 2'], - - # ["\\__a_", ['_', md_em('a')], 'Escaping of _'], - ["a __b__ ", ['a ', md_strong('b')], 'Emphasis 1'], - ["a __b__", ['a ', md_strong('b')], 'Emphasis 2'], - ["a __ b", ['a __ b'], 'Emphasis 3'], - ["a __ b__", :throw, 'Unclosed emphasis'], - ["__b____c__", [md_strong('b'),md_strong('c')], 'Emphasis 9'], - # extra strong - ["***a**", :throw, 'Unclosed triple *** '], - ["\\***a**", ['*', md_strong('a')], 'Escaping of *'], - ["a ***b*** ", ['a ', md_emstrong('b')], 'Strong elements'], - ["a ***b***", ['a ', md_emstrong('b')]], - ["a *** b", ['a *** b']], - ["a ** * b", ['a ** * b']], - ["***b******c***", [md_emstrong('b'),md_emstrong('c')]], - ["a *** b***", :throw, 'Unclosed emphasis'], - # same with underscores - ["___a__", :throw, 'Unclosed triple *** '], -# ["\\___a__", ['_', md_strong('a')], 'Escaping of _'], - ["a ___b___ ", ['a ', md_emstrong('b')], 'Strong elements'], - ["a ___b___", ['a ', md_emstrong('b')]], - ["a ___ b", ['a ___ b']], - ["a __ _ b", ['a __ _ b']], - ["___b______c___", [md_emstrong('b'),md_emstrong('c')]], - ["a ___ b___", :throw, 'Unclosed emphasis'], - # mixing is bad - ["*a_", :throw, 'Mixing is bad'], - ["_a*", :throw], - ["**a__", :throw], - ["__a**", :throw], - ["___a***", :throw], - ["***a___", :throw], - # links of the form [text][ref] - ["\\[a]", ["[a]"], 'Escaping 1'], - ["\\[a\\]", ["[a]"], 'Escaping 2'], -# This is valid in the new Markdown version -# ["[a]", ["a"], 'Not a link'], - ["[a]", [ md_link(["a"],'a')], 'Empty link'], - ["[a][]", ], - ["[a][]b", [ md_link(["a"],'a'),'b'], 'Empty link'], - ["[a\\]][]", [ md_link(["a]"],'a')], 'Escape inside link (throw ?] away)'], - - ["[a", :throw, 'Link not closed'], - ["[a][", :throw, 'Ref not closed'], - - # links of the form [text](url) - ["\\[a](b)", ["[a](b)"], 'Links'], - ["[a](url)c", [md_im_link(['a'],'url'),'c'], 'url'], - ["[a]( url )c" ], - ["[a] ( url )c" ], - ["[a] ( url)c" ], - - ["[a](ur:/l/ 'Title')", [md_im_link(['a'],'ur:/l/','Title')], - 'url and title'], - ["[a] ( ur:/l/ \"Title\")" ], - ["[a] ( ur:/l/ \"Title\")" ], - ["[a]( ur:/l/ Title)", :throw, "Must quote title" ], - - ["[a](url 'Tit\\\"l\\\\e')", [md_im_link(['a'],'url','Tit"l\\e')], - 'url and title escaped'], - ["[a] ( url \"Tit\\\"l\\\\e\")" ], - ["[a] ( url \"Tit\\\"l\\\\e\" )" ], - ['[a] ( url "Tit\\"l\\\\e" )' ], - ["[a]()", [md_im_link(['a'],'')], 'No URL is OK'], - - ["[a](\"Title\")", :throw, "No url specified" ], - ["[a](url \"Title)", :throw, "Unclosed quotes" ], - ["[a](url \"Title\\\")", :throw], - ["[a](url \"Title\" ", :throw], - - ["[a](url \'Title\")", :throw, "Mixing is bad" ], - ["[a](url \"Title\')"], - - ["[a](/url)", [md_im_link(['a'],'/url')], 'Funny chars in url'], - ["[a](#url)", [md_im_link(['a'],'#url')]], - ["[a]()", [md_im_link(['a'],'/script?foo=1&bar=2')]], - - - # Images - ["\\![a](url)", ['!', md_im_link(['a'],'url') ], 'Escaping images'], - - ["![a](url)", [md_im_image(['a'],'url')], 'Image no title'], - ["![a]( url )" ], - ["![a] ( url )" ], - ["![a] ( url)" ], - - ["![a](url 'ti\"tle')", [md_im_image(['a'],'url','ti"tle')], 'Image with title'], - ['![a]( url "ti\\"tle")' ], - - ["![a](url", :throw, 'Invalid images'], - ["![a( url )" ], - ["![a] ('url )" ], - - ["![a][imref]", [md_image(['a'],'imref')], 'Image with ref'], - ["![a][ imref]"], - ["![a][ imref ]"], - ["![a][\timref\t]"], - - - ['', - [md_url('http://example.com/?foo=1&bar=2')], 'Immediate link'], - ['ab', - ['a',md_url('http://example.com/?foo=1&bar=2'),'b'] ], - ['', - [md_email('andrea@censi.org')], 'Email address'], - [''], - ["Developmen ", - ["Developmen ", md_url("http://rubyforge.org/projects/maruku/")]], - ["ab", ['a',md_html(''),'b'], - 'HTML Comment'], - - ["a