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

Add Velocity template support. #352

Closed
wants to merge 2 commits into from
Closed
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
28 changes: 28 additions & 0 deletions lib/rouge/demos/velocity
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

#*
There is multi-line comment.
see this text because the Velocity Templating Engine will ignore it.
*#
<h3>List</h3>
## This is a single line comment.
#if( $allProducts )
<p>not found.</p>
#else

<table>
<tbody>
#foreach( $product in $allProducts )
<tr id="product-$product.Id" data-url="#SURL("$!product.Slug")">
<td>$product.Title</td>
</tr>
#end
</tbody>
</table>
#end
#set( $monkey.Say = ["Not", $my, "fault", 10, false, null] ) ## ArrayList
${mudSlinger}
${customer.Address}
${purchase.getTotal(true)}
$title.set( "Homage to Catalonia" )


102 changes: 102 additions & 0 deletions lib/rouge/lexers/velocity.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*- #

module Rouge
module Lexers
class Velocity < TemplateLexer
title 'Velocity'
desc 'Generic `Velocity <http://velocity.apache.org/>`_ template lexer.'
tag 'velocity'
filenames '*.vm', '*.velocity', '*.fhtml'
mimetypes 'text/html+velocity'

IDENTIFIER = IDENTIFIER = /[a-zA-Z_]\w*/

def self.analyze_text(text)
rv = 0.0
if text =~ /#\{?macro\}?\(.*?\).*?#\{?end\}?/
rv += 0.25
end

if text =~ /#\{?if\}?\(.+?\).*?#\{?end\}?/
rv += 0.15
end

if text =~ /#\{?foreach\}?\(.+?\).*?#\{?end\}?/
rv += 0.15
end

if text =~ /\$\{?[a-zA-Z_]\w*(\([^)]*\))?(\.\w+(\([^)]*\))?)*\}?/
rv += 0.01
end

rv
end

state :root do
rule /[^{#$]+/, Other
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of highlighting this as Other, I'd recommend delegating it to parent, a lexer provided by the TemplateLexer class that by default is HTML. So:

rule /.../ do
  delegate parent
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then after doing that, I suggest you look into the errors in the sample. Run bundle exec rackup and view localhost:9292/velocity.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(to see in detail how it's being lexed, add ?debug=1)


rule /(#)(\*.*?\*)(#)/m do
groups Comment::Preproc, Comment, Comment::Preproc
end

rule /(##)(.*?$)/ do
groups Comment::Preproc, Comment
end

rule /(#\{?)(#{IDENTIFIER})(\}?)(\s?\()/m do
groups Punctuation, Name::Function, Punctuation, Punctuation do
goto :directiveparams
end
end

rule /(#\{?)(#{IDENTIFIER})(\}|\b)/m do
groups Punctuation, Name::Function, Punctuation
end

rule /\$\{?/, Punctuation, :variable
end

state :variable do
rule /#{IDENTIFIER}/, Name::Variable
rule /\(/, Punctuation, :funcparams
rule /(\.)(#{IDENTIFIER})/ do
groups Punctuation, Name::Variable do
goto :push
end
end
rule /\}/, Punctuation, :pop!
rule /./, Str::Char, :pop!
end

state :directiveparams do
rule /(&&|\|\||==?|!=?|[-<>+*%&|^\/])|\b(eq|ne|gt|lt|ge|le|not|in)\b/, Operator
rule /\[/, Operator, :rangeoperator
rule /\b#{IDENTIFIER}\b/, Name::Function
mixin :funcparams
end

state :rangeoperator do
rule /\.\./, Operator
mixin :funcparams
rule /\]/, Operator, :pop!
end

state :funcparams do
rule /\$\{?/, Punctuation, :variable
rule /\s+/, Text
rule /,/, Punctuation
rule /"(\\\\|\\"|[^"])*"/, Str::Double
rule /'(\\\\|\\'|[^'])*'/, Str::Single
rule /0[xX][0-9a-fA-F]+[Ll]?/, Literal::Number
rule /\b[0-9]+\b/, Literal::Number
rule /(true|false|null)\b/, Keyword::Constant
rule /\(/, Punctuation, :push
rule /\)/, Punctuation, :push
rule /\[/, Punctuation, :push
rule /\]/, Punctuation, :push
rule /\}/, Punctuation, :pop!
end

end
end
end
19 changes: 19 additions & 0 deletions spec/lexers/velocity_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*- #

describe Rouge::Lexers::Velocity do
let(:subject) { Rouge::Lexers::Velocity.new }

describe 'guessing' do
include Support::Guessing

it 'guesses by filename' do
assert_guess :filename => 'foo.velocity'
assert_guess :filename => 'foo.vm'
assert_guess :filename => 'foo.fhtml'
end

it 'guesses by mimetype' do
assert_guess :mimetype => 'text/html+velocity'
end
end
end
28 changes: 28 additions & 0 deletions spec/visual/samples/velocity
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

#*
There is multi-line comment.
see this text because the Velocity Templating Engine will ignore it.
*#
<h3>List</h3>
## This is a single line comment.
#if( $allProducts )
<p>not found.</p>
#else

<table>
<tbody>
#foreach( $product in $allProducts )
<tr id="product-$product.Id" data-url="#SURL("$!product.Slug")">
<td>$product.Title</td>
</tr>
#end
</tbody>
</table>
#end
#set( $monkey.Say = ["Not", $my, "fault", 10, false, null] ) ## ArrayList
${mudSlinger}
${customer.Address}
${purchase.getTotal(true)}
$title.set( "Homage to Catalonia" )