wlang 2.0.0.beta → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|