Created
September 7, 2015 04:06
-
-
Save pragdave/fc56273a8f6cd772caac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- # | |
module Rouge | |
module Lexers | |
class EmbeddedJSX < RegexLexer | |
tag :xml_inside_jsx | |
def self.analyze_text(text) | |
0 | |
end | |
def jsx | |
@jsx ||= JSX.new | |
end | |
state :assignment_expression do # actually a JS expr in {...} | |
rule /{(.*?)}/m do |match| | |
inside = match.matched[1...-1] | |
delegate jsx, inside | |
end | |
end | |
state :root do | |
mixin :assignment_expression | |
rule /[^<&]+/, Text | |
rule /&\S*?;/, Name::Entity | |
rule /<!\[CDATA\[.*?\]\]\>/, Comment::Preproc | |
rule /<!--/, Comment, :comment | |
rule /<\?.*?\?>/, Comment::Preproc | |
rule /<![^>]*>/, Comment::Preproc | |
rule %r(<\s*[\w:.-]+)m, Name::Tag, :tag | |
# self-closing tags | |
rule %r(<\s*/\s*[\w:.-]+\s*>)m, Name::Tag | |
end | |
state :comment do | |
rule /[^-]+/m, Comment | |
rule /-->/, Comment, :pop! | |
rule /-/, Comment | |
end | |
state :tag do | |
rule /\s+/m, Text | |
rule /[\w.:-]+\s*=/m, Name::Attribute, :attr | |
mixin :assignment_expression | |
rule %r(/?\s*>), Name::Tag, :pop! | |
end | |
state :attr do | |
rule /\s+/m, Text | |
rule /{.*?}/m, Comment, :pop! | |
rule /\".*?\"|\'.*?'|[^\s>]+/, Str, :pop! | |
end | |
end | |
class JSX < RegexLexer | |
title "JavaScript (JSX)" | |
desc "JSX variant of JavaScript" | |
tag 'jsx' | |
filenames '*.jsx' | |
mimetypes 'text/jsx' | |
def self.analyze_text(text) | |
case text | |
when %r{</\w} | |
0.3 | |
else | |
0 | |
end | |
end | |
def initialize(opts={}) | |
@xml_lexer = EmbeddedJSX.new(opts) | |
super(opts) | |
end | |
state :comments_and_whitespace do | |
rule /\s+/, Text | |
rule /<!--/, Comment # really...? | |
rule %r(//.*?$), Comment::Single | |
rule %r(/\*.*?\*/)m, Comment::Multiline | |
end | |
state :embedded_xml do | |
# open tags | |
rule %r{<\s*([\w:.-]+).*?<\s*/\1\s*>}m do | |
delegate @xml_lexer | |
end | |
# self-closing tags | |
rule %r(<\s*/\s*[\w:.-]+\s*>)m do | |
delegate @xml_lexer | |
end | |
end | |
state :expr_start do | |
mixin :comments_and_whitespace | |
mixin :embedded_xml | |
rule %r(/) do | |
token Str::Regex | |
goto :regex | |
end | |
rule /[{]/, Punctuation, :object | |
rule //, Text, :pop! | |
end | |
state :comment do | |
rule /[^-]+/m, Comment | |
rule /-->/, Comment, :pop! | |
rule /-/, Comment | |
end | |
state :tag do | |
rule /\s+/m, Text | |
rule /[\w.:-]+\s*=/m, Name::Attribute, :attr | |
rule %r(/?\s*>), Name::Tag, :pop! | |
end | |
state :attr do | |
rule /\s+/m, Text | |
rule /\".*?\"|\'.*?'|[^\s>]+/, Str, :pop! | |
end | |
state :regex do | |
rule %r(/) do | |
token Str::Regex | |
goto :regex_end | |
end | |
rule %r([^/]\n), Error, :pop! | |
rule /\n/, Error, :pop! | |
rule /\[\^/, Str::Escape, :regex_group | |
rule /\[/, Str::Escape, :regex_group | |
rule /\\./, Str::Escape | |
rule %r{[(][?][:=<!]}, Str::Escape | |
rule /[{][\d,]+[}]/, Str::Escape | |
rule /[()?]/, Str::Escape | |
rule /./, Str::Regex | |
end | |
state :regex_end do | |
rule /[gim]+/, Str::Regex, :pop! | |
rule(//) { pop! } | |
end | |
state :regex_group do | |
# specially highlight / in a group to indicate that it doesn't | |
# close the regex | |
rule /\//, Str::Escape | |
rule %r([^/]\n) do | |
token Error | |
pop! 2 | |
end | |
rule /\]/, Str::Escape, :pop! | |
rule /\\./, Str::Escape | |
rule /./, Str::Regex | |
end | |
state :bad_regex do | |
rule /[^\n]+/, Error, :pop! | |
end | |
def self.keywords | |
@keywords ||= Set.new %w( | |
for in while do break return continue switch case default | |
if else throw try catch finally new delete typeof instanceof | |
void this yield | |
) | |
end | |
def self.declarations | |
@declarations ||= Set.new %w(var let with function) | |
end | |
def self.reserved | |
@reserved ||= Set.new %w( | |
abstract boolean byte char class const 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 | |
) | |
end | |
def self.constants | |
@constants ||= Set.new %w(true false null NaN Infinity undefined) | |
end | |
def self.builtins | |
@builtins ||= %w( | |
Array Boolean Date Error Function Math netscape | |
Number Object Packages RegExp String sun decodeURI | |
decodeURIComponent encodeURI encodeURIComponent | |
Error eval isFinite isNaN parseFloat parseInt document this | |
window | |
) | |
end | |
id = /[$a-zA-Z_][a-zA-Z0-9_]*/ | |
state :root do | |
rule /\A\s*#!.*?\n/m, Comment::Preproc, :statement | |
rule /\n/, Text, :statement | |
rule %r((?<=\n)(?=\s|/|<!--)), Text, :expr_start | |
mixin :embedded_xml | |
mixin :comments_and_whitespace | |
rule %r(\+\+ | -- | ~ | && | \|\| | \\(?=\n) | << | >>>? | === | |
| !== )x, | |
Operator, :expr_start | |
rule %r([-<>+*%&|\^/!=]=?), Operator, :expr_start | |
rule /[(\[,]/, Punctuation, :expr_start | |
rule /;/, Punctuation, :statement | |
rule /[)\].]/, Punctuation | |
rule /[?]/ do | |
token Punctuation | |
push :ternary | |
push :expr_start | |
end | |
rule /[{}]/, Punctuation, :statement | |
rule id do |m| | |
if self.class.keywords.include? m[0] | |
token Keyword | |
push :expr_start | |
elsif self.class.declarations.include? m[0] | |
token Keyword::Declaration | |
push :expr_start | |
elsif self.class.reserved.include? m[0] | |
token Keyword::Reserved | |
elsif self.class.constants.include? m[0] | |
token Keyword::Constant | |
elsif self.class.builtins.include? m[0] | |
token Name::Builtin | |
else | |
token Name::Other | |
end | |
end | |
rule /[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?/, Num::Float | |
rule /0x[0-9a-fA-F]+/, Num::Hex | |
rule /[0-9]+/, Num::Integer | |
rule /"(\\\\|\\"|[^"])*"/, Str::Double | |
rule /'(\\\\|\\'|[^'])*'/, Str::Single | |
end | |
# braced parts that aren't object literals | |
state :statement do | |
rule /(#{id})(\s*)(:)/ do | |
groups Name::Label, Text, Punctuation | |
end | |
rule /[{}]/, Punctuation | |
mixin :expr_start | |
end | |
# object literals | |
state :object do | |
mixin :comments_and_whitespace | |
rule /[}]/ do | |
token Punctuation | |
goto :statement | |
end | |
rule /(#{id})(\s*)(:)/ do | |
groups Name::Attribute, Text, Punctuation | |
push :expr_start | |
end | |
rule /:/, Punctuation | |
mixin :root | |
end | |
# ternary expressions, where <id>: is not a label! | |
state :ternary do | |
rule /:/ do | |
token Punctuation | |
goto :expr_start | |
end | |
mixin :root | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment