wikicloth 0.2.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +3 -1
- data/lib/wikicloth/calc.citrus +133 -0
- data/lib/wikicloth/core_ext.rb +12 -0
- data/lib/wikicloth/math.rb +155 -0
- data/lib/wikicloth/parser.rb +7 -7
- data/lib/wikicloth/section.rb +5 -1
- data/lib/wikicloth/wiki_buffer/template.rb +32 -0
- data/lib/wikicloth/wiki_buffer/var.rb +77 -9
- data/lib/wikicloth/wiki_link_handler.rb +25 -9
- data/lib/wikicloth.rb +13 -19
- metadata +21 -4
    
        data/Rakefile
    CHANGED
    
    | @@ -2,6 +2,7 @@ require 'rake' | |
| 2 2 | 
             
            require 'rake/testtask'
         | 
| 3 3 | 
             
            require 'rake/rdoctask'
         | 
| 4 4 | 
             
            require 'rake/gempackagetask'
         | 
| 5 | 
            +
            require 'init'
         | 
| 5 6 |  | 
| 6 7 | 
             
            desc 'Default: run unit tests.'
         | 
| 7 8 | 
             
            task :default => :test
         | 
| @@ -25,7 +26,7 @@ end | |
| 25 26 |  | 
| 26 27 | 
             
            spec = Gem::Specification.new do |s|
         | 
| 27 28 | 
             
              s.name = "wikicloth"
         | 
| 28 | 
            -
              s.version =  | 
| 29 | 
            +
              s.version = WikiCloth::VERSION
         | 
| 29 30 | 
             
              s.author = "David Ricciardi"
         | 
| 30 31 | 
             
              s.email = "nricciar@gmail.com"
         | 
| 31 32 | 
             
              s.homepage = "http://github.com/nricciar/wikicloth"
         | 
| @@ -41,6 +42,7 @@ spec = Gem::Specification.new do |s| | |
| 41 42 | 
             
              s.extra_rdoc_files = ["README","MIT-LICENSE"]
         | 
| 42 43 | 
             
              s.description = %q{mediawiki parser}
         | 
| 43 44 | 
             
              s.add_dependency 'builder'
         | 
| 45 | 
            +
              s.add_dependency 'expression_parser'
         | 
| 44 46 | 
             
            end
         | 
| 45 47 | 
             
            Rake::GemPackageTask.new(spec) do |pkg|
         | 
| 46 48 | 
             
                pkg.need_tar = true
         | 
| @@ -0,0 +1,133 @@ | |
| 1 | 
            +
            # A grammar for mathematical formulas that apply basic mathematical operations
         | 
| 2 | 
            +
            # to all numbers, respecting operator precedence and grouping of expressions
         | 
| 3 | 
            +
            # while ignoring whitespace.
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # An identical grammar that is written using pure Ruby can be found in calc.rb.
         | 
| 6 | 
            +
            grammar Calc
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              ## Hierarchy
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              rule term
         | 
| 11 | 
            +
                additive | factor
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              rule additive
         | 
| 15 | 
            +
                (factor additive_operator term) {
         | 
| 16 | 
            +
                  def value
         | 
| 17 | 
            +
                    additive_operator.apply(factor.value, term.value)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                }
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              rule factor
         | 
| 23 | 
            +
                multiplicative | prefix
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              rule multiplicative
         | 
