Skip to content

Commit

Permalink
Merge pull request #8 from nulian/no-longer-convert-assigns-to-atom
Browse files Browse the repository at this point in the history
No longer convert assigns to atom
  • Loading branch information
nulian committed Jun 1, 2016
2 parents 9892545 + 9e8252a commit ffee213
Show file tree
Hide file tree
Showing 25 changed files with 244 additions and 252 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Compile a template from a string:

Render the template with a keyword list representing the local variables:

`{ :ok, rendered, _ } = Liquid.Template.render(template, [world: "world"])`
`{ :ok, rendered, _ } = Liquid.Template.render(template, %{"world" => "world"})`

The tests should give a pretty good idea of the features implemented so far.

Expand Down
3 changes: 1 addition & 2 deletions lib/liquid/assign.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ defmodule Liquid.Assign do

def render(output, %Tag{markup: markup}, %Context{}=context) do
[[_, to, from]] = syntax |> Regex.scan(markup)
to_atom = to |> String.to_atom
variable = Variable.create(from)
{ from_value, context } = Variable.lookup(variable, context)
result_assign = context.assigns |> Dict.put(to_atom, from_value)
result_assign = context.assigns |> Map.put(to, from_value)
context = %{context | assigns: result_assign}
{ output, context }
end
Expand Down
4 changes: 2 additions & 2 deletions lib/liquid/capture.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ defmodule Liquid.Capture do
end

def render(output, %Block{markup: markup, nodelist: content}, %Context{}=context) do
to_atom = Regex.run(Liquid.variable_parser, markup) |> hd |> String.to_atom
variable_name = Regex.run(Liquid.variable_parser, markup) |> hd
{block_output, context } = Liquid.Render.render(output, content, context)
result_assign = context.assigns |> Dict.put(to_atom, block_output)
result_assign = context.assigns |> Map.put(variable_name, block_output)
context = %{context | assigns: result_assign}
{output, context}
end
Expand Down
2 changes: 1 addition & 1 deletion lib/liquid/context.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Liquid.Context do
defstruct assigns: [], offsets: [], registers: [], presets: [], blocks: [],
defstruct assigns: %{}, offsets: %{}, registers: [], presets: %{}, blocks: [],
extended: false, continue: false, break: false, template: nil

def registers(context, key) do
Expand Down
5 changes: 2 additions & 3 deletions lib/liquid/decrement.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ defmodule Liquid.Decrement do
end

def render(output, %Tag{markup: markup}, %Context{}=context) do
to_atom = markup |> String.to_atom
variable = Variable.create(markup)
{ value, context } = Variable.lookup(variable, context)
value = value || 0
result_assign = context.assigns |> Dict.put(to_atom, value - 1)
result_assign = context.assigns |> Map.put(markup, value - 1)
context = %{context | assigns: result_assign }
{ output ++ [value - 1], context }
end
end
end
50 changes: 25 additions & 25 deletions lib/liquid/for_else.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Liquid.ForElse do
alias Liquid.RangeLookup
defmodule Iterator do
defstruct name: nil, collection: nil, item: nil, reversed: false,
limit: nil, offset: nil, forloop: []
limit: nil, offset: nil, forloop: %{}
end

