Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify JSX and TSX lexers #1492

Merged
merged 9 commits into from May 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
106 changes: 47 additions & 59 deletions lib/rouge/lexers/jsx.rb
Expand Up @@ -6,97 +6,85 @@ module Lexers

class JSX < Javascript
title 'JSX'
desc 'React JSX (https://facebook.github.io/react/)'
desc 'An XML-like syntax extension to JavaScript (facebook.github.io/jsx/)'
tag 'jsx'
aliases 'jsx', 'react'
filenames '*.jsx'

mimetypes 'text/x-jsx', 'application/x-jsx'

id = Javascript.id_regex
start { @html = HTML.new(options); push :expr_start }

def start_embed!
@embed ||= JSX.new(options)
@embed.reset!
@embed.push(:expr_start)
push :jsx_embed_root
end

def tag_token(name)
name[0] =~ /\p{Lower}/ ? Name::Tag : Name::Class
prepend :expr_start do
mixin :tag
end

start { @html = HTML.new(options) }

state :jsx_tags do
rule %r/</, Punctuation, :jsx_element
state :tag do
rule %r/</ do
token Punctuation
push :tag_opening
push :element
push :element_name
end
end

state :jsx_internal do
rule %r(</) do
state :tag_opening do
rule %r/<\// do
token Punctuation
goto :jsx_end_tag
goto :element
push :element_name
end

mixin :tag
rule %r/{/ do
token Str::Interpol
start_embed!
push :interpol
push :expr_start
end

rule %r/[^<>{]+/ do
rule %r/[^<{]+/ do
delegate @html
end

mixin :jsx_tags
end

prepend :expr_start do
mixin :jsx_tags
end

state :jsx_tag do
state :element do
mixin :comments_and_whitespace
rule %r/#{id}/ do |m|
token tag_token(m[0])
rule %r/\/>/ do
token Punctuation
pop! 2
end

rule %r/[.]/, Punctuation
end

state :jsx_end_tag do
mixin :jsx_tag
rule %r/>/, Punctuation, :pop!
end

state :jsx_element do
rule %r/#{id}=/, Name::Attribute, :jsx_attribute
mixin :jsx_tag
rule %r/>/ do token Punctuation; goto :jsx_internal end
rule %r(/>), Punctuation, :pop!
end

state :jsx_attribute do
rule %r/"(\\[\\"]|[^"])*"/, Str::Double, :pop!
rule %r/'(\\[\\']|[^'])*'/, Str::Single, :pop!
rule %r/{/ do
token Str::Interpol
pop!
start_embed!
push :interpol
push :expr_start
end
rule %r/\w+/, Name::Attribute
rule %r/=/, Punctuation
rule %r/(["']).*?(\1)/, Str
end

state :jsx_embed_root do
rule %r/[.][.][.]/, Punctuation
state :element_name do
rule %r/[A-Z]\w*/, Name::Class
rule %r/\w+/, Name::Tag
rule %r/\./, Punctuation
rule(//) { pop! }
end

state :interpol do
rule %r/}/, Str::Interpol, :pop!
mixin :jsx_embed
rule %r/{/ do
token Punctuation
push :interpol_inner
push :statement
end
mixin :root
end

state :jsx_embed do
rule %r/{/ do delegate @embed; push :jsx_embed end
rule %r/}/ do delegate @embed; pop! end
rule %r/[^{}]+/ do
delegate @embed
state :interpol_inner do
rule %r/}/ do
token Punctuation
goto :statement
end
mixin :root
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/rouge/lexers/tsx.rb
Expand Up @@ -9,8 +9,8 @@ module Lexers
class TSX < JSX
extend TypescriptCommon

title 'TypeScript'
desc 'tsx'
title 'TSX'
desc 'TypeScript-compatible JSX (www.typescriptlang.org/docs/handbook/jsx.html)'

tag 'tsx'
filenames '*.tsx'
Expand Down
15 changes: 4 additions & 11 deletions spec/visual/samples/jsx
@@ -1,8 +1,10 @@
<header className="App-header">
Hello React!
</header>

var myDivElement = <div className="foo" />;
ReactDOM.render(myDivElement, document.getElementById('example'));



var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
ReactDOM.render(myElement, document.getElementById('example'));
Expand Down Expand Up @@ -50,15 +52,6 @@ var content = (
</Nav>
);

var App = (
<Form>
<FormRow>
<FormLabel />
<FormInput />
</FormRow>
</Form>
);

var thing = <A b={function() { var c = <D e={true}>&quot;</D>; }()}/>

class LikeButton extends React.Component {
Expand Down