personify 1.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/.gitignore +1 -0
- data/LICENSE +20 -0
- data/README.md +172 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/doc/syntax_ideas.md +141 -0
- data/lib/personify/context.rb +55 -0
- data/lib/personify/parser/personify.rb +1071 -0
- data/lib/personify/parser/personify.treetop +107 -0
- data/lib/personify/parser/personify_node_classes.rb +121 -0
- data/lib/personify/template.rb +17 -0
- data/lib/personify.rb +8 -0
- data/script/generate_parser.rb +6 -0
- data/test/context_test.rb +122 -0
- data/test/fixtures/multiple_tags.txt +8 -0
- data/test/parse_runner.rb +60 -0
- data/test/parser_test.rb +291 -0
- data/test/test_helper.rb +16 -0
- data/vendor/treetop/.gitignore +5 -0
- data/vendor/treetop/History.txt +9 -0
- data/vendor/treetop/README +164 -0
- data/vendor/treetop/Rakefile +20 -0
- data/vendor/treetop/Treetop.tmbundle/Snippets/grammar ___ end.tmSnippet +20 -0
- data/vendor/treetop/Treetop.tmbundle/Snippets/rule ___ end.tmSnippet +18 -0
- data/vendor/treetop/Treetop.tmbundle/Syntaxes/Treetop Grammar.tmLanguage +251 -0
- data/vendor/treetop/Treetop.tmbundle/info.plist +10 -0
- data/vendor/treetop/bin/tt +28 -0
- data/vendor/treetop/doc/contributing_and_planned_features.markdown +103 -0
- data/vendor/treetop/doc/grammar_composition.markdown +65 -0
- data/vendor/treetop/doc/index.markdown +90 -0
- data/vendor/treetop/doc/pitfalls_and_advanced_techniques.markdown +51 -0
- data/vendor/treetop/doc/semantic_interpretation.markdown +189 -0
- data/vendor/treetop/doc/site.rb +110 -0
- data/vendor/treetop/doc/sitegen.rb +60 -0
- data/vendor/treetop/doc/syntactic_recognition.markdown +100 -0
- data/vendor/treetop/doc/using_in_ruby.markdown +21 -0
- data/vendor/treetop/examples/lambda_calculus/arithmetic.rb +551 -0
- data/vendor/treetop/examples/lambda_calculus/arithmetic.treetop +97 -0
- data/vendor/treetop/examples/lambda_calculus/arithmetic_node_classes.rb +7 -0
- data/vendor/treetop/examples/lambda_calculus/arithmetic_test.rb +54 -0
- data/vendor/treetop/examples/lambda_calculus/lambda_calculus +0 -0
- data/vendor/treetop/examples/lambda_calculus/lambda_calculus.rb +718 -0
- data/vendor/treetop/examples/lambda_calculus/lambda_calculus.treetop +132 -0
- data/vendor/treetop/examples/lambda_calculus/lambda_calculus_node_classes.rb +5 -0
- data/vendor/treetop/examples/lambda_calculus/lambda_calculus_test.rb +89 -0
- data/vendor/treetop/examples/lambda_calculus/test_helper.rb +18 -0
- data/vendor/treetop/lib/treetop/bootstrap_gen_1_metagrammar.rb +45 -0
- data/vendor/treetop/lib/treetop/compiler/grammar_compiler.rb +40 -0
- data/vendor/treetop/lib/treetop/compiler/lexical_address_space.rb +17 -0
- data/vendor/treetop/lib/treetop/compiler/metagrammar.rb +2955 -0
- data/vendor/treetop/lib/treetop/compiler/metagrammar.treetop +404 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/anything_symbol.rb +20 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/atomic_expression.rb +14 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/character_class.rb +22 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/choice.rb +31 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/grammar.rb +28 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/nonterminal.rb +13 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/optional.rb +19 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/parsing_expression.rb +138 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/predicate.rb +45 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/repetition.rb +55 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/sequence.rb +68 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/terminal.rb +20 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/transient_prefix.rb +9 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
- data/vendor/treetop/lib/treetop/compiler/node_classes.rb +19 -0
- data/vendor/treetop/lib/treetop/compiler/ruby_builder.rb +113 -0
- data/vendor/treetop/lib/treetop/compiler.rb +6 -0
- data/vendor/treetop/lib/treetop/ruby_extensions/string.rb +42 -0
- data/vendor/treetop/lib/treetop/ruby_extensions.rb +2 -0
- data/vendor/treetop/lib/treetop/runtime/compiled_parser.rb +95 -0
- data/vendor/treetop/lib/treetop/runtime/interval_skip_list/head_node.rb +15 -0
- data/vendor/treetop/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb +200 -0
- data/vendor/treetop/lib/treetop/runtime/interval_skip_list/node.rb +164 -0
- data/vendor/treetop/lib/treetop/runtime/interval_skip_list.rb +4 -0
- data/vendor/treetop/lib/treetop/runtime/syntax_node.rb +72 -0
- data/vendor/treetop/lib/treetop/runtime/terminal_parse_failure.rb +16 -0
- data/vendor/treetop/lib/treetop/runtime/terminal_syntax_node.rb +17 -0
- data/vendor/treetop/lib/treetop/runtime.rb +5 -0
- data/vendor/treetop/lib/treetop/version.rb +9 -0
- data/vendor/treetop/lib/treetop.rb +11 -0
- data/vendor/treetop/script/generate_metagrammar.rb +14 -0
- data/vendor/treetop/script/svnadd +11 -0
- data/vendor/treetop/script/svnrm +11 -0
- data/vendor/treetop/spec/compiler/and_predicate_spec.rb +36 -0
- data/vendor/treetop/spec/compiler/anything_symbol_spec.rb +52 -0
- data/vendor/treetop/spec/compiler/character_class_spec.rb +188 -0
- data/vendor/treetop/spec/compiler/choice_spec.rb +80 -0
- data/vendor/treetop/spec/compiler/circular_compilation_spec.rb +28 -0
- data/vendor/treetop/spec/compiler/failure_propagation_functional_spec.rb +21 -0
- data/vendor/treetop/spec/compiler/grammar_compiler_spec.rb +84 -0
- data/vendor/treetop/spec/compiler/grammar_spec.rb +41 -0
- data/vendor/treetop/spec/compiler/nonterminal_symbol_spec.rb +40 -0
- data/vendor/treetop/spec/compiler/not_predicate_spec.rb +38 -0
- data/vendor/treetop/spec/compiler/one_or_more_spec.rb +35 -0
- data/vendor/treetop/spec/compiler/optional_spec.rb +37 -0
- data/vendor/treetop/spec/compiler/parenthesized_expression_spec.rb +19 -0
- data/vendor/treetop/spec/compiler/parsing_rule_spec.rb +32 -0
- data/vendor/treetop/spec/compiler/sequence_spec.rb +115 -0
- data/vendor/treetop/spec/compiler/terminal_spec.rb +81 -0
- data/vendor/treetop/spec/compiler/terminal_symbol_spec.rb +37 -0
- data/vendor/treetop/spec/compiler/test_grammar.treetop +7 -0
- data/vendor/treetop/spec/compiler/test_grammar.tt +7 -0
- data/vendor/treetop/spec/compiler/test_grammar_do.treetop +7 -0
- data/vendor/treetop/spec/compiler/zero_or_more_spec.rb +56 -0
- data/vendor/treetop/spec/composition/a.treetop +11 -0
- data/vendor/treetop/spec/composition/b.treetop +11 -0
- data/vendor/treetop/spec/composition/c.treetop +10 -0
- data/vendor/treetop/spec/composition/d.treetop +10 -0
- data/vendor/treetop/spec/composition/grammar_composition_spec.rb +26 -0
- data/vendor/treetop/spec/ruby_extensions/string_spec.rb +32 -0
- data/vendor/treetop/spec/runtime/compiled_parser_spec.rb +101 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/delete_spec.rb +147 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/expire_range_spec.rb +349 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/insert_and_delete_node.rb +385 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/insert_spec.rb +660 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.graffle +6175 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.rb +58 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture.rb +23 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture_spec.rb +164 -0
- data/vendor/treetop/spec/runtime/interval_skip_list/spec_helper.rb +84 -0
- data/vendor/treetop/spec/runtime/syntax_node_spec.rb +53 -0
- data/vendor/treetop/spec/spec_helper.rb +106 -0
- data/vendor/treetop/spec/spec_suite.rb +4 -0
- data/vendor/treetop/treetop.gemspec +18 -0
- metadata +196 -0
data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.DS_Store
|
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2011 Digitpaint, Flurin Egger
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Personify : personalisation template language
|
|
2
|
+
=============================================
|
|
3
|
+
|
|
4
|
+
Personfify is meant for use in environments where templates just need
|
|
5
|
+
to be personalized.
|
|
6
|
+
|
|
7
|
+
Basic syntax
|
|
8
|
+
------------
|
|
9
|
+
|
|
10
|
+
Alle expressions are wrapped in brackets ([ ]). All code outside
|
|
11
|
+
of brackets will not be evaluated.
|
|
12
|
+
|
|
13
|
+
If the return statement of an expression is nil, it won't be replaced
|
|
14
|
+
by it's output.
|
|
15
|
+
|
|
16
|
+
All whitespace within expressions is ignored.
|
|
17
|
+
|
|
18
|
+
Simple substitution
|
|
19
|
+
-------------------
|
|
20
|
+
|
|
21
|
+
The simplest use of the personify template language is to just use
|
|
22
|
+
the standard substitution expressions. A substitution expression
|
|
23
|
+
exists of a key which will be replaced if it's found in the context.
|
|
24
|
+
|
|
25
|
+
#### Examples:
|
|
26
|
+
|
|
27
|
+
With context:
|
|
28
|
+
|
|
29
|
+
{"key" => "value"}
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
|
|
33
|
+
[KEY] => value
|
|
34
|
+
[UNKNOWN] => [UNKNOWN]
|
|
35
|
+
|
|
36
|
+
Substitutions with fallback
|
|
37
|
+
---------------------------
|
|
38
|
+
|
|
39
|
+
A more advanced feature is to use fallbacks on missing keys. If a key can't
|
|
40
|
+
be found in the context, all alternative keys (separated by a pipe (|))
|
|
41
|
+
will be tried until a non-nil value is found. If a the last alternative
|
|
42
|
+
returns nil, the original expression won't be replaced.
|
|
43
|
+
|
|
44
|
+
You can also specify strings as fallbacks, they will always return the string.
|
|
45
|
+
See also the note on strings below.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
#### Examples:
|
|
49
|
+
|
|
50
|
+
With context:
|
|
51
|
+
|
|
52
|
+
{"key" => "value"}
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
|
|
56
|
+
[UNKNOWN | KEY] => value
|
|
57
|
+
[UNKNOWN1 | UNKNOWN2 | "default"] => default
|
|
58
|
+
[UNKNOWN1 | UNKNOWN2 | default] => default
|
|
59
|
+
|
|
60
|
+
Boolean logic
|
|
61
|
+
-------------
|
|
62
|
+
|
|
63
|
+
You can use boolean logic parameters && (and) and || (or) to implement simple logic. The logic can be used
|
|
64
|
+
anywhere where you can use a substitution, which means you can use it as a standalone subsitition, within a function
|
|
65
|
+
parameter or as an alternative.
|
|
66
|
+
|
|
67
|
+
**Attention!** We currently do not support operator precedence and parenthesis, the logic will be evaluated
|
|
68
|
+
backwards so the statement A && B || C will actually be evaluated as A && (B || C).
|
|
69
|
+
|
|
70
|
+
#### Examples:
|
|
71
|
+
|
|
72
|
+
with context:
|
|
73
|
+
|
|
74
|
+
{
|
|
75
|
+
"a" => "a",
|
|
76
|
+
"b" => "b",
|
|
77
|
+
"c" => "c",
|
|
78
|
+
"d" => nil
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
Example:
|
|
82
|
+
|
|
83
|
+
[A && B] => a
|
|
84
|
+
[A && D | "default"] => default
|
|
85
|
+
|
|
86
|
+
[A || B] => a
|
|
87
|
+
[B || A] => b
|
|
88
|
+
[D || A] => a
|
|
89
|
+
|
|
90
|
+
[A && B || C] => a
|
|
91
|
+
[A && D || C] => c
|
|
92
|
+
|
|
93
|
+
[A || B && C] => a
|
|
94
|
+
[D || B && C || "default"] => default
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
Function calls
|
|
98
|
+
--------------
|
|
99
|
+
|
|
100
|
+
For more flexibility, it is possible to put functions in
|
|
101
|
+
the context by means of lamda's and procs. However you need to be very
|
|
102
|
+
carefull with accepting parameters as Personify will just splat all
|
|
103
|
+
parameters into the proc's call method. If an expected function
|
|
104
|
+
doesn't respond to a call method, it just works like a normal substitution.
|
|
105
|
+
|
|
106
|
+
### Simple Syntax
|
|
107
|
+
|
|
108
|
+
#### Examples:
|
|
109
|
+
|
|
110
|
+
With context:
|
|
111
|
+
|
|
112
|
+
{
|
|
113
|
+
"key1" => "v1",
|
|
114
|
+
"key2" => "v2"
|
|
115
|
+
"ampersandize" => Proc.new{|*c| c.join(" & ") }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Example:
|
|
119
|
+
|
|
120
|
+
[AMPERSANDIZE(KEY1,KEY2)] => v1 & v2
|
|
121
|
+
[AMPERSANDIZE(KEY1 , "default")] => v1 & default
|
|
122
|
+
[AMPERSANDIZE("1","2","3")] => 1 & 2 & 3
|
|
123
|
+
[AMPERSANDIZE("1",2,3)] => 1 & 2 & 3
|
|
124
|
+
|
|
125
|
+
### Block Syntax
|
|
126
|
+
|
|
127
|
+
You can also use a block-style syntax with functions. The content of the block will be passed
|
|
128
|
+
to the function as the last parameter.
|
|
129
|
+
|
|
130
|
+
#### Example: Simple function substitution
|
|
131
|
+
|
|
132
|
+
[FUN(VAR) DO]
|
|
133
|
+
content passed to the IF fn as last parameter, the whole block will be substituted.
|
|
134
|
+
for example lambda{|var,glob| var > 1 ? glob : "" }
|
|
135
|
+
[END]
|
|
136
|
+
|
|
137
|
+
#### Example: Function as alternative
|
|
138
|
+
|
|
139
|
+
[FIRST | FUN() DO]
|
|
140
|
+
if FIRST is available do that, if not pass this text to FUN() call.
|
|
141
|
+
Always replace this text.
|
|
142
|
+
[END]
|
|
143
|
+
|
|
144
|
+
#### Example: Function as an alternative with a fallback string
|
|
145
|
+
|
|
146
|
+
[FIRST | FUN() DO]
|
|
147
|
+
First check FIRST, then try to call the FUN with this content, as a last resort use the
|
|
148
|
+
fallback string
|
|
149
|
+
[END | "fallback"]
|
|
150
|
+
|
|
151
|
+
#### Example: Function as an alternative with another function as fallback
|
|
152
|
+
|
|
153
|
+
[FUN() DO]
|
|
154
|
+
Pass this to FUN and if it returns non false/nil we show the return value
|
|
155
|
+
[END | FUN2() DO]
|
|
156
|
+
If FUN() return a false/nil value we pass this to FUN2() and show it's return value
|
|
157
|
+
[END]
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
Strings
|
|
161
|
+
-------
|
|
162
|
+
|
|
163
|
+
Strings can be used either as parameters for a function or in an expression
|
|
164
|
+
as an alternative. Strings don't necessarily need to be quoted as long
|
|
165
|
+
as they don't contain any of these characters: "]),|
|
|
166
|
+
|
|
167
|
+
Strings cannot ever contain double qoutes (").
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
Copyright
|
|
171
|
+
---------
|
|
172
|
+
Copyright (c) 2011 Digitpaint, Flurin Egger. See LICENSE for details.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'jeweler'
|
|
6
|
+
Jeweler::Tasks.new do |gem|
|
|
7
|
+
gem.name = "personify"
|
|
8
|
+
gem.summary = %Q{A personalisation template language}
|
|
9
|
+
gem.description = %Q{Personfify is meant for use in environments where templates just need to be personalized.}
|
|
10
|
+
gem.email = "flurin@digitpaint.nl"
|
|
11
|
+
gem.homepage = "http://github.com/digitpaint/personify"
|
|
12
|
+
gem.authors = ["Flurin Egger"]
|
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
|
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
15
|
+
end
|
|
16
|
+
Jeweler::GemcutterTasks.new
|
|
17
|
+
rescue LoadError
|
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
require 'rake/testtask'
|
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
|
23
|
+
test.libs << 'lib' << 'test'
|
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
|
25
|
+
test.verbose = true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
begin
|
|
29
|
+
require 'rcov/rcovtask'
|
|
30
|
+
Rcov::RcovTask.new do |test|
|
|
31
|
+
test.libs << 'test'
|
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
|
33
|
+
test.verbose = true
|
|
34
|
+
end
|
|
35
|
+
rescue LoadError
|
|
36
|
+
task :rcov do
|
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
task :test => :check_dependencies
|
|
42
|
+
|
|
43
|
+
task :default => :test
|
|
44
|
+
|
|
45
|
+
require 'rake/rdoctask'
|
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
48
|
+
|
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
50
|
+
rdoc.title = "personify #{version}"
|
|
51
|
+
rdoc.rdoc_files.include('README*')
|
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
53
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.0
|
data/doc/syntax_ideas.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Current state
|
|
2
|
+
=============
|
|
3
|
+
|
|
4
|
+
## String
|
|
5
|
+
["string"]
|
|
6
|
+
|
|
7
|
+
## Substitution
|
|
8
|
+
[SUBSTITUTE]
|
|
9
|
+
|
|
10
|
+
## Substitution with alternatives
|
|
11
|
+
[SUBSTITUTE | ALT]
|
|
12
|
+
|
|
13
|
+
## Function with substitution parameters
|
|
14
|
+
[FUN(SUBSTITUTE)]
|
|
15
|
+
|
|
16
|
+
## Function with string parameter
|
|
17
|
+
[FUN("string")]
|
|
18
|
+
|
|
19
|
+
## !? Does this work?
|
|
20
|
+
[FUN(1)]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Proposals for block syntax
|
|
24
|
+
==========================
|
|
25
|
+
|
|
26
|
+
[FUN() DO]
|
|
27
|
+
passed to function as last parameter
|
|
28
|
+
[END]
|
|
29
|
+
|
|
30
|
+
[START:FUN]
|
|
31
|
+
pass to block?
|
|
32
|
+
[STOP:FUN]
|
|
33
|
+
|
|
34
|
+
[FUN<]
|
|
35
|
+
[>]
|
|
36
|
+
|
|
37
|
+
[VAR<]
|
|
38
|
+
[>VAR]
|
|
39
|
+
|
|
40
|
+
[VAR]
|
|
41
|
+
[/VAR]
|
|
42
|
+
|
|
43
|
+
[FUN>
|
|
44
|
+
some weird stuff
|
|
45
|
+
<]
|
|
46
|
+
|
|
47
|
+
[SUBSTITUTE | >
|
|
48
|
+
|
|
49
|
+
<]
|
|
50
|
+
|
|
51
|
+
[SUBSTITUTE | FUN() >
|
|
52
|
+
<]
|
|
53
|
+
|
|
54
|
+
[FUN()]
|
|
55
|
+
passed to function as last parameter
|
|
56
|
+
[/]
|
|
57
|
+
|
|
58
|
+
[FUN(){
|
|
59
|
+
passed to function as last parameter
|
|
60
|
+
}]
|
|
61
|
+
|
|
62
|
+
[VAR{
|
|
63
|
+
show text if VAR == true
|
|
64
|
+
}]
|
|
65
|
+
|
|
66
|
+
# Context
|
|
67
|
+
{
|
|
68
|
+
:subscriber => {
|
|
69
|
+
:email => "flurin@digitpaint.nl",
|
|
70
|
+
:token => "abcdef",
|
|
71
|
+
:id => 201,
|
|
72
|
+
:newsletters => {
|
|
73
|
+
1 => {
|
|
74
|
+
:frequency => "day"
|
|
75
|
+
},
|
|
76
|
+
5 => {
|
|
77
|
+
:frequency => "day"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
# /Context
|
|
83
|
+
|
|
84
|
+
[SUBSCRIBER.EMAIL] #=> "flurin@digitpaint.nl"
|
|
85
|
+
[SUBSCRIBER.NEWSLETTER.1.FREQUENCY] #=> "day"
|
|
86
|
+
|
|
87
|
+
[IF SUBSCRIBER.NEWSLETTER.1]
|
|
88
|
+
...
|
|
89
|
+
[END]
|
|
90
|
+
|
|
91
|
+
# Capture content to pass to function
|
|
92
|
+
[FUN(VAR) DO]
|
|
93
|
+
content passed to the IF fn as last parameter, the whole block will be substituted.
|
|
94
|
+
for example lambda{|var,glob| var > 1 ? glob : "" }
|
|
95
|
+
[END]
|
|
96
|
+
|
|
97
|
+
[FIRST | FUN() DO]
|
|
98
|
+
if FIRST is available do that, if not pass this text to FUN() call.
|
|
99
|
+
Always replace this text.
|
|
100
|
+
[END]
|
|
101
|
+
|
|
102
|
+
[FIRST | FUN() DO]
|
|
103
|
+
First check FIRST, then try to call the FUN with this content, as a last resort use the
|
|
104
|
+
fallback string
|
|
105
|
+
[END | "fallback"]
|
|
106
|
+
|
|
107
|
+
[FUN() DO]
|
|
108
|
+
Pass this to FUN and if it returns non false/nil we show the return value
|
|
109
|
+
[END | FUN2() DO]
|
|
110
|
+
If FUN() return a false/nil value we pass this to FUN2() and show it's return value
|
|
111
|
+
[END]
|
|
112
|
+
|
|
113
|
+
[VAR DO]
|
|
114
|
+
invalid syntax will not substitue
|
|
115
|
+
[END]
|
|
116
|
+
|
|
117
|
+
# IF as a language construct with ELSIF and ELSE
|
|
118
|
+
[IF EXPR1]
|
|
119
|
+
if EXPR is true do this
|
|
120
|
+
[ELSIF EXPR2]
|
|
121
|
+
if EXPR1 is false and EXPR2 is true, do this
|
|
122
|
+
[ELSE]
|
|
123
|
+
all other cases do this
|
|
124
|
+
[END]
|
|
125
|
+
|
|
126
|
+
COMPARATORS
|
|
127
|
+
|
|
128
|
+
A == "b"
|
|
129
|
+
A > 1
|
|
130
|
+
A < 1
|
|
131
|
+
A <= 1
|
|
132
|
+
A >= 1
|
|
133
|
+
FN(A) == true
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
[IF(VAR){
|
|
138
|
+
|
|
139
|
+
[} ELSE {]
|
|
140
|
+
|
|
141
|
+
[}]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Personify
|
|
2
|
+
# This specifies the context we can evaluate in
|
|
3
|
+
class Context
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
def allowed_context_methods
|
|
7
|
+
@allowed_methods ||= []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def context_method(method_name)
|
|
11
|
+
self.allowed_context_methods << method_name.to_s if self.instance_methods.include?(method_name.to_s)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def allow_method?(method_name)
|
|
15
|
+
self.allowed_context_methods.include?(method_name.to_s)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def allow_method?(method_name)
|
|
20
|
+
self.class.allow_method?(method_name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def local_assigns=(assigns)
|
|
24
|
+
@local_assigns = assigns
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def local_assigns
|
|
28
|
+
@local_assigns ||= {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def [](k)
|
|
32
|
+
self.local_assigns[k]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def has_key?(k)
|
|
36
|
+
self.local_assigns.has_key?(k)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class DefaultContext < Context
|
|
44
|
+
|
|
45
|
+
def if(statement, value)
|
|
46
|
+
if statement
|
|
47
|
+
value
|
|
48
|
+
else
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
context_method :if
|
|
53
|
+
|
|
54
|
+
end
|
|
55
|
+
end
|