wlang 2.0.0.beta → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -8
- data/Gemfile.lock +4 -8
- data/Manifest.txt +0 -2
- data/README.md +36 -7
- data/lib/wlang.rb +3 -0
- data/lib/wlang/command.rb +3 -11
- data/lib/wlang/compiler.rb +11 -20
- data/lib/wlang/compiler/autospacing.rb +4 -2
- data/lib/wlang/compiler/dialect_enforcer.rb +1 -1
- data/lib/wlang/compiler/to_ruby_code.rb +1 -1
- data/lib/wlang/dialect.rb +163 -23
- data/lib/wlang/html.rb +9 -8
- data/lib/wlang/loader.rb +2 -4
- data/lib/wlang/scope.rb +17 -8
- data/lib/wlang/scope/proc_scope.rb +18 -0
- data/lib/wlang/source.rb +56 -0
- data/lib/wlang/source/front_matter.rb +51 -0
- data/lib/wlang/template.rb +55 -17
- data/lib/wlang/tilt.rb +3 -0
- data/lib/wlang/tilt/wlang_template.rb +43 -0
- data/lib/wlang/version.rb +1 -2
- data/spec/fixtures/templates/{hello.tpl → hello.wlang} +0 -0
- data/spec/fixtures/templates/hello_with_data.wlang +4 -0
- data/spec/fixtures/templates/hello_with_explicit_locals.wlang +6 -0
- data/spec/fixtures/templates/hello_with_partials.wlang +7 -0
- data/spec/integration/examples/{1-basics.txt → 1-html-intro/1-basics.md} +1 -1
- data/spec/integration/examples/{2-imperative.txt → 1-html-intro/2-imperative.md} +1 -1
- data/spec/integration/examples/{3-partials.txt → 1-html-intro/3-partials.md} +0 -0
- data/spec/integration/examples/{4-recursion.txt → 1-html-intro/4-recursion.md} +1 -2
- data/spec/integration/examples/1-html-intro/5-polymorphism.md +17 -0
- data/spec/integration/html/test_caret.rb +15 -2
- data/spec/integration/html/test_question.rb +12 -2
- data/spec/integration/html/test_sharp.rb +5 -1
- data/spec/integration/html/test_star.rb +1 -3
- data/spec/integration/test_examples.rb +2 -1
- data/spec/integration/test_readme.rb +14 -2
- data/spec/integration/tilt/test_wlang_template.rb +13 -0
- data/spec/spec_helper.rb +3 -3
- data/spec/unit/compiler/test_dialect_enforcer.rb +1 -1
- data/spec/unit/compiler/test_to_ruby_proc.rb +15 -0
- data/spec/unit/dialect/test_compile.rb +0 -10
- data/spec/unit/dialect/test_evaluate.rb +36 -28
- data/spec/unit/dialect/test_new.rb +61 -0
- data/spec/unit/dialect/test_tag.rb +36 -0
- data/spec/unit/dialect/test_tag_dispatching_name.rb +22 -0
- data/spec/unit/dialect/test_with_scope.rb +8 -11
- data/spec/unit/scope/test_chain.rb +29 -0
- data/spec/unit/scope/test_coerce.rb +13 -2
- data/spec/unit/scope/test_proc_scope.rb +18 -0
- data/spec/unit/source/front_matter/test_locals.rb +39 -0
- data/spec/unit/source/front_matter/test_template_content.rb +22 -0
- data/spec/unit/source/test_locals.rb +12 -0
- data/spec/unit/source/test_path.rb +27 -0
- data/spec/unit/source/test_template_content.rb +37 -0
- data/spec/unit/source/test_with_front_matter.rb +19 -0
- data/spec/unit/template/test_call.rb +16 -0
- data/spec/unit/template/test_new.rb +20 -0
- data/spec/unit/template/test_path.rb +28 -0
- data/spec/unit/template/test_render.rb +44 -0
- data/spec/unit/template/test_to_ast.rb +12 -0
- data/spec/unit/template/test_to_ruby_code.rb +13 -0
- data/spec/unit/template/test_to_ruby_proc.rb +12 -0
- data/spec/unit/template/test_yaml_front_matter.rb +22 -0
- data/spec/unit/tilt/test_wlang_template.rb +65 -0
- data/wlang.gemspec +3 -5
- data/wlang.noespec +12 -17
- metadata +117 -85
- data/lib/wlang/dialect/dispatching.rb +0 -51
- data/lib/wlang/dialect/evaluation.rb +0 -30
- data/lib/wlang/dialect/tags.rb +0 -50
- data/lib/wlang/mustang.rb +0 -90
- data/spec/integration/test_mustang.rb +0 -120
- data/spec/unit/dialect/test_dispatching.rb +0 -19
- data/spec/unit/dialect/test_tags.rb +0 -32
@@ -3,11 +3,17 @@ require 'wlang/html'
|
|
3
3
|
module WLang
|
4
4
|
describe Html, "?{...}" do
|
5
5
|
|
6
|
+
debug = Module.new{ def inspect; "lambda{ #{call.inspect} }"; end }
|
7
|
+
|
6
8
|
def render(tpl, scope = {})
|
7
9
|
Html.render(tpl, scope, "")
|
8
10
|
end
|
9
11
|
|
10
|
-
[true,
|
12
|
+
[ true,
|
13
|
+
"Something",
|
14
|
+
[],
|
15
|
+
lambda{ true }.extend(debug)
|
16
|
+
].each do |test|
|
11
17
|
context "when #{test.inspect}" do
|
12
18
|
it 'renders the then block' do
|
13
19
|
render("?{test}{hello}", binding).should eq("hello")
|
@@ -18,7 +24,11 @@ module WLang
|
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
21
|
-
[false,
|
27
|
+
[ false,
|
28
|
+
nil,
|
29
|
+
lambda{ false }.extend(debug),
|
30
|
+
lambda{ nil }.extend(debug)
|
31
|
+
].each do |test|
|
22
32
|
context "when #{test.inspect}" do
|
23
33
|
it 'do not render the then block' do
|
24
34
|
render("?{test}{hello}", binding).should eq("")
|
@@ -18,9 +18,7 @@ module WLang
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'preserves spacing in the third block' do
|
21
|
-
|
22
|
-
render("*{numbers}{+{self}}{, }", binding).should eq("1, 2, 3")
|
23
|
-
}
|
21
|
+
render("*{numbers}{+{self}}{, }", binding).should eq("1, 2, 3")
|
24
22
|
end
|
25
23
|
|
26
24
|
it 'renders nothing on empty collections' do
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'wlang/mustang'
|
3
2
|
module WLang
|
4
|
-
describe
|
3
|
+
describe "Examples in README.md" do
|
5
4
|
|
6
5
|
describe "The Highlighter example" do
|
7
6
|
|
@@ -52,5 +51,18 @@ module WLang
|
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
54
|
+
describe 'tilt integration' do
|
55
|
+
it 'works as announced' do
|
56
|
+
require 'tilt' # needed in your bundle, not a wlang dependency
|
57
|
+
require 'wlang/tilt' # load wlang integration specifycally
|
58
|
+
|
59
|
+
template = Tilt.new(hello_path.to_s) # suppose 'Hello ${who}!'
|
60
|
+
template.render(:who => "world").should eq('Hello world!')
|
61
|
+
|
62
|
+
template = Tilt.new(hello_path.to_s, :dialect => Highlighter)
|
63
|
+
template.render(:who => "world").should eq('Hello WORLD!')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
55
67
|
end
|
56
68
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'wlang/tilt'
|
3
|
+
describe 'WLang integration with tilt' do
|
4
|
+
|
5
|
+
it 'allows invoking tilt directly' do
|
6
|
+
Tilt.new(hello_path.to_s).render(:who => "world").should eq("Hello world!")
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'allows specifying the dialect' do
|
10
|
+
Tilt.new(hello_path.to_s, :dialect => Upcasing).render.should eq("Hello WHO!")
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -24,7 +24,7 @@ module Helpers
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def tpl_path(what)
|
27
|
-
what = "#{what}.
|
27
|
+
what = "#{what}.wlang" if what.is_a?(Symbol)
|
28
28
|
fixtures_folder/:templates/what
|
29
29
|
end
|
30
30
|
|
@@ -38,7 +38,7 @@ module Helpers
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Install helper methods for templates
|
41
|
-
fixtures_folder.glob("templates/*.
|
41
|
+
fixtures_folder.glob("templates/*.wlang").each do |f|
|
42
42
|
name = f.basename.without_extension
|
43
43
|
define_method(:"#{name}_path") do
|
44
44
|
fixtures_folder/:templates/f.basename
|
@@ -59,5 +59,5 @@ include Helpers
|
|
59
59
|
# Configure rspec
|
60
60
|
RSpec.configure do |c|
|
61
61
|
c.include Helpers
|
62
|
-
c.filter_run_excluding :hash_ordering =>
|
62
|
+
c.filter_run_excluding :hash_ordering => (RUBY_VERSION < "1.9")
|
63
63
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Compiler, 'to_ruby_proc' do
|
4
|
+
|
5
|
+
def to_ruby_proc(source)
|
6
|
+
Compiler.new(WLang::Dialect.new).to_ruby_proc(source)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'returns a proc even if no tag at all' do
|
10
|
+
source = "Hello world!"
|
11
|
+
to_ruby_proc(source).should be_a(Proc)
|
12
|
+
end
|
13
|
+
|
14
|
+
end # describe Compiler, 'to_ruby_proc'
|
15
|
+
end # module WLang
|
@@ -20,16 +20,6 @@ module WLang
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
it 'supports a no-op' do
|
24
|
-
t = compile(hello_tpl)
|
25
|
-
compile(t).should eq(t)
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'supports a proc' do
|
29
|
-
proc = compile(hello_tpl).inner_proc
|
30
|
-
compile(proc).should be_a(Template)
|
31
|
-
end
|
32
|
-
|
33
23
|
specify 'returned template is callable' do
|
34
24
|
compile(hello_tpl).call.should eq("Hello WHO!")
|
35
25
|
end
|
@@ -1,41 +1,49 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module WLang
|
3
|
-
|
4
|
-
describe Evaluation, "evaluate" do
|
5
|
-
include Evaluation
|
3
|
+
describe Dialect, 'evaluate' do
|
6
4
|
|
7
|
-
|
5
|
+
let(:struct){ Struct.new(:who) }
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
let(:dialect){ Dialect.new }
|
8
|
+
|
9
|
+
def with_scope(*args, &bl)
|
10
|
+
dialect.with_scope(*args, &bl)
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate(*args, &bl)
|
14
|
+
dialect.evaluate(*args, &bl)
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
17
|
+
it 'works with a hash' do
|
18
|
+
with_scope({:who => "World"}) do
|
19
|
+
evaluate("who").should eq("World")
|
20
|
+
evaluate(:who).should eq("World")
|
21
21
|
end
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
it 'works with a struct' do
|
25
|
+
with_scope(struct.new("World")) do
|
26
|
+
evaluate("who").should eq("World")
|
27
|
+
evaluate(:who).should eq("World")
|
27
28
|
end
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
31
|
+
it 'uses the hash in priority' do
|
32
|
+
with_scope({:keys => [1,2,3]}) do
|
33
|
+
evaluate("keys").should eq([1,2,3])
|
33
34
|
end
|
35
|
+
end
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
+
it 'falls back to send' do
|
38
|
+
with_scope({:who => "World"}) do
|
39
|
+
evaluate("keys").should eq([:who])
|
37
40
|
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'raises a NameError when not found' do
|
44
|
+
lambda{ evaluate("who") }.should raise_error(NameError)
|
45
|
+
end
|
46
|
+
|
47
|
+
end # describe Dialect, 'evaluate'
|
48
|
+
end # module WLang
|
38
49
|
|
39
|
-
end # describe Evaluation, "evaluate"
|
40
|
-
end # class Dialect
|
41
|
-
end # module WLang
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Dialect, 'new' do
|
4
|
+
|
5
|
+
let(:base){ Dialect.default_options }
|
6
|
+
let(:template){ Template.new "blah" }
|
7
|
+
|
8
|
+
subject{ Dialect.new(*args) }
|
9
|
+
|
10
|
+
context 'with no arguments' do
|
11
|
+
let(:args){ [] }
|
12
|
+
it 'should have default options' do
|
13
|
+
subject.options.should eq(base)
|
14
|
+
end
|
15
|
+
it 'should not have a template' do
|
16
|
+
subject.template.should be_nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with only options' do
|
21
|
+
let(:args){ [{:foo => :bar}] }
|
22
|
+
it 'should have merged options' do
|
23
|
+
subject.options.should eq(base.merge(:foo => :bar))
|
24
|
+
end
|
25
|
+
it 'should not have a template' do
|
26
|
+
subject.template.should be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with only a template' do
|
31
|
+
let(:args){ [template] }
|
32
|
+
it 'should have default options' do
|
33
|
+
subject.options.should eq(base)
|
34
|
+
end
|
35
|
+
it 'should not have a template' do
|
36
|
+
subject.template.should eq(template)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'with options and a template' do
|
41
|
+
let(:args){ [{:foo => :bar}, template] }
|
42
|
+
it 'should have merged options' do
|
43
|
+
subject.options.should eq(base.merge(:foo => :bar))
|
44
|
+
end
|
45
|
+
it 'should not have a template' do
|
46
|
+
subject.template.should eq(template)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with options and a template in reverse order' do
|
51
|
+
let(:args){ [template, {:foo => :bar}] }
|
52
|
+
it 'should have merged options' do
|
53
|
+
subject.options.should eq(base.merge(:foo => :bar))
|
54
|
+
end
|
55
|
+
it 'should not have a template' do
|
56
|
+
subject.template.should eq(template)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end # describe Dialect, 'new'
|
61
|
+
end # module WLang
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Dialect, 'tag' do
|
4
|
+
|
5
|
+
let(:dialect){ Class.new(Dialect) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
def dialect.define_tag_method(*args)
|
9
|
+
args
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def tag(*args, &bl)
|
14
|
+
dialect.tag(*args, &bl)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "works with a symbol" do
|
18
|
+
tag("$", :dollar).should eq(["$", nil, :dollar])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "works with a single proc" do
|
22
|
+
proc = lambda{|buf,fn| }
|
23
|
+
tag("$", &proc).should eq(["$", nil, proc])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "allows specifying dialects with a symbol" do
|
27
|
+
tag("$", [Foo], :dollar).should eq(["$", [Foo], :dollar])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "allows specifying dialects with a proc" do
|
31
|
+
proc = lambda{|buf,fn| }
|
32
|
+
tag("$", [Foo], &proc).should eq(["$", [Foo], proc])
|
33
|
+
end
|
34
|
+
|
35
|
+
end # describe Dialect
|
36
|
+
end # module WLang
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Dialect, 'tag_dispatching_name' do
|
4
|
+
|
5
|
+
def tag_dispatching_name(symbol)
|
6
|
+
Dialect.tag_dispatching_name(symbol)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "works with a single char" do
|
10
|
+
tag_dispatching_name("$").should eq(:_tag_36)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "works with a multiple chars" do
|
14
|
+
tag_dispatching_name("!$").should eq(:_tag_33_36)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "works with an array" do
|
18
|
+
tag_dispatching_name(['!', '$']).should eq(:_tag_33_36)
|
19
|
+
end
|
20
|
+
|
21
|
+
end # describe Dialect
|
22
|
+
end # module WLang
|
@@ -1,18 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module WLang
|
3
|
-
|
4
|
-
describe Evaluation, "with_scope" do
|
5
|
-
include Evaluation
|
3
|
+
describe Dialect, 'with_scope' do
|
6
4
|
|
7
|
-
|
5
|
+
let(:struct){ Struct.new(:who) }
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
got.should eq(12)
|
7
|
+
it 'returns the block value' do
|
8
|
+
got = Dialect.new.with_scope({:who => "World"}) do
|
9
|
+
12
|
14
10
|
end
|
11
|
+
got.should eq(12)
|
12
|
+
end
|
15
13
|
|
16
|
-
|
17
|
-
end # class Dialect
|
14
|
+
end # describe Dialect, 'with_scope'
|
18
15
|
end # module WLang
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module WLang
|
2
|
+
describe Scope, '.chain' do
|
3
|
+
|
4
|
+
it 'returns Scope.root on empty chain' do
|
5
|
+
Scope.chain([]).should eq(Scope.root)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns a single scope on singleton' do
|
9
|
+
s = Scope.chain([{:who => "World"}])
|
10
|
+
s.should be_a(Scope::ObjectScope)
|
11
|
+
s.parent.should eq(Scope.root)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'uses the last scope as most specific' do
|
15
|
+
s = Scope.chain([{:who => "World"}, lambda{}])
|
16
|
+
s.should be_a(Scope::ProcScope)
|
17
|
+
s.parent.should be_a(Scope::ObjectScope)
|
18
|
+
s.parent.parent.should eq(Scope.root)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'strips nils' do
|
22
|
+
s = Scope.chain([nil, {:who => "World"}, nil, lambda{}, nil])
|
23
|
+
s.should be_a(Scope::ProcScope)
|
24
|
+
s.parent.should be_a(Scope::ObjectScope)
|
25
|
+
s.parent.parent.should eq(Scope.root)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -6,8 +6,8 @@ module WLang
|
|
6
6
|
Scope.coerce(binding).should be_a(Scope::BindingScope)
|
7
7
|
end
|
8
8
|
|
9
|
-
it 'recognizes
|
10
|
-
Scope.coerce(
|
9
|
+
it 'recognizes Procs' do
|
10
|
+
Scope.coerce(lambda{}).should be_a(Scope::ProcScope)
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'falls back to ObjectScope on Hash' do
|
@@ -18,5 +18,16 @@ module WLang
|
|
18
18
|
Scope.coerce(12).should be_a(Scope::ObjectScope)
|
19
19
|
end
|
20
20
|
|
21
|
+
it 'returns the Scope if nothing has to be done' do
|
22
|
+
Scope.coerce(Scope.root).should eq(Scope.root)
|
23
|
+
s = Scope.coerce({})
|
24
|
+
Scope.coerce(s).should eq(s)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'builds ProxyScope on Scopes' do
|
28
|
+
s = Scope.coerce({})
|
29
|
+
Scope.coerce(s, Scope.root).should be_a(Scope::ProxyScope)
|
30
|
+
end
|
31
|
+
|
21
32
|
end # describe Scope
|
22
33
|
end # module WLang
|