| 27 | 
            +
                (prefix multiplicative_operator factor) {
         | 
| 28 | 
            +
                  def value
         | 
| 29 | 
            +
                    multiplicative_operator.apply(prefix.value, factor.value)
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              rule prefix
         | 
| 35 | 
            +
                prefixed | exponent
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              rule prefixed
         | 
| 39 | 
            +
                (unary_operator prefix) {
         | 
| 40 | 
            +
                  def value
         | 
| 41 | 
            +
                    unary_operator.apply(prefix.value)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                }
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              rule exponent
         | 
| 47 | 
            +
                exponential | primary
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              rule exponential
         | 
| 51 | 
            +
                (primary exponential_operator exponent) {
         | 
| 52 | 
            +
                  def value
         | 
| 53 | 
            +
                    exponential_operator.apply(primary.value, exponent.value)
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                }
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              rule primary
         | 
| 59 | 
            +
                group | number
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              rule group
         | 
| 63 | 
            +
                (lparen term rparen) {
         | 
| 64 | 
            +
                  def value
         | 
| 65 | 
            +
                    term.value
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
                }
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              ## Syntax
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              rule number
         | 
| 73 | 
            +
                float | integer
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              rule float
         | 
| 77 | 
            +
                (digits '.' digits space) {
         | 
| 78 | 
            +
                  def value
         | 
| 79 | 
            +
                    text.strip.to_f
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                }
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              rule integer
         | 
| 85 | 
            +
                (digits space) {
         | 
| 86 | 
            +
                  def value
         | 
| 87 | 
            +
                    text.strip.to_i
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
                }
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              rule digits
         | 
| 93 | 
            +
                [0-9]+ ('_' [0-9]+)*
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              rule additive_operator
         | 
| 97 | 
            +
                (('+' | '-') space) {
         | 
| 98 | 
            +
                  def apply(n1, n2)
         | 
| 99 | 
            +
                    n1.send(text.strip, n2)
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
                }
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              rule multiplicative_operator
         | 
| 105 | 
            +
                (('*' | '/' | '%') space) {
         | 
| 106 | 
            +
                  def apply(n1, n2)
         | 
| 107 | 
            +
                    n1.send(text.strip, n2)
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                }
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              rule exponential_operator
         | 
| 113 | 
            +
                ('**' space) {
         | 
| 114 | 
            +
                  def apply(n1, n2)
         | 
| 115 | 
            +
                    n1 ** n2
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
                }
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
              rule unary_operator
         | 
| 121 | 
            +
                (('~' | '+' | '-') space) {
         | 
| 122 | 
            +
                  def apply(n)
         | 
| 123 | 
            +
                    op = text.strip
         | 
| 124 | 
            +
                    # Unary + and - require an @.
         | 
| 125 | 
            +
                    n.send(op == '~' ? op : '%s@' % op)
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
                }
         | 
| 128 | 
            +
              end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
              rule lparen '(' space end
         | 
| 131 | 
            +
              rule rparen ')' space end
         | 
| 132 | 
            +
              rule space [ \t\n\r]* end
         | 
| 133 | 
            +
            end
         | 
    
        data/lib/wikicloth/core_ext.rb
    CHANGED
    
    | @@ -19,6 +19,14 @@ class Object | |
| 19 19 | 
             
              end
         | 
| 20 20 | 
             
            end
         | 
| 21 21 |  | 
| 22 | 
            +
            module Math
         | 
| 23 | 
            +
              def self.eval(expression)
         | 
| 24 | 
            +
                allowed_characters = Regexp.escape('+-*/.() ')
         | 
| 25 | 
            +
                safe_expression = expression.match(/[\d#{allowed_characters}]*/).to_s
         | 
| 26 | 
            +
                Kernel.eval(safe_expression)
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| 29 | 
            +
             | 
| 22 30 | 
             
            module ExtendedString
         | 
| 23 31 |  | 
| 24 32 | 
             
              def blank?
         | 
| @@ -37,6 +45,10 @@ module ExtendedString | |
| 37 45 | 
             
                to_s
         | 
| 38 46 | 
             
              end
         | 
| 39 47 |  | 
| 48 | 
            +
              def last(n)
         | 
| 49 | 
            +
                self[-n,n]
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 40 52 | 
             
              def dump()
         | 
| 41 53 | 
             
                ret = to_s
         | 
| 42 54 | 
             
                delete!(to_s)
         | 
| @@ -0,0 +1,155 @@ | |
| 1 | 
            +
            # The following code taken from http://lukaszwrobel.pl/blog/math-parser-part-3-implementation
         | 
| 2 | 
            +
            module WikiCloth
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Token
         | 
| 5 | 
            +
              Plus     = 0
         | 
| 6 | 
            +
              Minus    = 1
         | 
| 7 | 
            +
              Multiply = 2
         | 
| 8 | 
            +
              Divide   = 3
         | 
| 9 | 
            +
              
         | 
| 10 | 
            +
              Number   = 4
         | 
| 11 | 
            +
              
         | 
| 12 | 
            +
              LParen   = 5
         | 
| 13 | 
            +
              RParen   = 6
         | 
| 14 | 
            +
              
         | 
| 15 | 
            +
              End      = 7
         | 
| 16 | 
            +
              
         | 
| 17 | 
            +
              attr_accessor :kind
         | 
| 18 | 
            +
              attr_accessor :value
         | 
| 19 | 
            +
              
         | 
| 20 | 
            +
              def initialize
         | 
| 21 | 
            +
                @kind = nil
         | 
| 22 | 
            +
                @value = nil
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              def unknown?
         | 
| 26 | 
            +
                @kind.nil?
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            class Lexer
         | 
| 31 | 
            +
              def initialize(input)
         | 
| 32 | 
            +
                @input = input
         | 
| 33 | 
            +
                @return_previous_token = false
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
              
         | 
| 36 | 
            +
              def get_next_token
         | 
| 37 | 
            +
                if @return_previous_token
         | 
| 38 | 
            +
                  @return_previous_token = false
         | 
| 39 | 
            +
                  return @previous_token
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
                
         | 
| 42 | 
            +
                token = Token.new
         | 
| 43 | 
            +
                
         | 
| 44 | 
            +
                @input.lstrip!
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                case @input
         | 
| 47 | 
            +
                  when /\A\+/ then
         | 
| 48 | 
            +
                    token.kind = Token::Plus
         | 
| 49 | 
            +
                  when /\A-/ then
         | 
| 50 | 
            +
                    token.kind = Token::Minus
         | 
| 51 | 
            +
                  when /\A\*/ then
         | 
| 52 | 
            +
                    token.kind = Token::Multiply
         | 
| 53 | 
            +
                  when /\A\// then
         | 
| 54 | 
            +
                    token.kind = Token::Divide
         | 
| 55 | 
            +
                  when /\A\d+(\.\d+)?/
         | 
| 56 | 
            +
                    token.kind = Token::Number
         | 
| 57 | 
            +
                    token.value = $&.to_f
         | 
| 58 | 
            +
                  when /\A\(/
         | 
| 59 | 
            +
                    token.kind = Token::LParen
         | 
| 60 | 
            +
                  when /\A\)/
         | 
| 61 | 
            +
                    token.kind = Token::RParen
         | 
| 62 | 
            +
                  when ''
         | 
| 63 | 
            +
                    token.kind = Token::End
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
                
         | 
| 66 | 
            +
                raise 'Unknown token' if token.unknown?
         | 
| 67 | 
            +
                @input = $'
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                @previous_token = token
         | 
| 70 | 
            +
                token
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
              
         | 
| 73 | 
            +
              def revert
         | 
| 74 | 
            +
                @return_previous_token = true
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            class MathParser
         | 
| 79 | 
            +
              def parse(input)
         | 
| 80 | 
            +
                @lexer = Lexer.new(input)
         | 
| 81 | 
            +
                
         | 
| 82 | 
            +
                expression_value = expression
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                token = @lexer.get_next_token
         | 
| 85 | 
            +
                if token.kind == Token::End
         | 
| 86 | 
            +
                  expression_value
         | 
| 87 | 
            +
                else
         | 
| 88 | 
            +
                  raise 'End expected'
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
              
         | 
| 92 | 
            +
              protected
         | 
| 93 | 
            +
              def expression
         | 
| 94 | 
            +
                component1 = factor
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                additive_operators = [Token::Plus, Token::Minus]
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                token = @lexer.get_next_token
         | 
| 99 | 
            +
                while additive_operators.include?(token.kind)
         | 
| 100 | 
            +
                  component2 = factor
         | 
| 101 | 
            +
                  
         | 
| 102 | 
            +
                  if token.kind == Token::Plus
         | 
| 103 | 
            +
                    component1 += component2
         | 
| 104 | 
            +
                  else
         | 
| 105 | 
            +
                    component1 -= component2
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  token = @lexer.get_next_token
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
                @lexer.revert
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                component1
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
              
         | 
| 115 | 
            +
              def factor
         | 
| 116 | 
            +
                factor1 = number
         | 
| 117 | 
            +
                
         | 
| 118 | 
            +
                multiplicative_operators = [Token::Multiply, Token::Divide]
         | 
| 119 | 
            +
                
         | 
| 120 | 
            +
                token = @lexer.get_next_token
         | 
| 121 | 
            +
                while multiplicative_operators.include?(token.kind)
         | 
| 122 | 
            +
                  factor2 = number
         | 
| 123 | 
            +
                  
         | 
| 124 | 
            +
                  if token.kind == Token::Multiply
         | 
| 125 | 
            +
                    factor1 *= factor2
         | 
| 126 | 
            +
                  else
         | 
| 127 | 
            +
                    factor1 /= factor2
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
                  
         | 
| 130 | 
            +
                  token = @lexer.get_next_token
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
                @lexer.revert
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                factor1
         | 
| 135 | 
            +
              end
         | 
| 136 | 
            +
                
         | 
| 137 | 
            +
              def number
         | 
| 138 | 
            +
                token = @lexer.get_next_token
         | 
| 139 | 
            +
                
         | 
| 140 | 
            +
                if token.kind == Token::LParen
         | 
| 141 | 
            +
                  value = expression
         | 
| 142 | 
            +
                  
         | 
| 143 | 
            +
                  expected_rparen = @lexer.get_next_token
         | 
| 144 | 
            +
                  raise 'Unbalanced parenthesis' unless expected_rparen.kind == Token::RParen
         | 
| 145 | 
            +
                elsif token.kind == Token::Number
         | 
| 146 | 
            +
                  value = token.value
         | 
| 147 | 
            +
                else
         | 
| 148 | 
            +
                  raise 'Not a number'
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
                
         | 
| 151 | 
            +
                value
         | 
| 152 | 
            +
              end
         | 
| 153 | 
            +
            end
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            end
         | 
    
        data/lib/wikicloth/parser.rb
    CHANGED
    
    | @@ -46,6 +46,12 @@ module WikiCloth | |
| 46 46 | 
             
            	end
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 |  | 
| 49 | 
            +
                  def template(&block)
         | 
| 50 | 
            +
                    self.send :define_method, 'template' do |template|
         | 
| 51 | 
            +
                      self.instance_exec(template,&block)
         | 
| 52 | 
            +
                    end
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 49 55 | 
             
                  def link_for_resource(&block)
         | 
| 50 56 | 
             
            	self.send :define_method, 'link_for_resource' do |prefix,resource,options|
         | 
| 51 57 | 
             
            	  options ||= []
         | 
| @@ -59,12 +65,6 @@ module WikiCloth | |
| 59 65 | 
             
                    end
         | 
| 60 66 | 
             
                  end
         | 
| 61 67 |  | 
| 62 | 
            -
                  def template(&block)
         | 
| 63 | 
            -
                    self.send :define_method, 'template' do |template|
         | 
| 64 | 
            -
                      self.instance_exec(template,&block)
         | 
| 65 | 
            -
                    end
         | 
| 66 | 
            -
                  end
         | 
| 67 | 
            -
             | 
| 68 68 | 
             
                  def link_for(&block)
         | 
| 69 69 | 
             
            	self.send :define_method, 'link_for' do |page,text|
         | 
| 70 70 | 
             
            	  self.instance_exec(page,text,&block)
         | 
| @@ -80,7 +80,7 @@ module WikiCloth | |
| 80 80 |  | 
| 81 81 | 
             
                # Replace a section, along with any sub-section in the document
         | 
| 82 82 | 
             
                def put_section(id,data)
         | 
| 83 | 
            -
                  data = @wikicloth.sections.first.wikitext({ :replace => { id => data } })
         | 
| 83 | 
            +
                  data = @wikicloth.sections.first.wikitext({ :replace => { id => data.last(1) == "\n" ? data : "#{data}\n" } })
         | 
| 84 84 | 
             
                  @wikicloth = WikiCloth.new(:data => data, :link_handler => self, :params => @params)
         | 
| 85 85 | 
             
                end
         | 
| 86 86 |  | 
    
        data/lib/wikicloth/section.rb
    CHANGED
    
    | @@ -20,6 +20,10 @@ module WikiCloth | |
| 20 20 | 
             
                  @auto_toc = val
         | 
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 | 
            +
                def template=(val)
         | 
| 24 | 
            +
                  @template = val
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 23 27 | 
             
                def title=(val)
         | 
| 24 28 | 
             
                  if val =~ /^([=]{1,6})\s*(.*?)\s*(\1)/
         | 
| 25 29 | 
             
                    @depth = $1.length
         | 
| @@ -71,7 +75,7 @@ module WikiCloth | |
| 71 75 | 
             
                      "\" title=\"Edit section: #{self.title}\">edit</a>]</span>") +
         | 
| 72 76 | 
             
                      " <span id=\"#{self.id}\" class=\"mw-headline\">#{self.title}</span></h#{self.depth}>"
         | 
| 73 77 | 
             
                  end
         | 
| 74 | 
            -
                  ret += self
         | 
| 78 | 
            +
                  ret += @template ? self.gsub(/\{\{\{\s*([A-Za-z0-9]+)\s*\}\}\}/,'\1') : self
         | 
| 75 79 | 
             
                  ret += "__TOC__" if @auto_toc
         | 
| 76 80 | 
             
                  ret += @children.collect { |c| c.render(options) } .join
         | 
| 77 81 | 
             
                  ret
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            module WikiCloth
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class WikiBuffer::Template < WikiBuffer
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize(data="",options={})
         | 
| 6 | 
            +
                super(data,options)
         | 
| 7 | 
            +
                @in_quotes = false
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def to_s
         | 
| 11 | 
            +
                "WICKED COOL"
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              protected
         | 
| 15 | 
            +
              def new_char()
         | 
| 16 | 
            +
                case
         | 
| 17 | 
            +
                # End of a template, variable, or function
         | 
| 18 | 
            +
                when current_char == '}' && previous_char == '}'
         | 
| 19 | 
            +
                  puts "TEMP: #{self.data} ----"
         | 
| 20 | 
            +
                  self.data = ""
         | 
| 21 | 
            +
                  return false
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                else
         | 
| 24 | 
            +
                  self.data += current_char
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                return true
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'expression_parser'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module WikiCloth
         | 
| 2 4 |  | 
| 3 5 | 
             
            class WikiBuffer::Var < WikiBuffer
         | 
| @@ -18,17 +20,83 @@ class WikiBuffer::Var < WikiBuffer | |
| 18 20 |  | 
| 19 21 | 
             
              def to_s
         | 
| 20 22 | 
             
                if self.is_function?
         | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
            #      ret += " [#{data}]"
         | 
| 25 | 
            -
                  ret = @options[:link_handler].function(function_name, params.collect { |p| p.strip })
         | 
| 23 | 
            +
                  ret = default_functions(function_name,params.collect { |p| p.strip })
         | 
| 24 | 
            +
                  ret ||= @options[:link_handler].function(function_name, params.collect { |p| p.strip })
         | 
| 25 | 
            +
                  ret.to_s
         | 
| 26 26 | 
             
                else
         | 
| 27 27 | 
             
                  ret = @options[:link_handler].include_resource("#{params[0]}".strip,params[1..-1])
         | 
| 28 | 
            +
                  # template params
         | 
| 29 | 
            +
                  ret = ret.to_s.gsub(/\{\{\{\s*([A-Za-z0-9]+)+(|\|+([^}]+))\s*\}\}\}/) { |match| get_param($1.strip,$3.to_s.strip) }
         | 
| 30 | 
            +
                  # put template at beginning of buffer
         | 
| 31 | 
            +
                  self.data = ret
         | 
| 32 | 
            +
                  ""
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def get_param(name,default=nil)
         | 
| 37 | 
            +
                ret = nil
         | 
| 38 | 
            +
                # numbered params
         | 
| 39 | 
            +
                if name =~ /^[0-9]+$/
         | 
| 40 | 
            +
                  ret = self.params[name.to_i].instance_of?(Hash) ? self.params[name.to_i][:value] : self.params[name.to_i]
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                # named params
         | 
| 43 | 
            +
                self.params.each do |param|
         | 
| 44 | 
            +
                  ret = param[:value] if param[:name] == name
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
                ret.nil? ? default : ret
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def default_functions(name,params)
         | 
| 50 | 
            +
                case name
         | 
| 51 | 
            +
                when "#if"
         | 
| 52 | 
            +
                  params.first.blank? ? params[2] : params[1]
         | 
| 53 | 
            +
                when "#switch"
         | 
| 54 | 
            +
                  params.length.times do |i|
         | 
| 55 | 
            +
                    temp = params[i].split("=")
         | 
| 56 | 
            +
                    return temp[1].strip if temp[0].strip == params[0] && i != 0
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                  return ""
         | 
| 59 | 
            +
                when "#expr"
         | 
| 60 | 
            +
                  begin
         | 
| 61 | 
            +
                    ExpressionParser::Parser.new.parse(params.first)
         | 
| 62 | 
            +
                  rescue RuntimeError
         | 
| 63 | 
            +
                    'Expression error: ' + $!
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                when "#ifeq"
         | 
| 66 | 
            +
                  if params[0] =~ /^[0-9A-Fa-f]+$/ && params[1] =~ /^[0-9A-Fa-f]+$/
         | 
| 67 | 
            +
                    params[0].to_i == params[1].to_i ? params[2] : params[3]
         | 
| 68 | 
            +
                  else
         | 
| 69 | 
            +
                    params[0] == params[1] ? params[2] : params[3]
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                when "#len"
         | 
| 72 | 
            +
                  params.first.length
         | 
| 73 | 
            +
                when "#sub"
         | 
| 74 | 
            +
                  params.first[params[1].to_i,params[2].to_i]
         | 
| 75 | 
            +
                when "#pad"
         | 
| 76 | 
            +
                  case params[3]
         | 
| 77 | 
            +
                  when "right"
         | 
| 78 | 
            +
                    params[0].ljust(params[1].to_i,params[2])
         | 
| 79 | 
            +
                  when "center"
         | 
| 80 | 
            +
                    params[0].center(params[1].to_i,params[2])
         | 
| 81 | 
            +
                  else
         | 
| 82 | 
            +
                    params[0].rjust(params[1].to_i,params[2])
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                when "#iferror"
         | 
| 85 | 
            +
                  params.first =~ /error/ ? params[1] : params[2]
         | 
| 86 | 
            +
                when "#capture"
         | 
| 87 | 
            +
                  @options[:params][params.first] = params[1]
         | 
| 88 | 
            +
                  ""
         | 
| 89 | 
            +
                when "lc"
         | 
| 90 | 
            +
                  params.first.downcase
         | 
| 91 | 
            +
                when "uc"
         | 
| 92 | 
            +
                  params.first.upcase
         | 
| 93 | 
            +
                when "ucfirst"
         | 
| 94 | 
            +
                  params.first.capitalize
         | 
| 95 | 
            +
                when "lcfirst"
         | 
| 96 | 
            +
                  params.first[0,1].downcase + params.first[1,-1]
         | 
| 97 | 
            +
                when "plural"
         | 
| 98 | 
            +
                  params.first.to_i > 1 ? params[1] : params[2]
         | 
| 28 99 | 
             
                end
         | 
| 29 | 
            -
            #    ret ||= "<!-- TEMPLATE[#{params[0]}] NOT FOUND -->"
         | 
| 30 | 
            -
                ret ||= ""
         | 
| 31 | 
            -
                ret
         | 
| 32 100 | 
             
              end
         | 
| 33 101 |  | 
| 34 102 | 
             
              def is_function?
         | 
| @@ -54,7 +122,7 @@ class WikiBuffer::Var < WikiBuffer | |
| 54 122 |  | 
| 55 123 | 
             
                # Dealing with variable names within functions
         | 
| 56 124 | 
             
                # and variables
         | 
| 57 | 
            -
                when current_char == '=' && @in_quotes == false
         | 
| 125 | 
            +
                when current_char == '=' && @in_quotes == false && !is_function?
         | 
| 58 126 | 
             
                  self.current_param = self.data
         | 
| 59 127 | 
             
                  self.data = ""
         | 
| 60 128 | 
             
                  self.name_current_param()
         | 
| @@ -18,10 +18,7 @@ class WikiLinkHandler | |
| 18 18 | 
             
              end
         | 
| 19 19 |  | 
| 20 20 | 
             
              def function(name, params)
         | 
| 21 | 
            -
                 | 
| 22 | 
            -
                when "#if"
         | 
| 23 | 
            -
                  params.first.blank? ? params[2] : params[1]
         | 
| 24 | 
            -
                end
         | 
| 21 | 
            +
                nil
         | 
| 25 22 | 
             
              end
         | 
| 26 23 |  | 
| 27 24 | 
             
              def toc_children(children)
         | 
| @@ -44,10 +41,6 @@ class WikiLinkHandler | |
| 44 41 | 
             
                "#{ret}</ul></td></tr></table>"
         | 
| 45 42 | 
             
              end
         | 
| 46 43 |  | 
| 47 | 
            -
              def template(template, args)
         | 
| 48 | 
            -
                nil
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
             | 
| 51 44 | 
             
              def external_links
         | 
| 52 45 | 
             
                @external_links ||= []
         | 
| 53 46 | 
             
              end
         | 
| @@ -94,7 +87,30 @@ class WikiLinkHandler | |
| 94 87 | 
             
              end
         | 
| 95 88 |  | 
| 96 89 | 
             
              def include_resource(resource, options=[])
         | 
| 97 | 
            -
                 | 
| 90 | 
            +
                if self.params.has_key?(resource)
         | 
| 91 | 
            +
                  self.params[resource]
         | 
| 92 | 
            +
                else
         | 
| 93 | 
            +
                  # FIXME: hack to keep template loops from raising havoc
         | 
| 94 | 
            +
                  @include_count ||= 0
         | 
| 95 | 
            +
                  @include_count += 1
         | 
| 96 | 
            +
                  raise "Page reached maximum number of includes [1000] (possible template loop?)" if @include_count > 100
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  ret = template(resource)
         | 
| 99 | 
            +
                  unless ret.nil?
         | 
| 100 | 
            +
                    @included_templates ||= {}
         | 
| 101 | 
            +
                    @included_templates[resource] ||= 0
         | 
| 102 | 
            +
                    @included_templates[resource] += 1
         | 
| 103 | 
            +
                  end
         | 
| 104 | 
            +
                  ret
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              def included_templates
         | 
| 109 | 
            +
                @included_templates ||= {}
         | 
| 110 | 
            +
              end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              def template(template)
         | 
| 113 | 
            +
                nil
         | 
| 98 114 | 
             
              end
         | 
| 99 115 |  | 
| 100 116 | 
             
              def link_for_resource(prefix, resource, options=[])
         | 
    
        data/lib/wikicloth.rb
    CHANGED
    
    | @@ -8,6 +8,8 @@ String.send(:include, ExtendedString) | |
| 8 8 |  | 
| 9 9 | 
             
            module WikiCloth
         | 
| 10 10 |  | 
| 11 | 
            +
              VERSION = "0.5.0"
         | 
| 12 | 
            +
             | 
| 11 13 | 
             
              class WikiCloth
         | 
| 12 14 |  | 
| 13 15 | 
             
                def initialize(opt={})
         | 
| @@ -19,6 +21,8 @@ module WikiCloth | |
| 19 21 | 
             
                  depth = 1
         | 
| 20 22 | 
             
                  count = 0
         | 
| 21 23 | 
             
                  root = [self.sections]
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  # parse wiki document into sections
         | 
| 22 26 | 
             
                  data.each_line do |line|
         | 
| 23 27 | 
             
                    if line =~ /^([=]{1,6})\s*(.*?)\s*(\1)/
         | 
| 24 28 | 
             
                      root << root.last[-1].children if $1.length > depth
         | 
| @@ -30,7 +34,15 @@ module WikiCloth | |
| 30 34 | 
             
                      root.last[-1] << line
         | 
| 31 35 | 
             
                    end
         | 
| 32 36 | 
             
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # if we find template variables assume document is
         | 
| 39 | 
            +
                  # a template
         | 
| 40 | 
            +
                  self.sections.first.template = true if data =~ /\{\{\{\s*([A-Za-z0-9]+)\s*\}\}\}/
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  # If there are more than four sections enable automatic
         | 
| 43 | 
            +
                  # table of contents
         | 
| 33 44 | 
             
                  self.sections.first.auto_toc = true unless count < 4 || data =~ /__(NO|)TOC__/
         | 
| 45 | 
            +
             | 
| 34 46 | 
             
                  self.params = p
         | 
| 35 47 | 
             
                end
         | 
| 36 48 |  | 
| @@ -40,11 +52,11 @@ module WikiCloth | |
| 40 52 |  | 
| 41 53 | 
             
                def render(opt={})
         | 
| 42 54 | 
             
                  noedit = false
         | 
| 55 | 
            +
                  self.params.merge!({ 'WIKI_VERSION' => ::WikiCloth::VERSION })
         | 
| 43 56 | 
             
                  self.options = { :output => :html, :link_handler => self.link_handler, :params => self.params, :sections => self.sections }.merge(opt)
         | 
| 44 57 | 
             
                  self.options[:link_handler].params = options[:params]
         | 
| 45 58 | 
             
                  data = self.sections.first.render(self.options)
         | 
| 46 59 | 
             
                  data.gsub!(/<!--(.|\s)*?-->/,"")
         | 
| 47 | 
            -
                  data.gsub!(/\{\{(.*?)(\|(.*?))?\}\}/){ |match| expand_templates($1,$3,["."]) }
         | 
| 48 60 | 
             
                  buffer = WikiBuffer.new("",options)
         | 
| 49 61 | 
             
                  data.each_char { |c| buffer.add_char(c) }
         | 
| 50 62 | 
             
                  buffer.to_s
         | 
| @@ -63,24 +75,6 @@ module WikiCloth | |
| 63 75 | 
             
                end
         | 
| 64 76 |  | 
| 65 77 | 
             
                protected
         | 
| 66 | 
            -
                def expand_templates(template, args, stack)
         | 
| 67 | 
            -
                  template.strip!
         | 
| 68 | 
            -
                  article = link_handler.template(template, args)
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                  if article.nil?
         | 
| 71 | 
            -
                    data = "{{#{template}}}"
         | 
| 72 | 
            -
                  else
         | 
| 73 | 
            -
                    unless stack.include?(template)
         | 
| 74 | 
            -
                      data = article
         | 
| 75 | 
            -
                    else
         | 
| 76 | 
            -
                      data = "WARNING: TEMPLATE LOOP"
         | 
| 77 | 
            -
                    end
         | 
| 78 | 
            -
                    data = data.gsub(/\{\{(.*?)(?:\|(.*?))?\}\}?/){ |match| expand_templates($1, $2, stack + [template])}
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  data
         | 
| 82 | 
            -
                end
         | 
| 83 | 
            -
             | 
| 84 78 | 
             
                def sections=(val)
         | 
| 85 79 | 
             
                  @sections = val
         | 
| 86 80 | 
             
                end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: wikicloth
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 11
         | 
| 5 5 | 
             
              prerelease: false
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 0
         | 
| 8 | 
            -
              -  | 
| 8 | 
            +
              - 5
         | 
| 9 9 | 
             
              - 0
         | 
| 10 | 
            -
              version: 0. | 
| 10 | 
            +
              version: 0.5.0
         | 
| 11 11 | 
             
            platform: ruby
         | 
| 12 12 | 
             
            authors: 
         | 
| 13 13 | 
             
            - David Ricciardi
         | 
| @@ -15,7 +15,7 @@ autorequire: | |
| 15 15 | 
             
            bindir: bin
         | 
| 16 16 | 
             
            cert_chain: []
         | 
| 17 17 |  | 
| 18 | 
            -
            date: 2010-09- | 
| 18 | 
            +
            date: 2010-09-20 00:00:00 +00:00
         | 
| 19 19 | 
             
            default_executable: 
         | 
| 20 20 | 
             
            dependencies: 
         | 
| 21 21 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -32,6 +32,20 @@ dependencies: | |
| 32 32 | 
             
                    version: "0"
         | 
| 33 33 | 
             
              type: :runtime
         | 
| 34 34 | 
             
              version_requirements: *id001
         | 
| 35 | 
            +
            - !ruby/object:Gem::Dependency 
         | 
| 36 | 
            +
              name: expression_parser
         | 
| 37 | 
            +
              prerelease: false
         | 
| 38 | 
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         | 
| 39 | 
            +
                none: false
         | 
| 40 | 
            +
                requirements: 
         | 
| 41 | 
            +
                - - ">="
         | 
| 42 | 
            +
                  - !ruby/object:Gem::Version 
         | 
| 43 | 
            +
                    hash: 3
         | 
| 44 | 
            +
                    segments: 
         | 
| 45 | 
            +
                    - 0
         | 
| 46 | 
            +
                    version: "0"
         | 
| 47 | 
            +
              type: :runtime
         | 
| 48 | 
            +
              version_requirements: *id002
         | 
| 35 49 | 
             
            description: mediawiki parser
         | 
| 36 50 | 
             
            email: nricciar@gmail.com
         | 
| 37 51 | 
             
            executables: []
         | 
| @@ -43,10 +57,13 @@ extra_rdoc_files: | |
| 43 57 | 
             
            - MIT-LICENSE
         | 
| 44 58 | 
             
            files: 
         | 
| 45 59 | 
             
            - lib/wikicloth.rb
         | 
| 60 | 
            +
            - lib/wikicloth/calc.citrus
         | 
| 61 | 
            +
            - lib/wikicloth/math.rb
         | 
| 46 62 | 
             
            - lib/wikicloth/core_ext.rb
         | 
| 47 63 | 
             
            - lib/wikicloth/wiki_buffer/html_element.rb
         | 
| 48 64 | 
             
            - lib/wikicloth/wiki_buffer/var.rb
         | 
| 49 65 | 
             
            - lib/wikicloth/wiki_buffer/table.rb
         | 
| 66 | 
            +
            - lib/wikicloth/wiki_buffer/template.rb
         | 
| 50 67 | 
             
            - lib/wikicloth/wiki_buffer/link.rb
         | 
| 51 68 | 
             
            - lib/wikicloth/parser.rb
         | 
| 52 69 | 
             
            - lib/wikicloth/section.rb
         |