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.
Files changed (74) hide show
  1. data/Gemfile +2 -8
  2. data/Gemfile.lock +4 -8
  3. data/Manifest.txt +0 -2
  4. data/README.md +36 -7
  5. data/lib/wlang.rb +3 -0
  6. data/lib/wlang/command.rb +3 -11
  7. data/lib/wlang/compiler.rb +11 -20
  8. data/lib/wlang/compiler/autospacing.rb +4 -2
  9. data/lib/wlang/compiler/dialect_enforcer.rb +1 -1
  10. data/lib/wlang/compiler/to_ruby_code.rb +1 -1
  11. data/lib/wlang/dialect.rb +163 -23
  12. data/lib/wlang/html.rb +9 -8
  13. data/lib/wlang/loader.rb +2 -4
  14. data/lib/wlang/scope.rb +17 -8
  15. data/lib/wlang/scope/proc_scope.rb +18 -0
  16. data/lib/wlang/source.rb +56 -0
  17. data/lib/wlang/source/front_matter.rb +51 -0
  18. data/lib/wlang/template.rb +55 -17
  19. data/lib/wlang/tilt.rb +3 -0
  20. data/lib/wlang/tilt/wlang_template.rb +43 -0
  21. data/lib/wlang/version.rb +1 -2
  22. data/spec/fixtures/templates/{hello.tpl → hello.wlang} +0 -0
  23. data/spec/fixtures/templates/hello_with_data.wlang +4 -0
  24. data/spec/fixtures/templates/hello_with_explicit_locals.wlang +6 -0
  25. data/spec/fixtures/templates/hello_with_partials.wlang +7 -0
  26. data/spec/integration/examples/{1-basics.txt → 1-html-intro/1-basics.md} +1 -1
  27. data/spec/integration/examples/{2-imperative.txt → 1-html-intro/2-imperative.md} +1 -1
  28. data/spec/integration/examples/{3-partials.txt → 1-html-intro/3-partials.md} +0 -0
  29. data/spec/integration/examples/{4-recursion.txt → 1-html-intro/4-recursion.md} +1 -2
  30. data/spec/integration/examples/1-html-intro/5-polymorphism.md +17 -0
  31. data/spec/integration/html/test_caret.rb +15 -2
  32. data/spec/integration/html/test_question.rb +12 -2
  33. data/spec/integration/html/test_sharp.rb +5 -1
  34. data/spec/integration/html/test_star.rb +1 -3
  35. data/spec/integration/test_examples.rb +2 -1
  36. data/spec/integration/test_readme.rb +14 -2
  37. data/spec/integration/tilt/test_wlang_template.rb +13 -0
  38. data/spec/spec_helper.rb +3 -3
  39. data/spec/unit/compiler/test_dialect_enforcer.rb +1 -1
  40. data/spec/unit/compiler/test_to_ruby_proc.rb +15 -0
  41. data/spec/unit/dialect/test_compile.rb +0 -10
  42. data/spec/unit/dialect/test_evaluate.rb +36 -28
  43. data/spec/unit/dialect/test_new.rb +61 -0
  44. data/spec/unit/dialect/test_tag.rb +36 -0
  45. data/spec/unit/dialect/test_tag_dispatching_name.rb +22 -0
  46. data/spec/unit/dialect/test_with_scope.rb +8 -11
  47. data/spec/unit/scope/test_chain.rb +29 -0
  48. data/spec/unit/scope/test_coerce.rb +13 -2
  49. data/spec/unit/scope/test_proc_scope.rb +18 -0
  50. data/spec/unit/source/front_matter/test_locals.rb +39 -0
  51. data/spec/unit/source/front_matter/test_template_content.rb +22 -0
  52. data/spec/unit/source/test_locals.rb +12 -0
  53. data/spec/unit/source/test_path.rb +27 -0
  54. data/spec/unit/source/test_template_content.rb +37 -0
  55. data/spec/unit/source/test_with_front_matter.rb +19 -0
  56. data/spec/unit/template/test_call.rb +16 -0
  57. data/spec/unit/template/test_new.rb +20 -0
  58. data/spec/unit/template/test_path.rb +28 -0
  59. data/spec/unit/template/test_render.rb +44 -0
  60. data/spec/unit/template/test_to_ast.rb +12 -0
  61. data/spec/unit/template/test_to_ruby_code.rb +13 -0
  62. data/spec/unit/template/test_to_ruby_proc.rb +12 -0
  63. data/spec/unit/template/test_yaml_front_matter.rb +22 -0
  64. data/spec/unit/tilt/test_wlang_template.rb +65 -0
  65. data/wlang.gemspec +3 -5
  66. data/wlang.noespec +12 -17
  67. metadata +117 -85
  68. data/lib/wlang/dialect/dispatching.rb +0 -51
  69. data/lib/wlang/dialect/evaluation.rb +0 -30
  70. data/lib/wlang/dialect/tags.rb +0 -50
  71. data/lib/wlang/mustang.rb +0 -90
  72. data/spec/integration/test_mustang.rb +0 -120
  73. data/spec/unit/dialect/test_dispatching.rb +0 -19
  74. 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, "Something", []].each do |test|
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, nil].each do |test|
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("")
@@ -17,5 +17,9 @@ module WLang
17
17
  render('Hello #{scope}{${who}}', binding).should eq("Hello ")
