-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#170 - Introduce 'capture' template tag
- Loading branch information
Showing
5 changed files
with
226 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
require "./spec_helper" | ||
|
||
describe Marten::Template::Tag::Capture do | ||
describe "::new" do | ||
it "can initialize a regular capture tag" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Hello World, <b>John Doe</b>!\n" | ||
end | ||
|
||
it "can initialize a capture tag making use of the 'unless defined' modifier" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var unless defined") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Hello World, <b>John Doe</b>!\n" | ||
end | ||
|
||
it "raises a syntax error if no variable name is given" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
expect_raises( | ||
Marten::Template::Errors::InvalidSyntax, | ||
"Malformed capture tag: one variable name must be specified." | ||
) do | ||
Marten::Template::Tag::Capture.new(parser, "capture") | ||
end | ||
end | ||
|
||
it "raises a syntax error if more than one variable name is given" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
expect_raises( | ||
Marten::Template::Errors::InvalidSyntax, | ||
"Malformed capture tag: unrecognized syntax." | ||
) do | ||
Marten::Template::Tag::Capture.new(parser, "capture my_var my_var2 my_var3 my_var4") | ||
end | ||
end | ||
end | ||
|
||
describe "#render" do | ||
it "returns an empty string and assigns the captured content to the specified variable" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Hello World, <b>John Doe</b>!\n" | ||
end | ||
|
||
it "returns an empty string and assigns the captured content to the specified variable even if it already exists" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe", "my_var" => "Existing variable"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Hello World, <b>John Doe</b>!\n" | ||
end | ||
|
||
it "does the assignment when the 'unless defined' modifier is used and the variable does not exist" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var unless defined") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Hello World, <b>John Doe</b>!\n" | ||
end | ||
|
||
it "does not do the assignment when the 'unless defined' modifier is used and the variable already exists" do | ||
parser = Marten::Template::Parser.new( | ||
<<-TEMPLATE | ||
Hello World, <b>{{ name }}</b>! | ||
{% endcapture %} | ||
TEMPLATE | ||
) | ||
|
||
tag = Marten::Template::Tag::Capture.new(parser, "capture my_var unless defined") | ||
|
||
context = Marten::Template::Context{"name" => "John Doe", "my_var" => "Existing variable"} | ||
tag.render(context).should be_empty | ||
|
||
context["my_var"].should eq "Existing variable" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
require "./concerns/*" | ||
|
||
module Marten | ||
module Template | ||
module Tag | ||
# The `capture` template tag. | ||
# | ||
# The `capture` template tags allows to define that the output of a block of code should be stored in a variable: | ||
# | ||
# ``` | ||
# {% capture my_var %} | ||
# Hello World, {{ name }}! | ||
# {% endcapture %} | ||
# ``` | ||
# | ||
# It is also possible to use the `unless defined` modifier to only assign the variable if it is not already | ||
# defined in the template context. For example: | ||
# | ||
# ``` | ||
# {% capture my_var unless defined %} | ||
# Hello World, {{ name }}! | ||
# {% endcapture %} | ||
# ``` | ||
class Capture < Base | ||
include CanSplitSmartly | ||
|
||
@assigned_to : String | ||
@capture_nodes : NodeSet | ||
@unless_defined : Bool = false | ||
|
||
def initialize(parser : Parser, source : String) | ||
parts = split_smartly(source) | ||
|
||
if parts.size < 2 | ||
raise Errors::InvalidSyntax.new("Malformed capture tag: one variable name must be specified.") | ||
elsif parts.size == 2 | ||
@assigned_to = parts[1] | ||
elsif parts.size == 4 && parts[-2..] == UNLESS_DEFINED_PARTS | ||
@assigned_to = parts[1] | ||
@unless_defined = true | ||
else | ||
raise Errors::InvalidSyntax.new("Malformed capture tag: unrecognized syntax.") | ||
end | ||
|
||
# Retrieves the inner nodes, up to the `endcapture` tag. | ||
@capture_nodes = parser.parse(up_to: {"endcapture"}) | ||
parser.shift_token | ||
end | ||
|
||
def render(context : Context) : String | ||
if !unless_defined? || !context.has_key?(@assigned_to) | ||
context[@assigned_to] = @capture_nodes.render(context) | ||
end | ||
|
||
"" | ||
end | ||
|
||
private UNLESS_DEFINED_PARTS = ["unless", "defined"] | ||
|
||
private getter? unless_defined | ||
end | ||
end | ||
end | ||
end |