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
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
class Scope
|
4
|
+
describe ProcScope do
|
5
|
+
|
6
|
+
it 'implements fetch through call.xxx' do
|
7
|
+
scope = Scope.coerce(lambda{ {:who => "World"} })
|
8
|
+
scope.fetch(:who).should eq("World")
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'delegates fetch to its parent when not found' do
|
12
|
+
scope = Scope.coerce(lambda{ nil }, Scope.coerce({:who => "World"}))
|
13
|
+
scope.fetch(:who).should eq("World")
|
14
|
+
end
|
15
|
+
|
16
|
+
end # describe ProcScope
|
17
|
+
end # class Scope
|
18
|
+
end # module WLang
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
class Source
|
4
|
+
describe FrontMatter, "locals" do
|
5
|
+
|
6
|
+
let(:template){ nil }
|
7
|
+
|
8
|
+
subject{ FrontMatter.new(source, template).locals }
|
9
|
+
|
10
|
+
context 'without front matter' do
|
11
|
+
let(:source){ "Hello world!" }
|
12
|
+
it{ should eq({}) }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'with a front matter' do
|
16
|
+
let(:source){ "---\nlocals:\n x: 2\n---\nHello world!" }
|
17
|
+
specify 'it decode the YAML data' do
|
18
|
+
subject.should eq({"x" => 2})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'with a front matter containing partials' do
|
23
|
+
let(:template){
|
24
|
+
tpl_class = Struct.new(:compiler)
|
25
|
+
tpl_class.new(Object.new.extend(Module.new{
|
26
|
+
def to_ruby_proc(tpl)
|
27
|
+
tpl.upcase
|
28
|
+
end
|
29
|
+
}))
|
30
|
+
}
|
31
|
+
let(:source){ "---\npartials:\n x: abc\n---\nHello world!" }
|
32
|
+
specify 'it should have correct locals' do
|
33
|
+
subject.should eq({"x" => 'ABC'})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
class Source
|
4
|
+
describe FrontMatter, "template_content" do
|
5
|
+
|
6
|
+
subject{ FrontMatter.new(source).template_content }
|
7
|
+
|
8
|
+
context 'without front matter' do
|
9
|
+
let(:source){ "Hello world!" }
|
10
|
+
it{ should eq(source) }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'with a front matter' do
|
14
|
+
let(:source){ "---\nlocals:\n x: 2\n---\nHello world!" }
|
15
|
+
specify 'it should not return the front matter itself' do
|
16
|
+
subject.should eq("Hello world!")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Source, "path" do
|
4
|
+
|
5
|
+
subject{ Source.new(source).path }
|
6
|
+
|
7
|
+
context 'on a pure string' do
|
8
|
+
let(:source){ "Hello world!" }
|
9
|
+
it{ should be_nil }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'on a Path' do
|
13
|
+
let(:source){ Path.here }
|
14
|
+
it{ should eq(source.to_s) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'on a File' do
|
18
|
+
let(:source){ File.open(Path.here.to_s) }
|
19
|
+
it{ should eq(__FILE__) }
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'is aliased as to_path' do
|
23
|
+
Source.new(Path.here).to_path.should eq(__FILE__)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Source, "template_content" do
|
4
|
+
|
5
|
+
subject{ Source.new(source).template_content }
|
6
|
+
|
7
|
+
context 'on a pure string' do
|
8
|
+
let(:source){ "Hello world!" }
|
9
|
+
it{ should eq(source) }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'on a Path' do
|
13
|
+
let(:source){ hello_path }
|
14
|
+
it{ should eq(hello_path.read) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'on a File' do
|
18
|
+
let(:source){ File.open(Path.here.to_s) }
|
19
|
+
it{ should eq(File.read(__FILE__)) }
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'also works on an IO' do
|
23
|
+
hello_io do |io|
|
24
|
+
Source.new(io).template_content.should eq(hello_path.read)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'is aliased as to_s' do
|
29
|
+
Source.new("raw text").to_s.should eq("raw text")
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'is aliased as to_str' do
|
33
|
+
Source.new("raw text").to_str.should eq("raw text")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Source, "template_content" do
|
4
|
+
|
5
|
+
let(:source){ Source.new("Hello world") }
|
6
|
+
subject{ source.with_front_matter(enabled) }
|
7
|
+
|
8
|
+
context 'when enabled' do
|
9
|
+
let(:enabled){ true }
|
10
|
+
it { should be_a(Source::FrontMatter) }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when disabled' do
|
14
|
+
let(:enabled){ false }
|
15
|
+
it { should eq(source) }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, 'call' do
|
4
|
+
|
5
|
+
let(:template){ Template.new("Hello ${who}!") }
|
6
|
+
|
7
|
+
it 'renders the template to a string by default' do
|
8
|
+
template.render(:who => "world").should eq("Hello world!")
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'allows specifying a buffer' do
|
12
|
+
template.render({:who => "world"}, "Hey, ").should eq("Hey, Hello world!")
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, '.new' do
|
4
|
+
|
5
|
+
it 'returns a Template instance' do
|
6
|
+
Template.new("Hello ${who}!").should be_a(Template)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'allows specifying the dialect to use' do
|
10
|
+
t = Template.new("Hello ${who}!", :dialect => Upcasing)
|
11
|
+
t.dialect.should eq(Upcasing)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'uses WLang::Html as default dialect' do
|
15
|
+
t = Template.new("Hello ${who}!")
|
16
|
+
t.dialect.should eq(Html)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, 'path' do
|
4
|
+
|
5
|
+
subject{ template.path }
|
6
|
+
|
7
|
+
context 'when a string and no option' do
|
8
|
+
let(:template){ Template.new("Hello ${who}!") }
|
9
|
+
it{ should be_nil }
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when a Path and no option' do
|
13
|
+
let(:template){ Template.new(Path.here) }
|
14
|
+
it{ should eq(__FILE__) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when a string and an option' do
|
18
|
+
let(:template){ Template.new("Hello ${who}!", :path => __FILE__) }
|
19
|
+
it{ should eq(__FILE__) }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when a path an an option' do
|
23
|
+
let(:template){ Template.new(Path.here, :path => __FILE__) }
|
24
|
+
it{ should eq(__FILE__) }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, 'render' do
|
4
|
+
|
5
|
+
def template
|
6
|
+
Template.new(source, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:options){ {} }
|
10
|
+
|
11
|
+
subject{ template.render }
|
12
|
+
|
13
|
+
context 'with a single source String and no options' do
|
14
|
+
let(:source){ "Hello world!" }
|
15
|
+
it{ should eq("Hello world!") }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with a yaml front matter and default options' do
|
19
|
+
let(:source){ hello_with_data_path }
|
20
|
+
it{ should eq("Hello world!") }
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with a yaml front matter and front matter disabled' do
|
24
|
+
let(:source){ hello_with_data_path }
|
25
|
+
let(:options){ {:yaml_front_matter => false} }
|
26
|
+
it 'should fail' do
|
27
|
+
lambda{
|
28
|
+
subject
|
29
|
+
}.should raise_error(NameError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with explicit locals' do
|
34
|
+
let(:source){ hello_with_explicit_locals_path }
|
35
|
+
it{ should eq("Hello world and wlang!") }
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with partials' do
|
39
|
+
let(:source){ hello_with_partials_path }
|
40
|
+
it{ should eq("Hello world and wlang!") }
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, 'to_ruby_code' do
|
4
|
+
|
5
|
+
let(:template){ Template.new("Hello ${who}!") }
|
6
|
+
|
7
|
+
it 'it returns some ruby code' do
|
8
|
+
expected = %q{Proc.new{|d1,b1| b1 << ("Hello "); d1._tag_36(b1, "who"); b1 << ("!") }}
|
9
|
+
template.to_ruby_code.should eq(expected)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module WLang
|
3
|
+
describe Template, 'yaml_front_matter?' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
class Template; public :yaml_front_matter?; end
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'is true by default' do
|
10
|
+
Template.new("Hello ${who}!").should be_yaml_front_matter
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'is can be explicitely enabled' do
|
14
|
+
Template.new("Hello ${who}!", :yaml_front_matter => true).should be_yaml_front_matter
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'is can be explicitely disabled' do
|
18
|
+
Template.new("Hello ${who}!", :yaml_front_matter => false).should_not be_yaml_front_matter
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'wlang/tilt'
|
3
|
+
describe Tilt::WLangTemplate do
|
4
|
+
|
5
|
+
it 'is registered for .wlang files' do
|
6
|
+
Tilt.mappings['wlang'].should include(Tilt::WLangTemplate)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'supports basic rendering with no scope no locals' do
|
10
|
+
template = Tilt::WLangTemplate.new{ "Hello" }
|
11
|
+
template.render.should eq("Hello")
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'supports a binding scope' do
|
15
|
+
template = Tilt::WLangTemplate.new{ "Hello ${who}" }
|
16
|
+
who = "world"
|
17
|
+
template.render(binding).should eq("Hello world")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'supports a Hash scope' do
|
21
|
+
template = Tilt::WLangTemplate.new{ "Hello ${who}" }
|
22
|
+
scope = {:who => "world"}
|
23
|
+
template.render(scope).should eq("Hello world")
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'supports both a scope and locals' do
|
27
|
+
template = Tilt::WLangTemplate.new{ "Hello ${who} and ${who_else}" }
|
28
|
+
who = "world"
|
29
|
+
template.render(binding, :who_else => 'wlang').should eq("Hello world and wlang")
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'supports being rendered multiple times' do
|
33
|
+
template = Tilt::WLangTemplate.new{ "Hello ${i}" }
|
34
|
+
3.times{|i| template.render(binding).should eq("Hello #{i}") }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'supports passing a block for yielding' do
|
38
|
+
template = Tilt::WLangTemplate.new{ "Hello ${yield}" }
|
39
|
+
template.render{ "world" }.should eq('Hello world')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'supports expressions on yield' do
|
43
|
+
template = Tilt::WLangTemplate.new{ "Hello ${yield.upcase}" }
|
44
|
+
template.render{ "world" }.should eq('Hello WORLD')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'passes :path option to the underlying template' do
|
48
|
+
tpl = Tilt::WLangTemplate.new(hello_path.to_s)
|
49
|
+
tpl = tpl.send(:prepare)
|
50
|
+
tpl.should be_a(WLang::Template)
|
51
|
+
tpl.path.should eq(hello_path.to_s)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'supports passing a dialect as options' do
|
55
|
+
template = Tilt::WLangTemplate.new(:dialect => Upcasing){ "Hello ${who}" }
|
56
|
+
template.render.should eq("Hello WHO")
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'supports options through inheritance' do
|
60
|
+
tpl_class = Tilt::WLangTemplate.with_options(:dialect => Upcasing)
|
61
|
+
template = tpl_class.new{ "Hello ${who}" }
|
62
|
+
template.render.should eq("Hello WHO")
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/wlang.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
#
|
28
28
|
# The description should be more detailed than the summary. For example,
|
29
29
|
# you might wish to copy the entire README into the description.
|
30
|
-
s.description = "WLang is a general-purpose *code generation*/*templating engine*. It's main aim is to
|
30
|
+
s.description = "WLang is a general-purpose *code generation*/*templating engine*. It's main aim is to\nhelp you generating web pages, sql queries, ruby code (that is, generating text in\ngeneral) without having to worry too much about html entities encoding, sql back\nquoting, string escaping and the like. WLang proposes a generic engine that you can\neasily extend to fit your needs. It also proposes standard instantiations of this\nengine for common tasks such as rendering HTML web pages."
|
31
31
|
|
32
32
|
# The URL of this gem home page (optional)
|
33
33
|
s.homepage = "http://github.com/blambeau/wlang"
|
@@ -123,19 +123,17 @@ Gem::Specification.new do |s|
|
|
123
123
|
# One call to add_development_dependency('gem_name', 'gem version requirement')
|
124
124
|
# for each development dependency. These gems are required for developers
|
125
125
|
#
|
126
|
-
s.add_development_dependency("
|
127
|
-
s.add_development_dependency("mustache", "~> 0.99.4")
|
126
|
+
s.add_development_dependency("tilt", "~> 1.3")
|
128
127
|
s.add_development_dependency("rake", "~> 0.9.2")
|
129
128
|
s.add_development_dependency("bundler", "~> 1.0")
|
130
129
|
s.add_development_dependency("rspec", "~> 2.10.0")
|
131
|
-
s.add_development_dependency("epath", "~> 0.1.0")
|
132
130
|
s.add_development_dependency("yard", "~> 0.8.1")
|
133
131
|
s.add_development_dependency("bluecloth", "~> 2.2.0")
|
134
132
|
s.add_dependency("citrus", "~> 2.4.1")
|
135
133
|
s.add_dependency("temple", "~> 0.4.0")
|
136
|
-
s.add_dependency("backports", "~> 2.6.1")
|
137
134
|
s.add_dependency("quickl", "~> 0.4.3")
|
138
135
|
s.add_dependency("awesome_print", "~> 1.0.2")
|
136
|
+
s.add_dependency("epath", ">= 0.2")
|
139
137
|
|
140
138
|
# The version of ruby required by this gem
|
141
139
|
#
|