def syntax, do: ~r/(\w+)\s+in\s+(#{Liquid.quoted_fragment}+)\s*(reversed)?/
Expand All @@ -32,15 +32,15 @@ defmodule Liquid.ForElse do
attributes = Liquid.tag_attributes |> Regex.scan(markup)
limit = attributes |> parse_attribute("limit") |> Variable.create
offset = attributes |> parse_attribute("offset", "0") |> Variable.create
item = item |> String.to_atom

%Iterator{name: orig_collection, item: item, collection: collection,
limit: limit, offset: offset, reversed: reversed}
end

defp parse_attribute(attributes, name, default \\ "nil") do
attributes |> Enum.reduce(default, fn(x, ret) ->
case x do
[_, ^name, <<attribute::binary>>] -> attribute
[_, ^name, attribute] when is_binary(attribute) -> attribute
[_|_] -> ret
end
end)
Expand Down Expand Up @@ -70,7 +70,7 @@ defmodule Liquid.ForElse do
def each(output, [h|t]=list, %Block{iterator: it}=block, %Context{assigns: assigns}=context) do
forloop = next_forloop(it, list |> Enum.count)
block = %{ block | iterator: %{it | forloop: forloop }}
assigns = assigns |> Dict.put(:forloop, forloop) |> Dict.put(it.item, h)
assigns = assigns |> Map.put("forloop", forloop) |> Map.put(it.item, h)
{ output, block_context } = cond do
should_render?(block, forloop, context) && !block.blank ->
Render.render(output, block.nodelist, %{context | assigns: assigns})
Expand All @@ -88,18 +88,18 @@ defmodule Liquid.ForElse do
defp remember_limit(%Block{iterator: it}, context) do
{ limit, context } = lookup_limit(it, context)
limit = limit || 0
key = it.name |> String.to_atom
remembered = context.offsets[key] || 0
%{ context | offsets: context.offsets |> Dict.put(key, remembered + limit) }
remembered = context.offsets[it.name] || 0
%{ context | offsets: context.offsets |> Map.put(it.name, remembered + limit) }
end

defp should_render?(%Block{iterator: %Iterator{}=it}, forloop, context) do
{ limit, _ } = lookup_limit(it, context)
{ offset, _ } = lookup_offset(it, context)

cond do
forloop[:index] <= offset -> false
forloop["index"] <= offset -> false
limit |> is_nil -> true
forloop[:index] > limit + offset -> false
forloop["index"] > limit + offset -> false
true -> true
end
end
Expand All @@ -111,30 +111,30 @@ defmodule Liquid.ForElse do
defp lookup_offset(%Iterator{offset: offset}=it, %Context{}=context) do
case offset.name do
"continue" ->
offset = context.offsets[it.name |> String.to_atom]
offset = context.offsets[it.name]
{ offset || 0, context }
<<_::binary>> -> Variable.lookup(offset, context)
end
end

defp next_forloop(%Iterator{forloop: []}, count) do
[index: 1,
index0: 0,
rindex: count,
rindex0: count - 1,
length: count,
first: true,
last: count == 1]
defp next_forloop(%Iterator{forloop: loop}, count) when map_size(loop) < 1 do
%{"index" => 1,
"index0" => 0,
"rindex" => count,
"rindex0"=> count - 1,
"length" => count,
"first" => true,
"last" => count == 1}
end

defp next_forloop(%Iterator{forloop: loop}, count) do
[index: loop[:index] + 1,
index0: loop[:index0] + 1,
rindex: loop[:rindex] - 1,
rindex0: loop[:rindex0] - 1,
length: loop[:length],
first: false,
last: count == 1]
%{"index" => loop["index"] + 1,
"index0" => loop["index0"] + 1,
"rindex" => loop["rindex"] - 1,
"rindex0"=> loop["rindex0"] - 1,
"length" => loop["length"],
"first" => false,
"last" => count == 1}
end

end
Expand Down
20 changes: 10 additions & 10 deletions lib/liquid/include.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ defmodule Liquid.Include do
defp parse_tag(%Tag{}=tag, parts) do
case parts do
[_, name] -> %{tag | parts: [name: name |> Variable.create]}
[_, name," with "<>_,v] -> %{tag | parts: [name: name |> Variable.create , variable: v |> Variable.create]}
[_, name," with "<>_,v] ->
%{tag | parts: [name: name |> Variable.create , variable: v |> Variable.create]}
[_, name," for "<>_,v] -> %{tag | parts: [name: name |> Variable.create, foreach: v |> Variable.create]}
end
end

defp parse_attributes(markup) do
Liquid.tag_attributes |> Regex.scan(markup) |> Enum.reduce([], fn ([_, key, val], coll) ->
Dict.put(coll, key |> String.to_atom, val |> Variable.create)
Liquid.tag_attributes |> Regex.scan(markup) |> Enum.reduce(%{}, fn ([_, key, val], coll) ->
Map.put(coll, key, val |> Variable.create)
end)
end

Expand All @@ -37,22 +38,21 @@ defmodule Liquid.Include do
presets = build_presets(tag, context)
t = Template.parse(source, presets)
t = %{ t | blocks: context.template.blocks |> Dict.merge(t.blocks) }
key = name |> String.to_atom()
cond do
!is_nil(parts[:variable]) ->
{ item, _ } = Variable.lookup(parts[:variable], context)
render_item(output, key, item, t, context)
render_item(output, name, item, t, context)
!is_nil(parts[:foreach]) ->
{ items, _ } = Variable.lookup(parts[:foreach], context)
render_list(output, key, items, t, context)
true -> render_item(output, key, nil, t, context)
render_list(output, name, items, t, context)
true -> render_item(output, name, nil, t, context)
end
end

defp build_presets(%Tag{}=tag, context) do
tag.attributes |> Enum.reduce([], fn({key, value}, coll) ->
tag.attributes |> Enum.reduce(%{}, fn({key, value}, coll) ->
{ value, _ } = Variable.lookup(value, context)
Dict.put(coll, key, value)
Map.put(coll, key, value)
end)
end

Expand All @@ -71,7 +71,7 @@ defmodule Liquid.Include do
end

defp render_item(output, key, item, template, %Context{}=context) do
assigns = context.assigns |> Dict.merge([{ key, item }])
assigns = context.assigns |> Map.merge(%{ key => item })
{ :ok, rendered, _ } = Template.render(template, %{context | assigns: assigns })
{ output ++ [rendered], context }
end
Expand Down
3 changes: 1 addition & 2 deletions lib/liquid/increment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ defmodule Liquid.Increment do
end

def render(output, %Tag{markup: markup}, %Context{}=context) do
to_atom = markup |> String.to_atom
variable = Variable.create(markup)
{ value, context } = Variable.lookup(variable, context)
value = value || 0
result_assign = context.assigns |> Dict.put(to_atom, value + 1)
result_assign = context.assigns |> Map.put(markup, value + 1)
context = %{context | assigns: result_assign }
{ output ++ [value], context }
end
Expand Down
18 changes: 9 additions & 9 deletions lib/liquid/template.ex
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
defmodule Liquid.Template do
defstruct root: nil, presets: [], blocks: []
defstruct root: nil, presets: %{}, blocks: []
alias Liquid.Template, as: Template
alias Liquid.Render, as: Render
alias Liquid.Context, as: Context

def render(%Template{}=t), do: render(t, [])
def render(%Template{}=t, assigns) when is_list(assigns) do
context = %Context{template: t, assigns: assigns,
presets: t.presets, blocks: t.blocks}
Render.render(t, context)
end

def render(%Template{}=t), do: render(t, %{})
def render(%Template{}=t, %Context{}=c) do
c = %{c | blocks: t.blocks }
c = %{c | presets: t.presets }
c = %{c | template: t }
Render.render(t, c)
end

def parse(<<markup::binary>>, presets \\ []) do
def render(%Template{}=t, assigns) when is_map(assigns) do
context = %Context{template: t, assigns: assigns,
presets: t.presets, blocks: t.blocks}
Render.render(t, context)
end

def parse(<<markup::binary>>, presets \\ %{}) do
Liquid.Parse.parse(markup, %Template{presets: presets})
end

Expand Down
28 changes: 12 additions & 16 deletions lib/liquid/variable.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ defmodule Liquid.Variable do
alias Liquid.Variable, as: Variable
alias Liquid.Context, as: Context

defp literals, do: [nil: nil, null: nil, "": nil,
true: true, false: false,
blank: :blank?, empty: :empty?]
defp literals, do: %{"nil" => nil, "null" => nil, "" => nil,
"true" => true, "false" => false,
"blank" => :blank?, "empty" => :empty?}

def integer, do: ~r/^(-?\d+)$/
def float, do: ~r/^(-?\d[\d\.]+)$/
Expand All @@ -16,12 +16,12 @@ defmodule Liquid.Variable do
@doc """
matches for [] access
"""
def create(<<markup::binary>>) do
def create(markup) when is_binary(markup) do
[name|filters] = Filters.parse(markup)
key = name |> String.strip |> String.to_atom
key = name |> String.strip
variable = %Liquid.Variable{name: name, filters: filters}
cond do
literals |> Dict.has_key?(key) ->
literals |> Map.has_key?(key) ->
value = literals |> Dict.get(key)
%{variable | literal: value }
integer |> Regex.match?(name) ->
Expand Down Expand Up @@ -51,17 +51,15 @@ defmodule Liquid.Variable do
{ ret, context }
end

defp resolve([<<name::binary>>|_]=parts, %Context{}=current, %Context{}=context) do
key = name |> String.to_atom
defp resolve([<<key::binary>>|_]=parts, %Context{}=current, %Context{}=context) do
cond do
current.assigns |> Dict.has_key?(key) ->
current.assigns |> Map.has_key?(key) ->
resolve(parts, current.assigns, context)
current.presets |> Dict.has_key?(key) ->
current.presets |> Map.has_key?(key) ->
resolve(parts, current.presets, context)
true -> { nil, context }
end
end

defp resolve([], current, %Context{}=context), do: { current, context }
defp resolve([<<?[,index::binary>>|parts], current, %Context{}=context) do
[index, _] = String.split(index, "]")
Expand All @@ -77,11 +75,9 @@ defmodule Liquid.Variable do
{ current, context } = resolve(name, current, context)
resolve(parts, current, context)
end

defp resolve(<<_::binary>>, current, %Context{}=context) when not is_list(current), do: { nil, context } # !is_list(current)
defp resolve(<<name::binary>>, current, %Context{}=context) when is_list(current) do
key = String.to_atom(name)
return = Dict.get(current, key)
defp resolve(<<_::binary>>, current, %Context{}=context) when not is_map(current), do: { nil, context } # !is_list(current)
defp resolve(key, current, %Context{}=context) when is_map(current) and is_binary(key) do
return = Map.get(current, key)
{ return, context }
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule Liquid.Mixfile do

def project do
[ app: :liquid,
version: "0.1.4",
version: "0.2.0",
elixir: "~> 1.0",
deps: deps,
name: "Liquid",
Expand Down
8 changes: 4 additions & 4 deletions test/liquid/assign_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ defmodule Liquid.AssignTest do

test :assigned_variable do
assert_result(".foo.", "{% assign foo = values %}.{{ foo[0] }}.",
[values: ["foo", "bar", "baz"]])
%{"values" => ["foo", "bar", "baz"]})

assert_result(".bar.", "{% assign foo = values %}.{{ foo[1] }}.",
[values: ["foo", "bar", "baz"]])
%{"values" => ["foo", "bar", "baz"]})
end

test :assign_with_filter do
assert_result(".bar.", "{% assign foo = values | split: ',' %}.{{ foo[1] }}.",
[values: "foo,bar,baz"])
%{"values" => "foo,bar,baz"})
end

test "assign string to var and then show" do
assert_result("test", "{% assign foo = 'test' %}{{foo}}", [])
assert_result("test", "{% assign foo = 'test' %}{{foo}}", %{})
end

defp assert_result(expected, markup, assigns) do
Expand Down
4 changes: 2 additions & 2 deletions test/liquid/blank_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ defmodule Liquid.BlankTest do
end

test :test_loops_are_blank do
assert_result("", wrap_in_for(" "), [])
assert_result("", wrap_in_for(" "), %{})
end

test :test_if_else_are_blank do
Expand Down Expand Up @@ -62,7 +62,7 @@ defmodule Liquid.BlankTest do
end

defp assert_template_result(expected, markup) do
assert_result(expected, markup, [])
assert_result(expected, markup, %{})
end

defp assert_result(expected, markup, assigns) do
Expand Down
2 changes: 1 addition & 1 deletion test/liquid/capture_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule Liquid.CaptureTest do
end

test :test_captures_block_content_in_variable do
assert_template_result("test string", "{% capture 'var' %}test string{% endcapture %}{{var}}", [])
assert_template_result("test string", "{% capture 'var' %}test string{% endcapture %}{{var}}", %{})
end

test :test_capture_with_hyphen_in_variable_name do
Expand Down
Loading

0 comments on commit ffee213

Please sign in to comment.