Skip to content

Commit 79e0fa7

Browse files
Add ERB lexer (#1228)
1 parent b59560d commit 79e0fa7

4 files changed

Lines changed: 1413 additions & 0 deletions

File tree

‎lexers/embedded/erb.xml‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<lexer>
2+
<config>
3+
<name>ERB</name>
4+
<dot_all>true</dot_all>
5+
</config>
6+
<rules>
7+
<state name="root">
8+
<rule pattern="(&lt;%#)(.*?)(-?%&gt;)">
9+
<bygroups>
10+
<token type="CommentPreproc"/>
11+
<token type="Comment"/>
12+
<token type="CommentPreproc"/>
13+
</bygroups>
14+
</rule>
15+
<rule pattern="(&lt;%-?=)(.*?)(-?%&gt;)">
16+
<bygroups>
17+
<token type="CommentPreproc"/>
18+
<using lexer="Ruby"/>
19+
<token type="CommentPreproc"/>
20+
</bygroups>
21+
</rule>
22+
<rule pattern="(&lt;%-?)(.*?)(-?%&gt;)">
23+
<bygroups>
24+
<token type="CommentPreproc"/>
25+
<using lexer="Ruby"/>
26+
<token type="CommentPreproc"/>
27+
</bygroups>
28+
</rule>
29+
<rule pattern="[^&lt;]+">
30+
<token type="Other"/>
31+
</rule>
32+
<rule pattern="&lt;">
33+
<token type="Other"/>
34+
</rule>
35+
</state>
36+
</rules>
37+
</lexer>

‎lexers/erb.go‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package lexers
2+
3+
import (
4+
"strings"
5+
6+
. "github.com/alecthomas/chroma/v2" // nolint
7+
)
8+
9+
// ERB lexer is Ruby embedded in HTML.
10+
var ERB = Register(DelegatingLexer(HTML, MustNewXMLLexer(
11+
embedded,
12+
"embedded/erb.xml",
13+
).SetConfig(
14+
&Config{
15+
Name: "ERB",
16+
Aliases: []string{"erb", "html+erb", "html+ruby", "rhtml"},
17+
Filenames: []string{"*.erb", "*.html.erb", "*.xml.erb", "*.rhtml"},
18+
MimeTypes: []string{"application/x-ruby-templating"},
19+
DotAll: true,
20+
},
21+
).SetAnalyser(func(text string) float32 {
22+
if strings.Contains(text, "<%=") && strings.Contains(text, "%>") {
23+
return 0.4
24+
}
25+
if strings.Contains(text, "<%") {
26+
return 0.1
27+
}
28+
return 0.0
29+
})))

‎lexers/testdata/erb.actual‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!DOCTYPE html>
2+
<html lang="<%= I18n.locale %>">
3+
<head>
4+
<title><%= content_for?(:title) ? yield(:title) : "Default Title" %></title>
5+
<%= csrf_meta_tags %>
6+
<%= csp_meta_tag %>
7+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
8+
</head>
9+
<body class="<%= controller_name %> <%= action_name %>">
10+
11+
<%# Navigation partial %>
12+
<%= render "shared/navbar", user: current_user %>
13+
14+
<%# ERB comment spanning
15+
multiple lines %>
16+
17+
<% if current_user.admin? %>
18+
<div class="admin-banner">
19+
<p>Welcome, <%= current_user.name %>! You have <%= current_user.roles.count %> roles.</p>
20+
</div>
21+
<% end %>
22+
23+
<% @posts.each_with_index do |post, index| %>
24+
<article id="post-<%= post.id %>" class="<%= cycle('odd', 'even') %>" data-tags="<%= post.tags.pluck(:name).join(',') %>">
25+
<h2><%= link_to post.title, post_path(post), class: "post-link" %></h2>
26+
27+
<div class="meta">
28+
<span><%= l(post.created_at, format: :long) %></span>
29+
<span><%= pluralize(post.comments.count, "comment") %></span>
30+
<%= "Featured" if post.featured? %>
31+
</div>
32+
33+
<div class="body">
34+
<%= sanitize post.body, tags: %w[p br strong em a ul ol li code pre], attributes: %w[href class id] %>
35+
</div>
36+
37+
<% if post.tags.any? %>
38+
<ul class="tags">
39+
<% post.tags.each do |tag| %>
40+
<li><%= link_to tag.name, tag_path(tag) %></li>
41+
<% end %>
42+
</ul>
43+
<% end %>
44+
45+
<%# Render comments if they exist %>
46+
<% unless post.comments.empty? %>
47+
<section class="comments">
48+
<%= render partial: "comments/comment", collection: post.comments, as: :comment, locals: { editable: current_user&.admin? } %>
49+
</section>
50+
<% end %>
51+
</article>
52+
<% end %>
53+
54+
<%= form_with(model: @post, local: true, data: { turbo: false, controller: "form" }) do |f| %>
55+
<% if @post.errors.any? %>
56+
<div id="error_explanation">
57+
<h2><%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:</h2>
58+
<ul>
59+
<% @post.errors.full_messages.each do |message| %>
60+
<li><%= message %></li>
61+
<% end %>
62+
</ul>
63+
</div>
64+
<% end %>
65+
66+
<div class="field">
67+
<%= f.label :title %>
68+
<%= f.text_field :title, placeholder: "Enter title...", required: true, maxlength: 255 %>
69+
</div>
70+
71+
<div class="field">
72+
<%= f.label :body %>
73+
<%= f.text_area :body, rows: 10, data: { action: "input->form#validate" } %>
74+
</div>
75+
76+
<div class="field">
77+
<%= f.label :category_id %>
78+
<%= f.collection_select :category_id, Category.order(:name), :id, :name, { prompt: "Select a category" }, { class: "form-control" } %>
79+
</div>
80+
81+
<div class="actions">
82+
<%= f.submit @post.persisted? ? "Update Post" : "Create Post", class: "btn btn-primary" %>
83+
<%= link_to "Cancel", posts_path, class: "btn btn-secondary" %>
84+
</div>
85+
<% end %>
86+
87+
<%- trimmed = @items.select { |i| i.active? && i.visible_to?(current_user) } -%>
88+
<%= render partial: "items/grid", locals: { items: trimmed, columns: 3 } %>
89+
90+
<% content_for :sidebar do %>
91+
<div class="sidebar">
92+
<h3>Recent Posts</h3>
93+
<ul>
94+
<% Post.published.order(created_at: :desc).limit(5).each do |post| %>
95+
<li><%= link_to post.title, post %></li>
96+
<% end %>
97+
</ul>
98+
99+
<h3>Archives</h3>
100+
<% Post.published.group_by { |p| p.created_at.strftime("%B %Y") }.each do |month, posts| %>
101+
<p><%= link_to "#{month} (#{posts.size})", archive_path(month: month) %></p>
102+
<% end %>
103+
</div>
104+
<% end %>
105+
106+
<script>
107+
var postCount = <%= @posts.count %>;
108+
var config = <%= raw({ api_key: ENV["API_KEY"], debug: Rails.env.development? }.to_json) %>;
109+
</script>
110+
111+
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
112+
</body>
113+
</html>

0 commit comments

Comments
 (0)