diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/coderay/encoders/html/css.rb | 21 | ||||
-rw-r--r-- | lib/coderay/helpers/file_type.rb | 1 | ||||
-rw-r--r-- | lib/coderay/scanner.rb | 2 | ||||
-rw-r--r-- | lib/coderay/scanners/java_script.rb | 191 | ||||
-rw-r--r-- | lib/coderay/styles/cycnus.rb | 4 | ||||
-rw-r--r-- | lib/coderay/styles/murphy.rb | 3 | ||||
-rwxr-xr-x | lib/coderay/token_classes.rb | 2 |
7 files changed, 214 insertions, 10 deletions
diff --git a/lib/coderay/encoders/html/css.rb b/lib/coderay/encoders/html/css.rb index d577602..90d8cb1 100644 --- a/lib/coderay/encoders/html/css.rb +++ b/lib/coderay/encoders/html/css.rb @@ -34,9 +34,12 @@ module Encoders private CSS_CLASS_PATTERN = / - ( (?: # $1 = classes - \s* \. [-\w]+ - )+ ) + ( # $1 = selectors + (?: + (?: \s* \. [-\w]+ )+ + \s* ,? + )+ + ) \s* \{ \s* ( [^\}]+ )? # $2 = style \s* \} \s* @@ -44,12 +47,14 @@ module Encoders ( . ) # $3 = error /mx def parse stylesheet - stylesheet.scan CSS_CLASS_PATTERN do |classes, style, error| + stylesheet.scan CSS_CLASS_PATTERN do |selectors, style, error| raise "CSS parse error: '#{error.inspect}' not recognized" if error - styles = classes.scan(/[-\w]+/) - cl = styles.pop - @classes[cl] ||= Hash.new - @classes[cl][styles] = style.to_s.strip + for selector in selectors.split(',') + classes = selector.scan(/[-\w]+/) + cl = classes.pop + @classes[cl] ||= Hash.new + @classes[cl][classes] = style.to_s.strip + end end end diff --git a/lib/coderay/helpers/file_type.rb b/lib/coderay/helpers/file_type.rb index 75c691f..f7c5f7d 100644 --- a/lib/coderay/helpers/file_type.rb +++ b/lib/coderay/helpers/file_type.rb @@ -88,6 +88,7 @@ module FileType 'cpp' => :c, 'c' => :c, 'h' => :c, + 'js' => :java_script, 'xml' => :xml, 'htm' => :html, 'html' => :html, diff --git a/lib/coderay/scanner.rb b/lib/coderay/scanner.rb index d33e2f2..a28f70f 100644 --- a/lib/coderay/scanner.rb +++ b/lib/coderay/scanner.rb @@ -77,7 +77,7 @@ module CodeRay else @file_extension ||= plugin_id.to_s end - end + end end diff --git a/lib/coderay/scanners/java_script.rb b/lib/coderay/scanners/java_script.rb new file mode 100644 index 0000000..f13c5d3 --- /dev/null +++ b/lib/coderay/scanners/java_script.rb @@ -0,0 +1,191 @@ +module CodeRay +module Scanners + + class JavaScript < Scanner + + include Streamable + + register_for :java_script + file_extension 'js' + + # The actual JavaScript keywords. + KEYWORDS = %w[ + break case catch continue default delete do else + false finally for function if in instanceof new null + return switch throw true try typeof var void while with + ] + + MAGIC_VARIABLES = %w[ this arguments ] # arguments was introduced in JavaScript 1.4 + + KEYWORDS_EXPECTING_VALUE = WordList.new.add %w[ + case delete in instanceof new return throw typeof while with + ] + + # Reserved for future use. + RESERVED_WORDS = %w[ + abstract boolean byte char class debugger double enum export extends + final float goto implements import int interface long native package + private protected public short static super synchronized throws transient + volatile + ] + + IDENT_KIND = WordList.new(:ident). + add(RESERVED_WORDS, :reserved). + add(MAGIC_VARIABLES, :local_variable). + add(KEYWORDS, :keyword) + + ESCAPE = / [bfnrtv\n\\'"] | x[a-fA-F0-9]{1,2} | [0-7]{1,3} /x + UNICODE_ESCAPE = / u[a-fA-F0-9]{4} | U[a-fA-F0-9]{8} /x + REGEXP_ESCAPE = / [bBdDsSwW] /x + STRING_CONTENT_PATTERN = { + "'" => /[^\\']+/, + '"' => /[^\\"]+/, + '/' => /[^\\\/]+/, + } + + def scan_tokens tokens, options + + state = :initial + string_delimiter = nil + value_expected = true + key_expected = false + + until eos? + + kind = nil + match = nil + + case state + + when :initial + + if match = scan(/ \s+ | \\\n /x) + value_expected = true if !value_expected && match.index(?\n) + tokens << [match, :space] + next + + elsif scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx) + value_expected = true + kind = :comment + + elsif scan(/[+-]?(?:\d+)(?![.eEfF])/) + value_expected = false + kind = :integer + + elsif match = scan(/ [-+*=<>?:;,!&^|(\[{~%]+ | \.(?!\d) /x) + value_expected = true + last_operator = match[-1] + key_expected = (last_operator == ?{) || (last_operator == ?,) + kind = :operator + + elsif scan(/ [)\]}]+ /x) + key_expected = value_expected = false + kind = :operator + + elsif match = scan(/ [$a-zA-Z_][A-Za-z_0-9$]* /x) + kind = IDENT_KIND[match] + value_expected = (kind == :keyword) && KEYWORDS_EXPECTING_VALUE[match] + if kind == :ident + if match.index(?$) + kind = :predefined + elsif key_expected && check(/\s*:/) + kind = :key + end + end + key_expected = false + + elsif match = scan(/["']/) + tokens << [:open, :string] + state = :string + string_delimiter = match + kind = :delimiter + + elsif value_expected && (match = scan(/\/(?=\S)/)) + tokens << [:open, :regexp] + state = :regexp + string_delimiter = '/' + kind = :delimiter + + elsif scan(/ \/ /x) + value_expected = true + key_expected = false + kind = :operator + + elsif scan(/0[xX][0-9A-Fa-f]+/) + key_expected = value_expected = false + kind = :hex + + elsif scan(/(?:0[0-7]+)(?![89.eEfF])/) + key_expected = value_expected = false + kind = :oct + + elsif scan(/\d[fF]?|\d*\.\d+(?:[eE][+-]?\d+)?[fF]?|\d+[eE][+-]?\d+[fF]?/) + key_expected = value_expected = false + kind = :float + + else + getch + kind = :error + + end + + when :string, :regexp + if scan(STRING_CONTENT_PATTERN[string_delimiter]) + kind = :content + elsif match = scan(/["'\/]/) + tokens << [match, :delimiter] + if state == :regexp + modifiers = scan(/[gim]+/) + tokens << [modifiers, :modifier] if modifiers && !modifiers.empty? + end + tokens << [:close, state] + string_delimiter = nil + key_expected = value_expected = false + state = :initial + next + elsif state == :string && (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) + if string_delimiter == "'" && !(match == "\\\\" || match == "\\'") + kind = :content + else + kind = :char + end + elsif state == :regexp && scan(/ \\ (?: #{ESCAPE} | #{REGEXP_ESCAPE} | #{UNICODE_ESCAPE} ) /mox) + kind = :char + elsif scan(/\\./m) + kind = :content + elsif scan(/ \\ | $ /x) + tokens << [:close, :delimiter] + kind = :error + key_expected = value_expected = false + state = :initial + else + raise_inspect "else case \" reached; %p not handled." % peek(1), tokens + end + + else + raise_inspect 'Unknown state', tokens + + end + + match ||= matched + if $DEBUG and not kind + raise_inspect 'Error token %p in line %d' % + [[match, kind], line], tokens + end + raise_inspect 'Empty token', tokens unless match + + tokens << [match, kind] + + end + + if [:string, :regexp].include? state + tokens << [:close, state] + end + + tokens + end + + end + +end +end diff --git a/lib/coderay/styles/cycnus.rb b/lib/coderay/styles/cycnus.rb index 7747c75..7b68a66 100644 --- a/lib/coderay/styles/cycnus.rb +++ b/lib/coderay/styles/cycnus.rb @@ -91,7 +91,9 @@ ol.CodeRay li { white-space: pre } .pd { color:#369; font-weight:bold } .pp { color:#579 } .pt { color:#339; font-weight:bold } -.r { color:#080; font-weight:bold } +.r, .kw { color:#080; font-weight:bold } + +.ke { color: #808; } .rx { background-color:#fff0ff } .rx .k { color:#808 } diff --git a/lib/coderay/styles/murphy.rb b/lib/coderay/styles/murphy.rb index b42f0e0..15faadb 100644 --- a/lib/coderay/styles/murphy.rb +++ b/lib/coderay/styles/murphy.rb @@ -84,6 +84,9 @@ ol.CodeRay li { white-space: pre; } .pp { color:#579; } .pt { color:#66f; font-weight:bold; } .r { color:#5de; font-weight:bold; } +.r, .kw { color:#5de; font-weight:bold } + +.ke { color: #808; } .rx { background-color:#221133; } .rx .k { color:#f8f; } diff --git a/lib/coderay/token_classes.rb b/lib/coderay/token_classes.rb index d0de855..c352e48 100755 --- a/lib/coderay/token_classes.rb +++ b/lib/coderay/token_classes.rb @@ -35,6 +35,8 @@ module CodeRay :instance_variable => 'iv', :integer => 'i', :interpreted => 'in', + :keyword => 'kw', + :key => 'ke', :label => 'la', :local_variable => 'lv', :modifier => 'mod', |