personify 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|