diff vendor/gems/coderay-0.9.7/lib/coderay/scanners/html.rb @ 210:0579821a129a

Update to Redmine trunk rev 4802
author Chris Cannam
date Tue, 08 Feb 2011 13:51:46 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/gems/coderay-0.9.7/lib/coderay/scanners/html.rb	Tue Feb 08 13:51:46 2011 +0000
@@ -0,0 +1,182 @@
+module CodeRay
+module Scanners
+
+  # HTML Scanner
+  class HTML < Scanner
+
+    include Streamable
+    register_for :html
+    
+    KINDS_NOT_LOC = [
+      :comment, :doctype, :preprocessor,
+      :tag, :attribute_name, :operator,
+      :attribute_value, :delimiter, :content,
+      :plain, :entity, :error
+    ]
+
+    ATTR_NAME = /[\w.:-]+/
+    ATTR_VALUE_UNQUOTED = ATTR_NAME
+    TAG_END = /\/?>/
+    HEX = /[0-9a-fA-F]/
+    ENTITY = /
+      &
+      (?:
+        \w+
+      |
+        \#
+        (?:
+          \d+
+        |
+          x#{HEX}+
+        )
+      )
+      ;
+    /ox
+
+    PLAIN_STRING_CONTENT = {
+      "'" => /[^&'>\n]+/,
+      '"' => /[^&">\n]+/,
+    }
+
+    def reset
+      super
+      @state = :initial
+    end
+
+  private
+    def setup
+      @state = :initial
+      @plain_string_content = nil
+    end
+
+    def scan_tokens tokens, options
+
+      state = @state
+      plain_string_content = @plain_string_content
+
+      until eos?
+
+        kind = nil
+        match = nil
+
+        if scan(/\s+/m)
+          kind = :space
+
+        else
+
+          case state
+
+          when :initial
+            if scan(/<!--.*?-->/m)
+              kind = :comment
+            elsif scan(/<!DOCTYPE.*?>/m)
+              kind = :doctype
+            elsif scan(/<\?xml.*?\?>/m)
+              kind = :preprocessor
+            elsif scan(/<\?.*?\?>|<%.*?%>/m)
+              kind = :comment
+            elsif scan(/<\/[-\w.:]*>/m)
+              kind = :tag
+            elsif match = scan(/<[-\w.:]+>?/m)
+              kind = :tag
+              state = :attribute unless match[-1] == ?>
+            elsif scan(/[^<>&]+/)
+              kind = :plain
+            elsif scan(/#{ENTITY}/ox)
+              kind = :entity
+            elsif scan(/[<>&]/)
+              kind = :error
+            else
+              raise_inspect '[BUG] else-case reached with state %p' % [state], tokens
+            end
+
+          when :attribute
+            if scan(/#{TAG_END}/o)
+              kind = :tag
+              state = :initial
+            elsif scan(/#{ATTR_NAME}/o)
+              kind = :attribute_name
+              state = :attribute_equal
+            else
+              kind = :error
+              getch
+            end
+
+          when :attribute_equal
+            if scan(/=/)
+              kind = :operator
+              state = :attribute_value
+            elsif scan(/#{ATTR_NAME}/o)
+              kind = :attribute_name
+            elsif scan(/#{TAG_END}/o)
+              kind = :tag
+              state = :initial
+            elsif scan(/./)
+              kind = :error
+              state = :attribute
+            end
+
+          when :attribute_value
+            if scan(/#{ATTR_VALUE_UNQUOTED}/o)
+              kind = :attribute_value
+              state = :attribute
+            elsif match = scan(/["']/)
+              tokens << [:open, :string]
+              state = :attribute_value_string
+              plain_string_content = PLAIN_STRING_CONTENT[match]
+              kind = :delimiter
+            elsif scan(/#{TAG_END}/o)
+              kind = :tag
+              state = :initial
+            else
+              kind = :error
+              getch
+            end
+
+          when :attribute_value_string
+            if scan(plain_string_content)
+              kind = :content
+            elsif scan(/['"]/)
+              tokens << [matched, :delimiter]
+              tokens << [:close, :string]
+              state = :attribute
+              next
+            elsif scan(/#{ENTITY}/ox)
+              kind = :entity
+            elsif scan(/&/)
+              kind = :content
+            elsif scan(/[\n>]/)
+              tokens << [:close, :string]
+              kind = :error
+              state = :initial
+            end
+
+          else
+            raise_inspect 'Unknown state: %p' % [state], tokens
+
+          end
+
+        end
+
+        match ||= matched
+        if $CODERAY_DEBUG and not kind
+          raise_inspect 'Error token %p in line %d' %
+            [[match, kind], line], tokens, state
+        end
+        raise_inspect 'Empty token', tokens unless match
+
+        tokens << [match, kind]
+      end
+
+      if options[:keep_state]
+        @state = state
+        @plain_string_content = plain_string_content
+      end
+
+      tokens
+    end
+
+  end
+
+end
+end