tempeh 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +55 -21
- data/examples/advanced.tempeh +14 -0
- data/examples/basic.tempeh +1 -0
- data/extras/Tempeh.sublime-syntax +38 -0
- data/lib/tempeh.rb +31 -19
- data/test/all.rb +42 -23
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17deec681294c1e4063e5d17506291cc84f0a565
|
4
|
+
data.tar.gz: 8a20e0ec8b46118a008db617b56e242fca4e3091
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53d84b831ce14d0155e56b84f2608af0cd3ed843a9cdb304de5bd3b4d875ec4400dff52cd32d8e80a19dae9d5291f3f1d762a4ed588de361f5c9a0a966b0cc83
|
7
|
+
data.tar.gz: 0e646e35b1542b1b36fdae9861b224be95eed88056767155ff72038791ccdd617a0bb6bd168582485f0ef7624e8caecece01f074499d7705222b9c38e7f2fd87
|
data/README.md
CHANGED
@@ -1,33 +1,67 @@
|
|
1
|
-
Tempeh
|
2
|
-
======
|
1
|
+
# Tempeh
|
3
2
|
|
4
3
|
Tasty Ruby Templates
|
5
4
|
|
6
|
-
Description
|
7
|
-
-----------
|
5
|
+
## Description
|
8
6
|
|
9
7
|
Tempeh is an opininated template engine for rendering html. It steals
|
10
|
-
most of its ideas from Mote
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
each time when passed to `#render`.
|
8
|
+
most of its ideas from [Mote](https://github.com/soveran/mote)
|
9
|
+
and the [Herb](https://github.com/frodsan/herb) fork. The motivation for
|
10
|
+
a new library is the different rendering API that is designed
|
11
|
+
for lazily binding a context with instance_eval for use with view components.
|
15
12
|
|
16
|
-
|
17
|
-
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
`gem install tempeh`
|
16
|
+
|
17
|
+
## Example
|
18
18
|
|
19
19
|
```ruby
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
20
|
+
# ./templates/eat.tempeh
|
21
|
+
#
|
22
|
+
# % if hungry? %
|
23
|
+
# Eat {{ food }}!
|
24
|
+
# % end %
|
25
|
+
|
26
|
+
require 'tempeh'
|
27
|
+
|
28
|
+
class View
|
29
|
+
include Tempeh::Helpers
|
30
|
+
|
31
|
+
def initialize(food)
|
32
|
+
@food = food
|
33
|
+
end
|
34
|
+
|
35
|
+
def food
|
36
|
+
@food
|
37
|
+
end
|
38
|
+
|
39
|
+
def hungry?
|
40
|
+
true
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
32
|
-
|
44
|
+
View.new('Tempeh').render('./templates/eat.tempeh') # Eat Tempeh!
|
33
45
|
```
|
46
|
+
|
47
|
+
## API
|
48
|
+
|
49
|
+
### Templates
|
50
|
+
|
51
|
+
`% code %`: Ruby to be evaluated but not outputted.
|
52
|
+
|
53
|
+
`{{ code }}`: Ruby that gets outputted as an escaped string. Safe for user input.
|
54
|
+
|
55
|
+
`{{& code }}`: Ruby that gets outputted as an unescaped string. Useful for rendering partials and other content that is guarenteed to be safe.
|
56
|
+
|
57
|
+
### Module Methods
|
58
|
+
|
59
|
+
`cache`: Hash of compiled templates, populated by the `render` helper.
|
60
|
+
|
61
|
+
`compile`: Creates a proc from the the given string.
|
62
|
+
|
63
|
+
`escape`: HTML escapes the given string.
|
64
|
+
|
65
|
+
### Helpers
|
66
|
+
|
67
|
+
`render`: instance_eval's a template found at a file path. Saves the compiled template in `Tempeh::cache` for reuse.
|
@@ -0,0 +1 @@
|
|
1
|
+
% 3.times do %{{ name }}% end %
|
@@ -0,0 +1,38 @@
|
|
1
|
+
%YAML 1.2
|
2
|
+
---
|
3
|
+
name: Tempeh
|
4
|
+
file_extensions:
|
5
|
+
- tempeh
|
6
|
+
scope: text.html
|
7
|
+
contexts:
|
8
|
+
main:
|
9
|
+
- match: ''
|
10
|
+
push: 'scope:text.html.basic'
|
11
|
+
with_prototype:
|
12
|
+
- match: "%\\s*#"
|
13
|
+
push:
|
14
|
+
- meta_scope: comment.block
|
15
|
+
- match: "%"
|
16
|
+
pop: true
|
17
|
+
|
18
|
+
- match: "%"
|
19
|
+
push:
|
20
|
+
- meta_scope: punctuation.section.braces
|
21
|
+
- match: "%"
|
22
|
+
pop: true
|
23
|
+
- include: 'scope:source.ruby'
|
24
|
+
|
25
|
+
- match: "{{&"
|
26
|
+
push:
|
27
|
+
- meta_scope: punctuation.section.braces
|
28
|
+
- match: "}}"
|
29
|
+
pop: true
|
30
|
+
- include: 'scope:source.ruby'
|
31
|
+
|
32
|
+
|
33
|
+
- match: "{{"
|
34
|
+
push:
|
35
|
+
- meta_scope: punctuation.section.braces
|
36
|
+
- match: "}}"
|
37
|
+
pop: true
|
38
|
+
- include: 'scope:source.ruby'
|
data/lib/tempeh.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.
|
1
|
+
module Tempeh
|
2
|
+
VERSION = "0.2.0"
|
3
3
|
|
4
|
-
BLK_OPEN =
|
4
|
+
BLK_OPEN = "%"
|
5
5
|
|
6
|
-
BLK_CLOSE =
|
6
|
+
BLK_CLOSE = "%"
|
7
7
|
|
8
|
-
|
8
|
+
RAW_OPEN = "{{&"
|
9
9
|
|
10
|
-
|
10
|
+
RAW_CLOSE = "}}"
|
11
|
+
|
12
|
+
STR_OPEN = "{{"
|
13
|
+
|
14
|
+
STR_CLOSE = "}}"
|
11
15
|
|
12
16
|
PATTERN = /
|
13
|
-
(?<!\\)(#{BLK_OPEN})\s+(.*?)\s+#{BLK_CLOSE} | # Multiline
|
14
|
-
(?<!\\)(#{
|
17
|
+
(?<!\\)(#{BLK_OPEN})\s+(.*?)\s+#{BLK_CLOSE} | # Multiline blocks.
|
18
|
+
(?<!\\)(#{RAW_OPEN})(.*?)#{RAW_CLOSE} | # Evaluated as a string, unescaped
|
19
|
+
(?<!\\)(#{STR_OPEN})(.*?)#{STR_CLOSE} # Evaluated as a string, escaped.
|
15
20
|
/mx
|
16
21
|
|
17
22
|
HTML_ESCAPE = {
|
@@ -19,25 +24,30 @@ class Tempeh
|
|
19
24
|
">" => ">",
|
20
25
|
"<" => "<",
|
21
26
|
'"' => "'",
|
22
|
-
"'" => """
|
27
|
+
"'" => """
|
23
28
|
}.freeze
|
24
29
|
|
25
30
|
UNSAFE = /[&"'><]/
|
26
31
|
|
27
32
|
class << self
|
33
|
+
def cache
|
34
|
+
@cache ||= {}
|
35
|
+
end
|
36
|
+
|
28
37
|
def compile(str)
|
29
38
|
terms = str.split(PATTERN)
|
30
|
-
parts = "proc
|
39
|
+
parts = "proc { __o = '';"
|
31
40
|
|
32
41
|
while (term = terms.shift)
|
33
42
|
case term
|
34
|
-
when BLK_OPEN then parts << terms.shift
|
35
|
-
when
|
36
|
-
|
43
|
+
when BLK_OPEN then parts << "#{terms.shift}\n"
|
44
|
+
when RAW_OPEN then parts << "__o << (#{terms.shift}).to_s\n"
|
45
|
+
when STR_OPEN then parts << "__o << Tempeh.escape((#{terms.shift}).to_s)\n"
|
46
|
+
else parts << "__o << #{term.dump}\n"
|
37
47
|
end
|
38
48
|
end
|
39
49
|
|
40
|
-
parts << "__o;
|
50
|
+
parts << "__o; }"
|
41
51
|
|
42
52
|
eval(parts)
|
43
53
|
end
|
@@ -47,11 +57,13 @@ class Tempeh
|
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
50
|
-
|
51
|
-
|
52
|
-
|
60
|
+
module Helpers
|
61
|
+
def render(path)
|
62
|
+
instance_eval &tempeh_template_for(path)
|
63
|
+
end
|
53
64
|
|
54
|
-
|
55
|
-
|
65
|
+
def tempeh_template_for(path)
|
66
|
+
Tempeh.cache[path] ||= Tempeh.compile(File.read(path))
|
67
|
+
end
|
56
68
|
end
|
57
69
|
end
|
data/test/all.rb
CHANGED
@@ -1,57 +1,76 @@
|
|
1
1
|
require_relative '../lib/tempeh'
|
2
2
|
|
3
3
|
test 'empty lines' do
|
4
|
-
template = Tempeh.
|
4
|
+
template = Tempeh.compile("\n\n \n")
|
5
5
|
|
6
|
-
assert_equal "\n\n \n", template.
|
6
|
+
assert_equal "\n\n \n", template.call
|
7
7
|
end
|
8
8
|
|
9
9
|
test 'quotes' do
|
10
|
-
template = Tempeh.
|
10
|
+
template = Tempeh.compile("'foo' 'bar' 'baz'")
|
11
11
|
|
12
|
-
assert_equal "'foo' 'bar' 'baz'", template.
|
12
|
+
assert_equal "'foo' 'bar' 'baz'", template.call
|
13
13
|
end
|
14
14
|
|
15
15
|
test 'block expressions' do
|
16
|
-
template = Tempeh.
|
16
|
+
template = Tempeh.compile("% if true %yes% else %no% end %")
|
17
17
|
|
18
|
-
assert_equal "yes", template.
|
18
|
+
assert_equal "yes", template.call
|
19
19
|
end
|
20
20
|
|
21
|
-
test 'string expressions' do
|
22
|
-
template = Tempeh.
|
21
|
+
test 'unescaped string expressions' do
|
22
|
+
template = Tempeh.compile(%q({{& %q(<>&"') }}))
|
23
23
|
|
24
|
-
assert_equal "
|
24
|
+
assert_equal %q(<>&"'), template.call
|
25
25
|
end
|
26
26
|
|
27
|
-
test '
|
28
|
-
template = Tempeh.
|
27
|
+
test 'escaped string expressions' do
|
28
|
+
template = Tempeh.compile(%q({{ %q(<>&"') }}))
|
29
29
|
|
30
|
-
assert_equal "<>&'"", template.
|
30
|
+
assert_equal "<>&'"", template.call
|
31
31
|
end
|
32
32
|
|
33
33
|
test 'nil string expressions' do
|
34
|
-
template = Tempeh.
|
34
|
+
template = Tempeh.compile("{{ nil }}")
|
35
35
|
|
36
|
-
assert_equal "", template.
|
36
|
+
assert_equal "", template.call
|
37
37
|
end
|
38
38
|
|
39
39
|
test 'allows escaping expressions' do
|
40
|
-
template = Tempeh.
|
40
|
+
template = Tempeh.compile('\{{ nil }}\% hello %')
|
41
41
|
|
42
|
-
assert_equal '\{ nil }\% hello %', template.
|
42
|
+
assert_equal '\{{ nil }}\% hello %', template.call
|
43
43
|
end
|
44
44
|
|
45
|
-
test '
|
46
|
-
context
|
45
|
+
test 'contextual rendering' do
|
46
|
+
context = Struct.new(:foo).new('bar')
|
47
|
+
template = Tempeh.compile("{{ foo }}")
|
47
48
|
|
48
|
-
|
49
|
+
assert_equal "bar", context.instance_eval(&template)
|
50
|
+
end
|
51
|
+
|
52
|
+
class View
|
53
|
+
include Tempeh::Helpers
|
49
54
|
|
50
|
-
|
55
|
+
def initialize(name)
|
56
|
+
@name = name
|
57
|
+
end
|
58
|
+
|
59
|
+
def name
|
60
|
+
@name
|
61
|
+
end
|
51
62
|
end
|
52
63
|
|
53
|
-
|
54
|
-
|
64
|
+
setup do
|
65
|
+
View.new('steve')
|
66
|
+
end
|
67
|
+
|
68
|
+
test 'helpers' do |view|
|
69
|
+
path = './test/basic.tempeh'
|
70
|
+
|
71
|
+
assert Tempeh.cache[path].nil?, 'template is already cached'
|
72
|
+
|
73
|
+
assert_equal 'stevestevesteve', view.render('./examples/basic.tempeh')
|
55
74
|
|
56
|
-
|
75
|
+
assert Tempeh.cache[path], 'template was not cached'
|
57
76
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tempeh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steve Weiss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cutest
|
@@ -37,6 +37,9 @@ files:
|
|
37
37
|
- LICENSE
|
38
38
|
- README.md
|
39
39
|
- Rakefile
|
40
|
+
- examples/advanced.tempeh
|
41
|
+
- examples/basic.tempeh
|
42
|
+
- extras/Tempeh.sublime-syntax
|
40
43
|
- lib/tempeh.rb
|
41
44
|
- tempeh.gemspec
|
42
45
|
- test/all.rb
|