wlang 0.10.2 → 2.0.0.beta
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/CHANGELOG.md +3 -121
- data/Gemfile +23 -1
- data/Gemfile.lock +32 -28
- data/LICENCE.md +18 -21
- data/Manifest.txt +4 -5
- data/README.md +100 -174
- data/Rakefile +1 -13
- data/bin/wlang +3 -29
- data/lib/wlang.rb +21 -394
- data/lib/wlang/command.rb +94 -0
- data/lib/wlang/compiler.rb +78 -0
- data/lib/wlang/compiler/autospacing.rb +60 -0
- data/lib/wlang/compiler/dialect_enforcer.rb +91 -0
- data/lib/wlang/compiler/filter.rb +32 -0
- data/lib/wlang/compiler/grammar.citrus +67 -0
- data/lib/wlang/compiler/parser.rb +26 -0
- data/lib/wlang/compiler/proc_call_removal.rb +15 -0
- data/lib/wlang/compiler/static_merger.rb +28 -0
- data/lib/wlang/compiler/strconcat_flattener.rb +25 -0
- data/lib/wlang/compiler/to_ruby_abstraction.rb +22 -0
- data/lib/wlang/compiler/to_ruby_code.rb +55 -0
- data/lib/wlang/dialect.rb +40 -237
- data/lib/wlang/dialect/dispatching.rb +51 -0
- data/lib/wlang/dialect/evaluation.rb +30 -0
- data/lib/wlang/dialect/tags.rb +50 -0
- data/lib/wlang/dummy.rb +32 -0
- data/lib/wlang/html.rb +106 -0
- data/lib/wlang/loader.rb +6 -0
- data/lib/wlang/mustang.rb +90 -0
- data/lib/wlang/scope.rb +57 -0
- data/lib/wlang/scope/binding_scope.rb +18 -0
- data/lib/wlang/scope/object_scope.rb +25 -0
- data/lib/wlang/scope/proxy_scope.rb +18 -0
- data/lib/wlang/scope/root_scope.rb +24 -0
- data/lib/wlang/template.rb +16 -86
- data/lib/wlang/version.rb +9 -8
- data/spec/fixtures/dialect/foobar.rb +31 -0
- data/spec/fixtures/dialect/upcasing.rb +13 -0
- data/spec/fixtures/templates/hello.tpl +1 -0
- data/spec/integration/examples/1-basics.txt +65 -0
- data/spec/integration/examples/2-imperative.txt +51 -0
- data/spec/integration/examples/3-partials.txt +76 -0
- data/spec/integration/examples/4-recursion.txt +16 -0
- data/spec/integration/html/test_ampersand.rb +15 -0
- data/spec/integration/html/test_bang.rb +38 -0
- data/spec/integration/html/test_caret.rb +33 -0
- data/spec/integration/html/test_dollar.rb +16 -0
- data/spec/integration/html/test_greater.rb +23 -0
- data/spec/integration/html/test_modulo.rb +16 -0
- data/spec/integration/html/test_plus.rb +48 -0
- data/spec/integration/html/test_question.rb +33 -0
- data/spec/integration/html/test_sharp.rb +21 -0
- data/spec/integration/html/test_slash.rb +16 -0
- data/spec/integration/html/test_star.rb +37 -0
- data/spec/integration/test_dummy.rb +51 -0
- data/spec/integration/test_examples.rb +29 -0
- data/spec/integration/test_mustang.rb +120 -0
- data/spec/integration/test_readme.rb +56 -0
- data/spec/integration/test_upcasing.rb +22 -0
- data/spec/spec_helper.rb +62 -1
- data/spec/test_wlang.rb +101 -0
- data/spec/unit/compiler/autospacing/test_right_strip.rb +30 -0
- data/spec/unit/compiler/autospacing/test_unindent.rb +30 -0
- data/spec/unit/compiler/test_dialect_enforcer.rb +168 -0
- data/spec/unit/compiler/test_grammar.rb +207 -0
- data/spec/unit/compiler/test_parser.rb +69 -0
- data/spec/unit/compiler/test_proc_call_removal.rb +24 -0
- data/spec/unit/compiler/test_static_merger.rb +29 -0
- data/spec/unit/compiler/test_strconcat_flattener.rb +30 -0
- data/spec/unit/compiler/test_to_ruby_abstraction.rb +59 -0
- data/spec/unit/compiler/test_to_ruby_code.rb +24 -0
- data/spec/unit/dialect/test_compile.rb +52 -0
- data/spec/unit/dialect/test_dispatching.rb +19 -0
- data/spec/unit/dialect/test_evaluate.rb +41 -0
- data/spec/unit/dialect/test_render.rb +33 -0
- data/spec/unit/dialect/test_tags.rb +32 -0
- data/spec/unit/dialect/test_with_scope.rb +18 -0
- data/spec/unit/scope/test_binding_scope.rb +27 -0
- data/spec/unit/scope/test_coerce.rb +22 -0
- data/spec/unit/scope/test_object_scope.rb +38 -0
- data/spec/unit/scope/test_proxy_scope.rb +22 -0
- data/spec/unit/scope/test_root_scope.rb +22 -0
- data/spec/unit/test_assumptions.rb +29 -0
- data/spec/unit/test_scope.rb +57 -0
- data/tasks/debug_mail.rake +42 -45
- data/tasks/gem.rake +22 -17
- data/tasks/spec_test.rake +9 -17
- data/tasks/unit_test.rake +11 -12
- data/tasks/yard.rake +13 -13
- data/wlang.gemspec +36 -32
- data/wlang.noespec +27 -35
- metadata +268 -451
- data/doc/specification/about.rdoc +0 -61
- data/doc/specification/analytics.wtpl +0 -13
- data/doc/specification/dialect.wtpl +0 -14
- data/doc/specification/dialects.wtpl +0 -3
- data/doc/specification/examples.rb +0 -3
- data/doc/specification/glossary.wtpl +0 -14
- data/doc/specification/hosting.rdoc +0 -0
- data/doc/specification/overview.rdoc +0 -116
- data/doc/specification/rulesets.wtpl +0 -87
- data/doc/specification/specification.css +0 -53
- data/doc/specification/specification.html +0 -1690
- data/doc/specification/specification.js +0 -8
- data/doc/specification/specification.wtpl +0 -42
- data/doc/specification/specification.yml +0 -432
- data/doc/specification/symbols.wtpl +0 -16
- data/lib/wlang/dialect_dsl.rb +0 -141
- data/lib/wlang/dialect_loader.rb +0 -74
- data/lib/wlang/dialects/bluecloth_dialect.rb +0 -16
- data/lib/wlang/dialects/coderay_dialect.rb +0 -45
- data/lib/wlang/dialects/hosted_dialect.rb +0 -50
- data/lib/wlang/dialects/plain_text_dialect.rb +0 -69
- data/lib/wlang/dialects/rdoc_dialect.rb +0 -33
- data/lib/wlang/dialects/redcloth_dialect.rb +0 -16
- data/lib/wlang/dialects/ruby_dialect.rb +0 -118
- data/lib/wlang/dialects/sql_dialect.rb +0 -38
- data/lib/wlang/dialects/standard_dialects.rb +0 -181
- data/lib/wlang/dialects/xhtml_dialect.rb +0 -63
- data/lib/wlang/dialects/yaml_dialect.rb +0 -30
- data/lib/wlang/encoder.rb +0 -62
- data/lib/wlang/encoder_set.rb +0 -122
- data/lib/wlang/errors.rb +0 -80
- data/lib/wlang/ext/hash_methodize.rb +0 -13
- data/lib/wlang/ext/string.rb +0 -44
- data/lib/wlang/hash_scope.rb +0 -89
- data/lib/wlang/hosted_language.rb +0 -146
- data/lib/wlang/intelligent_buffer.rb +0 -94
- data/lib/wlang/parser.rb +0 -332
- data/lib/wlang/parser_state.rb +0 -94
- data/lib/wlang/rule.rb +0 -66
- data/lib/wlang/rule_set.rb +0 -106
- data/lib/wlang/rulesets/basic_ruleset.rb +0 -83
- data/lib/wlang/rulesets/buffering_ruleset.rb +0 -115
- data/lib/wlang/rulesets/context_ruleset.rb +0 -111
- data/lib/wlang/rulesets/encoding_ruleset.rb +0 -73
- data/lib/wlang/rulesets/imperative_ruleset.rb +0 -132
- data/lib/wlang/rulesets/ruleset_utils.rb +0 -317
- data/lib/wlang/wlang_command.rb +0 -51
- data/lib/wlang/wlang_command_options.rb +0 -163
- data/spec/basic_object.spec +0 -40
- data/spec/coderay_dialect.spec +0 -8
- data/spec/dialect/apply_post_transform.spec +0 -16
- data/spec/global_extensions.rb +0 -2
- data/spec/hash_scope.spec +0 -76
- data/spec/redcloth_dialect.spec +0 -24
- data/spec/test_all.rb +0 -8
- data/spec/wlang.spec +0 -53
- data/spec/wlang_spec.rb +0 -8
- data/spec/xhtml_dialect.spec +0 -22
- data/tasks/genspec.rake +0 -5
- data/test/blackbox/basic/execution_1.exp +0 -1
- data/test/blackbox/basic/execution_1.tpl +0 -1
- data/test/blackbox/basic/execution_2.exp +0 -1
- data/test/blackbox/basic/execution_2.tpl +0 -1
- data/test/blackbox/basic/execution_3.exp +0 -1
- data/test/blackbox/basic/execution_3.tpl +0 -1
- data/test/blackbox/basic/execution_4.exp +0 -1
- data/test/blackbox/basic/execution_4.tpl +0 -1
- data/test/blackbox/basic/inclusion_1.exp +0 -1
- data/test/blackbox/basic/inclusion_1.tpl +0 -1
- data/test/blackbox/basic/inclusion_2.exp +0 -1
- data/test/blackbox/basic/inclusion_2.tpl +0 -1
- data/test/blackbox/basic/injection_1.exp +0 -1
- data/test/blackbox/basic/injection_1.tpl +0 -1
- data/test/blackbox/basic/injection_2.exp +0 -1
- data/test/blackbox/basic/injection_2.tpl +0 -1
- data/test/blackbox/basic/modulation_1.exp +0 -1
- data/test/blackbox/basic/modulation_1.tpl +0 -1
- data/test/blackbox/basic/modulation_2.exp +0 -1
- data/test/blackbox/basic/modulation_2.tpl +0 -1
- data/test/blackbox/basic/recursive_app_1.exp +0 -1
- data/test/blackbox/basic/recursive_app_1.tpl +0 -1
- data/test/blackbox/basic/recursive_app_2.exp +0 -1
- data/test/blackbox/basic/recursive_app_2.tpl +0 -1
- data/test/blackbox/buffering/data_1.rb +0 -1
- data/test/blackbox/buffering/data_assignment_1.exp +0 -1
- data/test/blackbox/buffering/data_assignment_1.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_2.exp +0 -1
- data/test/blackbox/buffering/data_assignment_2.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_3.exp +0 -1
- data/test/blackbox/buffering/data_assignment_3.tpl +0 -1
- data/test/blackbox/buffering/data_assignment_4.exp +0 -1
- data/test/blackbox/buffering/data_assignment_4.tpl +0 -1
- data/test/blackbox/buffering/input_1.exp +0 -1
- data/test/blackbox/buffering/input_1.tpl +0 -1
- data/test/blackbox/buffering/input_2.exp +0 -1
- data/test/blackbox/buffering/input_2.tpl +0 -1
- data/test/blackbox/buffering/input_3.exp +0 -1
- data/test/blackbox/buffering/input_3.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion.exp +0 -1
- data/test/blackbox/buffering/input_inclusion.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_1.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_1.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_2.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_2.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_3.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_3.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_4.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_4.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_5.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_5.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_6.exp +0 -1
- data/test/blackbox/buffering/input_inclusion_6.tpl +0 -1
- data/test/blackbox/buffering/input_inclusion_7.exp +0 -0
- data/test/blackbox/buffering/input_inclusion_7.tpl +0 -1
- data/test/blackbox/buffering/text_1.txt +0 -1
- data/test/blackbox/buffering/wlang.txt +0 -1
- data/test/blackbox/context/assignment_1.exp +0 -1
- data/test/blackbox/context/assignment_1.tpl +0 -1
- data/test/blackbox/context/assignment_2.exp +0 -1
- data/test/blackbox/context/assignment_2.tpl +0 -1
- data/test/blackbox/context/assignment_3.exp +0 -2
- data/test/blackbox/context/assignment_3.tpl +0 -2
- data/test/blackbox/context/assignment_4.exp +0 -1
- data/test/blackbox/context/assignment_4.tpl +0 -1
- data/test/blackbox/context/block_assignment_1.exp +0 -1
- data/test/blackbox/context/block_assignment_1.tpl +0 -1
- data/test/blackbox/context/block_assignment_2.exp +0 -1
- data/test/blackbox/context/block_assignment_2.tpl +0 -1
- data/test/blackbox/context/modulo_assignment_1.exp +0 -1
- data/test/blackbox/context/modulo_assignment_1.tpl +0 -1
- data/test/blackbox/context/modulo_assignment_2.exp +0 -1
- data/test/blackbox/context/modulo_assignment_2.tpl +0 -1
- data/test/blackbox/data_1.rb +0 -1
- data/test/blackbox/postblock/hello.exp +0 -1
- data/test/blackbox/postblock/hello.pre +0 -1
- data/test/blackbox/postblock/hello.tpl +0 -1
- data/test/blackbox/postblock/hello_input_inclusion.exp +0 -1
- data/test/blackbox/postblock/hello_input_inclusion.tpl +0 -1
- data/test/blackbox/postblock/hello_to_authors.exp +0 -1
- data/test/blackbox/postblock/hello_to_authors.tpl +0 -1
- data/test/blackbox/poststring/hello.exp +0 -1
- data/test/blackbox/poststring/hello.tpl +0 -1
- data/test/blackbox/test_all.rb +0 -70
- data/test/standard_dialects/ruby/data.rb +0 -7
- data/test/standard_dialects/ruby/inclusion.exp +0 -6
- data/test/standard_dialects/ruby/inclusion.tpl +0 -6
- data/test/standard_dialects/test_all.rb +0 -29
- data/test/standard_dialects/yaml/assumptions_test.rb +0 -13
- data/test/standard_dialects/yaml/data.rb +0 -3
- data/test/standard_dialects/yaml/inclusion_1.exp +0 -7
- data/test/standard_dialects/yaml/inclusion_1.tpl +0 -2
- data/test/standard_dialects/yaml/inclusion_2.exp +0 -5
- data/test/standard_dialects/yaml/inclusion_2.tpl +0 -3
- data/test/unit/test_all.rb +0 -9
- data/test/unit/wlang/anagram_bugs_test.rb +0 -111
- data/test/unit/wlang/basic_ruleset_test.rb +0 -52
- data/test/unit/wlang/buffering_ruleset_test.rb +0 -102
- data/test/unit/wlang/buffering_template1.wtpl +0 -1
- data/test/unit/wlang/buffering_template2.wtpl +0 -1
- data/test/unit/wlang/buffering_template3.wtpl +0 -1
- data/test/unit/wlang/buffering_template4.wtpl +0 -1
- data/test/unit/wlang/buffering_template5.wtpl +0 -1
- data/test/unit/wlang/context_ruleset_test.rb +0 -32
- data/test/unit/wlang/data.rb +0 -3
- data/test/unit/wlang/encoder_set_test.rb +0 -42
- data/test/unit/wlang/imperative_ruleset_test.rb +0 -107
- data/test/unit/wlang/intelligent_buffer_test.rb +0 -194
- data/test/unit/wlang/othersymbols_test.rb +0 -16
- data/test/unit/wlang/parser_test.rb +0 -88
- data/test/unit/wlang/plain_text_dialect_test.rb +0 -21
- data/test/unit/wlang/ruby_dialect_test.rb +0 -100
- data/test/unit/wlang/ruby_expected.rb +0 -3
- data/test/unit/wlang/ruby_template.wrb +0 -3
- data/test/unit/wlang/ruleset_utils_test.rb +0 -245
- data/test/unit/wlang/specification_examples_test.rb +0 -54
- data/test/unit/wlang/test_utils.rb +0 -25
- data/test/unit/wlang/wlang_test.rb +0 -80
|
@@ -0,0 +1,30 @@
|
|
|
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
|
|
@@ -0,0 +1,50 @@
|
|
|
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/dummy.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'wlang'
|
|
2
|
+
module WLang
|
|
3
|
+
#
|
|
4
|
+
# The _dummy_ dialect, which has no tag at all.
|
|
5
|
+
#
|
|
6
|
+
# This dialect can be used to parse tag blocks without further interpreting
|
|
7
|
+
# any wlang tag. This is needed to flush wlang output in certain situations
|
|
8
|
+
# as illustrated by the following template:
|
|
9
|
+
#
|
|
10
|
+
# Hello ${who}! This is wlang, a templating language which comes with
|
|
11
|
+
# special tags such as %{ ${who}, +{who}, *{authors}{...}, etc }
|
|
12
|
+
#
|
|
13
|
+
# The special tag %{ } might easily be implemented using the Dummy dialect:
|
|
14
|
+
#
|
|
15
|
+
# require 'wlang/dummy'
|
|
16
|
+
# class MyDialect < WLang::Dialect
|
|
17
|
+
#
|
|
18
|
+
# def dollar(buf, fn)
|
|
19
|
+
# buf << evaluate(fn)
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
# def no_wlang(buf, fn)
|
|
23
|
+
# render(fn)
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# tag '$', :dollar
|
|
27
|
+
# tag '%', [WLang::Dummy], :no_wlang
|
|
28
|
+
# end
|
|
29
|
+
#
|
|
30
|
+
class Dummy < Dialect
|
|
31
|
+
end # class Dummy
|
|
32
|
+
end # module WLang
|
data/lib/wlang/html.rb
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'wlang'
|
|
2
|
+
require 'wlang/dummy'
|
|
3
|
+
module WLang
|
|
4
|
+
class Html < WLang::Dialect
|
|
5
|
+
|
|
6
|
+
module Helpers
|
|
7
|
+
|
|
8
|
+
def value_of(fn)
|
|
9
|
+
evaluate(render(fn).to_s.strip)
|
|
10
|
+
end
|
|
11
|
+
private :value_of
|
|
12
|
+
|
|
13
|
+
def to_html(val)
|
|
14
|
+
val = val.to_html if val.respond_to?(:to_html)
|
|
15
|
+
val = to_html(val.call) if val.is_a?(Proc)
|
|
16
|
+
val.to_s
|
|
17
|
+
end
|
|
18
|
+
private :to_html
|
|
19
|
+
|
|
20
|
+
def escape_html(val)
|
|
21
|
+
Temple::Utils.escape_html(val)
|
|
22
|
+
end
|
|
23
|
+
private :escape_html
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
include Helpers
|
|
27
|
+
|
|
28
|
+
module HighOrderFunctions
|
|
29
|
+
|
|
30
|
+
def bang(buf, fn)
|
|
31
|
+
val = value_of(fn).to_s
|
|
32
|
+
render(val, nil, buf)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def plus(buf, fn)
|
|
36
|
+
val = value_of(fn)
|
|
37
|
+
val = to_html(val) unless val.is_a?(Template)
|
|
38
|
+
render(val, nil, buf)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def dollar(buf, fn)
|
|
42
|
+
val = escape_html(plus("", fn))
|
|
43
|
+
render(val, nil, buf)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def ampersand(buf, fn)
|
|
47
|
+
val = escape_html(render(fn))
|
|
48
|
+
render(val, nil, buf)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def slash(buf, fn)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def modulo(buf, fn)
|
|
55
|
+
render(fn, nil, buf)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def question(buf, fn_if, fn_then, fn_else)
|
|
59
|
+
val = value_of(fn_if) ? fn_then : fn_else
|
|
60
|
+
render(val, nil, buf) if val
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def caret(buf, fn_if, fn_then, fn_else)
|
|
64
|
+
val = value_of(fn_if) ? fn_else : fn_then
|
|
65
|
+
render(val, nil, buf) if val
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def star(buf, coll_fn, elm_fn, between_fn)
|
|
69
|
+
collection = value_of(coll_fn)
|
|
70
|
+
collection.each_with_index do |elm,i|
|
|
71
|
+
render(between_fn, elm, buf) if between_fn and (i > 0)
|
|
72
|
+
render(elm_fn, elm, buf)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def greater(buf, fn)
|
|
77
|
+
val = value_of(fn)
|
|
78
|
+
val = Html.compile(val) unless Template === val
|
|
79
|
+
render(val, nil, buf)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def sharp(buf, who_fn, then_fn)
|
|
83
|
+
val = value_of(who_fn)
|
|
84
|
+
if val and not(val.respond_to?(:empty?) and val.empty?)
|
|
85
|
+
render(then_fn, val, buf)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
end
|
|
90
|
+
include HighOrderFunctions
|
|
91
|
+
|
|
92
|
+
default_options :autospacing => true
|
|
93
|
+
tag '!', :bang
|
|
94
|
+
tag '+', :plus
|
|
95
|
+
tag '$', :dollar
|
|
96
|
+
tag '&', :ampersand
|
|
97
|
+
tag '/', :slash
|
|
98
|
+
tag '%', [WLang::Dummy], :modulo
|
|
99
|
+
tag '?', :question
|
|
100
|
+
tag '^', :caret
|
|
101
|
+
tag '*', :star
|
|
102
|
+
tag '>', :greater
|
|
103
|
+
tag '#', :sharp
|
|
104
|
+
|
|
105
|
+
end # class Html
|
|
106
|
+
end # module WLang
|
data/lib/wlang/loader.rb
CHANGED
|
@@ -0,0 +1,90 @@
|
|
|
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
|
data/lib/wlang/scope.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Scope
|
|
3
|
+
|
|
4
|
+
attr_reader :subject
|
|
5
|
+
attr_reader :parent
|
|
6
|
+
|
|
7
|
+
def initialize(subject, parent)
|
|
8
|
+
@subject, @parent = subject, parent
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.root
|
|
12
|
+
@root ||= RootScope.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.coerce(arg, parent = root)
|
|
16
|
+
clazz = case arg
|
|
17
|
+
when Binding
|
|
18
|
+
BindingScope
|
|
19
|
+
when Scope
|
|
20
|
+
ProxyScope
|
|
21
|
+
else
|
|
22
|
+
ObjectScope
|
|
23
|
+
end
|
|
24
|
+
clazz.new(arg, parent)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def push(x)
|
|
28
|
+
Scope.coerce(x, self)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def pop
|
|
32
|
+
@parent
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def with(x)
|
|
36
|
+
yield(self.push(x))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def evaluate(expr, *default)
|
|
40
|
+
unfound = lambda{ default.empty? ? throw(:fail) : default.first }
|
|
41
|
+
expr = expr.to_s.strip
|
|
42
|
+
if expr.to_s.index('.').nil?
|
|
43
|
+
fetch(expr.to_sym, &unfound)
|
|
44
|
+
else
|
|
45
|
+
keys = expr.split('.').map(&:to_sym)
|
|
46
|
+
keys.inject(self){|scope,key|
|
|
47
|
+
Scope.coerce(scope.fetch(key, &unfound))
|
|
48
|
+
}.subject
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end # class Scope
|
|
53
|
+
end # module WLang
|
|
54
|
+
require 'wlang/scope/root_scope'
|
|
55
|
+
require 'wlang/scope/proxy_scope'
|
|
56
|
+
require 'wlang/scope/object_scope'
|
|
57
|
+
require 'wlang/scope/binding_scope'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Scope
|
|
3
|
+
class BindingScope < Scope
|
|
4
|
+
|
|
5
|
+
def fetch(k, &blk)
|
|
6
|
+
subject.eval(k.to_s)
|
|
7
|
+
rescue NameError
|
|
8
|
+
parent.fetch(k, &blk)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def inspect
|
|
12
|
+
"BindingScope(#{subject.inspect})"
|
|
13
|
+
end
|
|
14
|
+
alias :to_s :inspect
|
|
15
|
+
|
|
16
|
+
end # class ProxyScope
|
|
17
|
+
end # class Scope
|
|
18
|
+
end # module WLang
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Scope
|
|
3
|
+
class ObjectScope < Scope
|
|
4
|
+
|
|
5
|
+
def fetch(k, &blk)
|
|
6
|
+
s = subject
|
|
7
|
+
return s if k == :self
|
|
8
|
+
if s.respond_to?(:has_key?)
|
|
9
|
+
return s[k] if s.has_key?(k)
|
|
10
|
+
return s[k.to_s] if s.has_key?(k.to_s)
|
|
11
|
+
end
|
|
12
|
+
return s.send(k) if s.respond_to?(k)
|
|
13
|
+
parent.fetch(k, &blk)
|
|
14
|
+
rescue NameError
|
|
15
|
+
parent.fetch(k, &blk)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def inspect
|
|
19
|
+
"ObjectScope(#{subject.inspect})"
|
|
20
|
+
end
|
|
21
|
+
alias :to_s :inspect
|
|
22
|
+
|
|
23
|
+
end # class ProxyScope
|
|
24
|
+
end # class Scope
|
|
25
|
+
end # module WLang
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Scope
|
|
3
|
+
class ProxyScope < Scope
|
|
4
|
+
|
|
5
|
+
def fetch(key, &blk)
|
|
6
|
+
subject.fetch(key) do
|
|
7
|
+
parent.fetch(key, &blk)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def inspect
|
|
12
|
+
subject.inspect
|
|
13
|
+
end
|
|
14
|
+
alias :to_s :inspect
|
|
15
|
+
|
|
16
|
+
end # class ProxyScope
|
|
17
|
+
end # class Scope
|
|
18
|
+
end # module WLang
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module WLang
|
|
2
|
+
class Scope
|
|
3
|
+
class RootScope < Scope
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
super(nil,nil)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def pop
|
|
10
|
+
raise "Unable to pop from root scope"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def fetch(key)
|
|
14
|
+
block_given? ? yield : throw(:fail)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def inspect
|
|
18
|
+
"RootScope"
|
|
19
|
+
end
|
|
20
|
+
alias :to_s :inspect
|
|
21
|
+
|
|
22
|
+
end # class RootScope
|
|
23
|
+
end # class Scope
|
|
24
|
+
end # module WLang
|