Skip to content

Commit

Permalink
Fix support for :attr_list_delims config option
Browse files Browse the repository at this point in the history
This introduces new compile-time dependency: neotoma parser
  • Loading branch information
Rakoth committed Apr 8, 2017
1 parent 0e6faed commit f770eba
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 527 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
erl_crash.dump
*.ez
/bench/snapshots
/src/slime_parser.peg
/src/slime_parser.erl
26 changes: 18 additions & 8 deletions lib/slime/parser/transform.ex
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,29 @@ defmodule Slime.Parser.Transform do
]}
end

def transform(:simple_tag, node, _index) do
{tag_name, initial_attrs} = node[:tag]
attrs = case node[:attrs] do
[] -> []
[_space, attrs_list] -> attrs_list
def transform(:simple_tag_content_without_attrs, [_, content], _index), do: content

def transform(:attributes_with_content, node, _index) do
{attrs, content} = case node do
[attrs, _, content] -> {attrs, content}
content -> {[], content}
end

content = case node[:content] do
content = case content do
[] -> [{:close, false}]
[_, "/"] -> [{:close, true}]
[_, child] -> [{:children, [child]}, {:close, false}]
"/" -> [{:close, true}]
"" -> [{:close, false}]
child -> [{:children, [child]}, {:close, false}]
end

[attrs: attrs, content: content]
end

def transform(:simple_tag, node, _index) do
{tag_name, initial_attrs} = node[:tag]
attrs = Keyword.get(node[:attrs_with_content], :attrs, [])
content = Keyword.get(node[:attrs_with_content], :content, [])

attributes =
initial_attrs
|> Enum.concat(attrs)
Expand Down
9 changes: 5 additions & 4 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ defmodule Slime.Mixfile do
version: @version]
end

defp compilers(:prod), do: nil
defp compilers(_), do: [:peg, :erlang, :elixir, :app]

def application do
[applications: [:eex]]
[
applications: [:eex]
]
end

def package do
Expand All @@ -42,6 +43,8 @@ defmodule Slime.Mixfile do

def deps do
[
# packrat parser-generator for PEGs
{:neotoma, "~> 1.7"},
# Benchmarking tool
{:benchfella, ">= 0.0.0", only: ~w(dev test)a},
# Documentation
Expand All @@ -52,8 +55,6 @@ defmodule Slime.Mixfile do
{:credo, ">= 0.0.0", only: ~w(dev test)a},
# HTML generation helpers
{:phoenix_html, "~> 2.6", only: :test},
# packrat parser-generator for PEGs
{:neotoma, "~> 1.7", only: ~w(dev test)a},
]
end
end
505 changes: 0 additions & 505 deletions src/slime_parser.erl

This file was deleted.

20 changes: 14 additions & 6 deletions src/slime_parser.peg → src/slime_parser.peg.eex
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ html_tag <- inline_tag / simple_tag;

inline_tag <- tag:tag_shortcut ':' space children:simple_tag;

simple_tag <- tag:tag_shortcut spaces:tag_spaces?
attrs:(space? attributes)?
content:(space? '/' / space? dynamic_content / space text_content)?;
simple_tag <- tag:tag_shortcut spaces:tag_spaces? space? attrs_with_content:attributes_with_content?;

attributes_with_content <- attributes space? simple_tag_content? / simple_tag_content_without_attrs;

simple_tag_content <- '/' / dynamic_content / text_content;

% NOTE: tag content can not begin from valid wrapped attributes bracket if attributes are not present
simple_tag_content_without_attrs <-
!('<%= attr_list_delims |> Map.keys |> Enum.join("' / '") %>') simple_tag_content;

text_content <- dynamic:text_with_interpolation / simple:text;

Expand All @@ -44,9 +50,11 @@ shortcut <- type:('.' / '#' / '@' / '$' / '%' / '^' / '&' / '+' / '!') value:tag
attributes <- wrapped_attributes / plain_attributes;

wrapped_attributes <-
'[' wrapped_attributes_list ']' /
'(' wrapped_attributes_list ')' /
'{' wrapped_attributes_list '}';
<%=
attr_list_delims
|> Enum.map(fn ({open, close}) -> "'#{open}' wrapped_attributes_list '#{close}'" end)
|> Enum.join(" / ")
%>;

wrapped_attributes_list <- head:wrapped_attribute tail:(space wrapped_attribute)*;

Expand Down
14 changes: 12 additions & 2 deletions tasks/compile.peg.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
defmodule Mix.Tasks.Compile.Peg do
@moduledoc """
Compile peg template file into parser module
"""

use Mix.Task
require EEx

@recursive true

def run(_) do
peg = Path.expand("src/slime_parser.peg")
case :neotoma.file('#{peg}', transform_module: :slime_parser_transform) do
attr_list_delims = Application.get_env(
:slime, :attr_list_delims, %{"[" => "]", "(" => ")", "{" => "}"}
)
grammar = EEx.eval_file("src/slime_parser.peg.eex", attr_list_delims: attr_list_delims)
File.write!("src/slime_parser.peg", grammar)
peg = "src/slime_parser.peg" |> Path.expand |> String.to_charlist
case :neotoma.file(peg, transform_module: :slime_parser_transform) do
:ok -> :ok
{:error, reason} ->
Mix.shell.error "Failed to compile: #{inspect reason}"
Expand Down
1 change: 0 additions & 1 deletion test/parser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ defmodule ParserTest do
end)
end

@tag :pending
test ~s(show error message for div [id="test"} case with leading space) do
assert_raise(Slime.TemplateSyntaxError, fn () ->
parse_line(~S(div [id="test"}))
Expand Down
6 changes: 5 additions & 1 deletion test/rendering/attributes_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,16 @@ defmodule RenderAttributesTest do
assert render(slime, test: "1") == ~s(<p c="1"></p>)
end

@tag :pending
test "render of disabled wrapped attributes" do
slime = "p {c=true}"
assert render(slime) == ~s(<p>{c=true}</p>)
end

test "render of disabled wrapped attributes without space" do
slime = "p{c=true}"
assert render(slime) == ~s(<p>{c=true}</p>)
end

test "do not overescape quotes in attributes" do
defmodule RenderHelperMethodWithQuotesArguments do
require Slime
Expand Down

0 comments on commit f770eba

Please sign in to comment.