18
18
  end
19
19
 
20
+ it 'allows undefined variables' do
21
+ render('Hello #{scope}{${who}}', binding).should eq("Hello ")
22
+ end
23
+
20
24
  end
21
- end
25
+ end
@@ -18,9 +18,7 @@ module WLang
18
18
  end
19
19
 
20
20
  it 'preserves spacing in the third block' do
21
- pending{
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
@@ -14,7 +14,8 @@ module WLang
14
14
  end
15
15
 
16
16
  let(:expected) do
17
- Path.dir/:examples/ex_file.basename.sub_ext(".txt")
17
+ from, to = root_folder, Path.dir
18
+ (to/(ex_file % from)).rm_ext
18
19
  end
19
20
 
20
21
  it 'is instantiated as expected with autospacing' do
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
- require 'wlang/mustang'
3
2
  module WLang
4
- describe Mustang do
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
@@ -24,7 +24,7 @@ module Helpers
24
24
  end
25
25
 
26
26
  def tpl_path(what)
27
- what = "#{what}.tpl" if what.is_a?(Symbol)
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/*.tpl").each do |f|
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 => true if RUBY_VERSION < "1.9"
62
+ c.filter_run_excluding :hash_ordering => (RUBY_VERSION < "1.9")
63
63
  end
@@ -12,7 +12,7 @@ module WLang
12
12
  tag('!$') do |buf,fn| buf << "!$" end
13
13
  tag('*') do |buf,fn1,fn2| end
14
14
  tag('%', [WLang::Dummy]) do |buf, fn| end
15
- }.factor
15
+ }.new
16
16
  }
17
17
 
18
18
  describe 'find_dispatching_method' do
@@ -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
- class Dialect
4
- describe Evaluation, "evaluate" do
5
- include Evaluation
3
+ describe Dialect, 'evaluate' do
6
4
 
7
- let(:struct){ Struct.new(:who) }
5
+ let(:struct){ Struct.new(:who) }
8
6
 
9
- it 'works with a hash' do
10
- with_scope({:who => "World"}) do
11
- evaluate("who").should eq("World")
12
- evaluate(:who).should eq("World")
13
- end
14
- end
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
- it 'works with a struct' do
17
- with_scope(struct.new("World")) do
18
- evaluate("who").should eq("World")
19
- evaluate(:who).should eq("World")
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
- it 'uses the hash in priority' do
24
- with_scope({:keys => [1,2,3]}) do
25
- evaluate("keys").should eq([1,2,3])
26
- end
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
- it 'falls back to send' do
30
- with_scope({:who => "World"}) do
31
- evaluate("keys").should eq([:who])
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
- it 'raises a NameError when not found' do
36
- lambda{ evaluate("who") }.should raise_error(NameError)
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
- class Dialect
4
- describe Evaluation, "with_scope" do
5
- include Evaluation
3
+ describe Dialect, 'with_scope' do
6
4
 
7
- let(:struct){ Struct.new(:who) }
5
+ let(:struct){ Struct.new(:who) }
8
6
 
9
- it 'returns the block value' do
10
- got = with_scope({:who => "World"}) do
11
- 12
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
- end # describe Evaluation, "with_scope"
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 Scopes' do
10
- Scope.coerce(Scope.root).should be_a(Scope::ProxyScope)
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