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
@@ -1,30 +0,0 @@
|
|
1
|
-
module WLang
|
2
|
-
class Dialect
|
3
|
-
module Evaluation
|
4
|
-
|
5
|
-
def scope
|
6
|
-
@scope ||= Scope.root
|
7
|
-
end
|
8
|
-
|
9
|
-
def with_scope(x)
|
10
|
-
@scope = scope.push(x)
|
11
|
-
res = yield
|
12
|
-
@scope = scope.pop
|
13
|
-
res
|
14
|
-
end
|
15
|
-
|
16
|
-
def evaluate(expr, *default)
|
17
|
-
case expr
|
18
|
-
when Symbol, String
|
19
|
-
catch(:fail) do
|
20
|
-
return scope.evaluate(expr, *default)
|
21
|
-
end
|
22
|
-
raise NameError, "Unable to find `#{expr}`"
|
23
|
-
else
|
24
|
-
evaluate(render(expr), *default)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end # module Evaluation
|
29
|
-
end # class Dialect
|
30
|
-
end # module WLang
|
data/lib/wlang/dialect/tags.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
module WLang
|
2
|
-
class Dialect
|
3
|
-
module Tags
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
|
7
|
-
protected
|
8
|
-
|
9
|
-
def tag(symbols, dialects = nil, method = nil, &block)
|
10
|
-
if block
|
11
|
-
tag(symbols, dialects, block)
|
12
|
-
else
|
13
|
-
dialects, method = nil, dialects if method.nil?
|
14
|
-
define_tag_method(symbols, dialects, method)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
module InstanceMethods
|
21
|
-
|
22
|
-
protected
|
23
|
-
|
24
|
-
def render(fn, scope = nil, buffer = "")
|
25
|
-
if scope.nil?
|
26
|
-
case fn
|
27
|
-
when String
|
28
|
-
buffer << fn
|
29
|
-
when Proc
|
30
|
-
fn.call(self, buffer)
|
31
|
-
when Template
|
32
|
-
fn.call(@scope, buffer)
|
33
|
-
else
|
34
|
-
raise ArgumentError, "Unable to render `#{fn}`"
|
35
|
-
end
|
36
|
-
else
|
37
|
-
with_scope(scope){ render(fn, nil, buffer) }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.included(mod)
|
44
|
-
mod.instance_eval{ include(InstanceMethods) }
|
45
|
-
mod.extend(ClassMethods)
|
46
|
-
end
|
47
|
-
|
48
|
-
end # module Tags
|
49
|
-
end # class Dialect
|
50
|
-
end # module WLang
|
data/lib/wlang/mustang.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
require 'wlang'
|
2
|
-
require 'wlang/dummy'
|
3
|
-
module WLang
|
4
|
-
#
|
5
|
-
# A WLang dialect mimicing the excellent Mustache.
|
6
|
-
#
|
7
|
-
# This dialect installs the following high-order functions:
|
8
|
-
#
|
9
|
-
# * `${...}` mimics mustache's `{{ ... }}` that is, it evaluates the variable and
|
10
|
-
# returns the HTML-escaped string
|
11
|
-
# * `+{...}` mimics mustache's `{{{ ... }}}` that is, it evaluates the variable and
|
12
|
-
# returns its string representation (through `to_s`)
|
13
|
-
# * `#{..1..}{..2..}` mimics mustache's `{{#..1..}}..2..{{/..1..}}`. For false and nil,
|
14
|
-
# it returns nil. For scopes and ranges, it instantiates the second block in the scope
|
15
|
-
# of each element in turn and returns the concatenation of instantiation results. For
|
16
|
-
# a Proc, it calls it, passing a rendering continuation as first argument. Every other
|
17
|
-
# object is used as a new scope in which the second block is instantiated.
|
18
|
-
# * `^{..1..}{..2..}` mimics mustache's `{{^..1..}}..2..{{/..1..}}`, instantiating the
|
19
|
-
# second only if the evaluation of the first yields false, nil, an empty list or an
|
20
|
-
# unbound variable.
|
21
|
-
# * `>{...}` mimics mustache's `{{>...}}`, instantiating the partial denoted by the
|
22
|
-
# evaluated expression.
|
23
|
-
# * `!{...}` mimics mustache's `{{!...}}`, taking the block content as a comment
|
24
|
-
# therefore skipping it.
|
25
|
-
#
|
26
|
-
class Mustang < WLang::Dialect
|
27
|
-
|
28
|
-
module HighOrderFunctions
|
29
|
-
|
30
|
-
def plus(buf, fn)
|
31
|
-
if x = evaluate(fn)
|
32
|
-
buf << x.to_s
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def escape(buf, fn)
|
37
|
-
buf << Temple::Utils.escape_html(evaluate(fn))
|
38
|
-
end
|
39
|
-
|
40
|
-
def section(buf, fn1, fn2)
|
41
|
-
case x = evaluate(fn1)
|
42
|
-
when FalseClass, NilClass
|
43
|
-
nil
|
44
|
-
when Array, Range
|
45
|
-
x.each{|item|
|
46
|
-
render(fn2, item, buf)
|
47
|
-
}
|
48
|
-
when Proc
|
49
|
-
buf << x.call(lambda{ render(fn2) })
|
50
|
-
else
|
51
|
-
render(fn2, x, buf)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def inverted(buf, fn1, fn2)
|
56
|
-
case x = evaluate(fn1)
|
57
|
-
when FalseClass, NilClass
|
58
|
-
render(fn2, scope, buf)
|
59
|
-
when Array
|
60
|
-
render(fn2, scope, buf) if x.empty?
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def comment(buf, fn)
|
65
|
-
end
|
66
|
-
|
67
|
-
def partial(buf, fn)
|
68
|
-
if x = Mustang.compile(evaluate(fn))
|
69
|
-
render(x, scope, buf)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
include HighOrderFunctions
|
75
|
-
|
76
|
-
def evaluate(expr)
|
77
|
-
super
|
78
|
-
rescue
|
79
|
-
nil
|
80
|
-
end
|
81
|
-
|
82
|
-
tag '+', :plus
|
83
|
-
tag '$', :escape
|
84
|
-
tag '#', :section
|
85
|
-
tag '^', :inverted
|
86
|
-
tag '>', :partial
|
87
|
-
tag '!', [WLang::Dummy], :comment
|
88
|
-
|
89
|
-
end # class Mustang
|
90
|
-
end # module WLang
|
@@ -1,120 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'wlang/mustang'
|
3
|
-
module WLang
|
4
|
-
describe Mustang do
|
5
|
-
|
6
|
-
def m(tpl, scope = {}, buffer = "")
|
7
|
-
Mustang.render(tpl, scope, buffer)
|
8
|
-
end
|
9
|
-
|
10
|
-
context '+{...} mimicing {{{ ... }}}' do
|
11
|
-
it "renders nothing on nil" do
|
12
|
-
m('Hello +{who}', :who => nil).should eq("Hello ")
|
13
|
-
end
|
14
|
-
it "renders nothing on unknown" do
|
15
|
-
m('Hello +{who}', {}).should eq("Hello ")
|
16
|
-
end
|
17
|
-
it "renders the variable if known" do
|
18
|
-
m('Hello +{who}', :who => "World").should eq("Hello World")
|
19
|
-
end
|
20
|
-
it "calls to_s on such variable" do
|
21
|
-
m('Hello +{who}', :who => 12).should eq("Hello 12")
|
22
|
-
end
|
23
|
-
it "does not escape html" do
|
24
|
-
m('Hello +{who}', :who => "<script>").should eq("Hello <script>")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "${...} mimicing {{ ... }}" do
|
29
|
-
it "renders nothing on nil" do
|
30
|
-
m('Hello ${who}', :who => nil).should eq("Hello ")
|
31
|
-
end
|
32
|
-
it "renders nothing on unknown" do
|
33
|
-
m('Hello ${who}', {}).should eq("Hello ")
|
34
|
-
end
|
35
|
-
it "renders the variable if known" do
|
36
|
-
m('Hello ${who}', :who => "World").should eq("Hello World")
|
37
|
-
end
|
38
|
-
it "calls to_s on such variable" do
|
39
|
-
m('Hello ${who}', :who => 12).should eq("Hello 12")
|
40
|
-
end
|
41
|
-
it "does escape html" do
|
42
|
-
m('Hello ${who}', :who => "<script>").should eq("Hello <script>")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context '#{..1..}{..2..} mimicing {{#..1..}}..2..{{/..1..}} ' do
|
47
|
-
it 'skips the section on false' do
|
48
|
-
m('Hello #{present}{World}', :present => false).should eq("Hello ")
|
49
|
-
end
|
50
|
-
it 'skips the section on nil' do
|
51
|
-
m('Hello #{present}{World}', :present => nil).should eq("Hello ")
|
52
|
-
end
|
53
|
-
it 'skips the section on missing' do
|
54
|
-
m('Hello #{present}{World}').should eq("Hello ")
|
55
|
-
end
|
56
|
-
it 'skips the section on empty lists' do
|
57
|
-
m('Hello #{present}{World}', :present => []).should eq("Hello ")
|
58
|
-
end
|
59
|
-
it 'iterates on non-empty lists' do
|
60
|
-
repo = [{:name => "resque"},{:name => "hub"},{:name => "rip"}]
|
61
|
-
m('Hello #{repo}{<b>${name}</b>}', :repo => repo).should eq("Hello <b>resque</b><b>hub</b><b>rip</b>")
|
62
|
-
end
|
63
|
-
it 'iterates on ranges' do
|
64
|
-
m('Hello #{range}{.}', :range => 1..10).should eq("Hello ..........")
|
65
|
-
end
|
66
|
-
it 'passes the block to a lambda' do
|
67
|
-
wrapped = lambda{|fn| "<b>#{fn.call}</b>"}
|
68
|
-
scope = {:wrapped => wrapped, :name => "World"}
|
69
|
-
m('#{wrapped}{Hello ${name}}', scope).should eq("<b>Hello World</b>")
|
70
|
-
end
|
71
|
-
it 'use a Hash a a new scope' do
|
72
|
-
m('Hello #{person}{${name}}', :person => {:name => "World"}).should eq("Hello World")
|
73
|
-
end
|
74
|
-
it 'use a Struct a a new scope' do
|
75
|
-
person = Struct.new(:name).new("World")
|
76
|
-
m('Hello #{person}{${name}}', :person => person).should eq("Hello World")
|
77
|
-
end
|
78
|
-
it 'outputs frequently when iterating' do
|
79
|
-
m('#{range}{.}', {:range => 1..10}, []).should eq(Array.new(10, '.'))
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
context "^{..1..}{..2..} mimicing {{^..1..}}..2..{{/..1..}}" do
|
84
|
-
it 'renders the section on false' do
|
85
|
-
m('Hello ^{missing}{World}', :missing => false).should eq("Hello World")
|
86
|
-
end
|
87
|
-
it 'renders the section on nil' do
|
88
|
-
m('Hello ^{missing}{World}', :missing => nil).should eq("Hello World")
|
89
|
-
end
|
90
|
-
it 'renders the section on missing' do
|
91
|
-
m('Hello ^{missing}{World}').should eq("Hello World")
|
92
|
-
end
|
93
|
-
it 'renders the section on empty lists' do
|
94
|
-
m('Hello ^{missing}{World}', :missing => []).should eq("Hello World")
|
95
|
-
end
|
96
|
-
it 'does not iterate lists' do
|
97
|
-
repo = [{:name => "resque"},{:name => "hub"},{:name => "rip"}]
|
98
|
-
m('Hello ^{repo}{<b>${name}</b>}', :repo => repo).should eq("Hello ")
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context "!{...} mimicing {{!...}}" do
|
103
|
-
it 'skips the section altogether' do
|
104
|
-
m('Hello !{this is a comment} world').should eq("Hello world")
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context '>{...} mimicing {{>...}}' do
|
109
|
-
it 'renders the partial' do
|
110
|
-
scope = {:who => "<b>${name}</b>", :name => "World"}
|
111
|
-
m("Hello >{who}", scope).should eq("Hello <b>World</b>")
|
112
|
-
end
|
113
|
-
it 'supports a pre-compiled partial' do
|
114
|
-
scope = {:who => Mustang.compile("<b>${name}</b>"), :name => "World"}
|
115
|
-
m("Hello >{who}", scope).should eq("Hello <b>World</b>")
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
end # describe Mustang
|
120
|
-
end # module WLang
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module WLang
|
3
|
-
describe Dialect::Dispatching do
|
4
|
-
include Dialect::Dispatching::ClassMethods
|
5
|
-
|
6
|
-
describe 'tag_dispatching_name' do
|
7
|
-
it "works with a single char" do
|
8
|
-
tag_dispatching_name("$").should eq(:_tag_36)
|
9
|
-
end
|
10
|
-
it "works with a multiple chars" do
|
11
|
-
tag_dispatching_name("!$").should eq(:_tag_33_36)
|
12
|
-
end
|
13
|
-
it "works with an array" do
|
14
|
-
tag_dispatching_name(['!', '$']).should eq(:_tag_33_36)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end # describe Dialect
|
19
|
-
end # module WLang
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
module WLang
|
3
|
-
describe Dialect::Tags do
|
4
|
-
|
5
|
-
describe 'tag' do
|
6
|
-
include Dialect::Tags::ClassMethods
|
7
|
-
|
8
|
-
def define_tag_method(*args)
|
9
|
-
args
|
10
|
-
end
|
11
|
-
|
12
|
-
it "works with a symbol" do
|
13
|
-
tag("$", :dollar).should eq(["$", nil, :dollar])
|
14
|
-
end
|
15
|
-
|
16
|
-
it "works with a single proc" do
|
17
|
-
proc = lambda{|buf,fn| }
|
18
|
-
tag("$", &proc).should eq(["$", nil, proc])
|
19
|
-
end
|
20
|
-
|
21
|
-
it "allows specifying dialects with a symbol" do
|
22
|
-
tag("$", [Foo], :dollar).should eq(["$", [Foo], :dollar])
|
23
|
-
end
|
24
|
-
|
25
|
-
it "allows specifying dialects with a proc" do
|
26
|
-
proc = lambda{|buf,fn| }
|
27
|
-
tag("$", [Foo], &proc).should eq(["$", [Foo], proc])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end # describe Dialect
|
32
|
-
end # module WLang
|