hmote 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a6f391daf28188242490899c275ffeae71b3aab6
4
+ data.tar.gz: bc569d4bb4e614bc7a6ddbeeee38e8cb5dbecf7d
5
+ SHA512:
6
+ metadata.gz: f367bf5d0fe6fecd1a5276f4ea1a22d89f5dac7b9712f45a5097f38db2b6b5cb660e4d0e399c06d5f745782001ccf00bdaee4e23dcccc6f2da889c6a30085974
7
+ data.tar.gz: 63b4f9a3d394726212b89d3fa0a0182db3c38c1e147b0b6afdc93df74eba11da454ff06d12d95a058382085341705b9495294efc84ef9c94f212cfe632cd2dba
data/.gems ADDED
@@ -0,0 +1,2 @@
1
+ cutest -v 1.2.1
2
+ hache -v 1.1.0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Francesco Rodríguez
2
+ Copyright (c) 2011-2014 Michel Martens
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in
12
+ all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ hmote
2
+ =====
3
+
4
+ Minimum Operational Template. Same as [mote][mote] but it escapes HTML
5
+ tag characters by default. It uses [hache][hache] to do the escaping.
6
+
7
+ Usage
8
+ -----
9
+
10
+ HMote escapes tag characters by default:
11
+
12
+ ```ruby
13
+ {{ '<img src="img.jpeg">' }}
14
+ # => &lt;img src=&quot;img.jpeg&quot;&gt;
15
+ ```
16
+
17
+ If you want to print content without escaping, then add `>` as
18
+ shown below:
19
+
20
+ ```ruby
21
+ {{> '<img src="img.jpeg">' }}
22
+ # => <img src="img.jpeg">
23
+ ```
24
+
25
+ For more information about the usage, check the
26
+ [Mote project homepage](https://github.com/soveran/mote).
27
+
28
+ Installation
29
+ ------------
30
+
31
+ ```
32
+ $ gem install hmote
33
+ ```
34
+
35
+ [mote]: https://github.com/soveran/mote
36
+ [hache]: https://github.com/frodsan/hache
data/hmote.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "hmote"
3
+ s.version = "1.0.0"
4
+ s.summary = "A minimum operational template that escapes HTML tags by default."
5
+ s.description = s.summary
6
+ s.authors = ["Francesco Rodríguez"]
7
+ s.email = ["frodsan@me.com"]
8
+ s.homepage = "http://github.com/frodsan/hmote"
9
+ s.license = "MIT"
10
+
11
+ s.files = `git ls-files`.split("\n")
12
+
13
+ s.add_dependency "hache"
14
+ s.add_development_dependency "cutest"
15
+ end
data/lib/hmote.rb ADDED
@@ -0,0 +1,44 @@
1
+ require "hache"
2
+
3
+ class Mote
4
+ PATTERN = /^(\n)|^\s*(%)\s*(.*?)(?:\n|\Z)|(<\?)\s+(.*?)\s+\?>|(\{\{>?)(.*?)\}\}/m
5
+
6
+ def self.parse(template, context = self, vars = [])
7
+ terms = template.split(PATTERN)
8
+
9
+ parts = "Proc.new do |params, __o|\n params ||= {}; __o ||= ''\n"
10
+
11
+ vars.each do |var|
12
+ parts << "%s = params[%s]\n" % [var, var.inspect]
13
+ end
14
+
15
+ while term = terms.shift
16
+ case term
17
+ when "<?" then parts << "#{terms.shift}\n"
18
+ when "%" then parts << "#{terms.shift}\n"
19
+ when "{{" then parts << "__o << Hache.h((#{terms.shift}).to_s)\n"
20
+ when "{{>" then parts << "__o << (#{terms.shift}).to_s\n"
21
+ else parts << "__o << #{term.dump}\n"
22
+ end
23
+ end
24
+
25
+ parts << "__o; end"
26
+
27
+ compile(context, parts)
28
+ end
29
+
30
+ def self.compile(context, parts)
31
+ context.instance_eval(parts)
32
+ end
33
+
34
+ module Helpers
35
+ def mote(file, params = {}, context = self)
36
+ mote_cache[file] ||= Mote.parse(File.read(file), context, params.keys)
37
+ mote_cache[file][params]
38
+ end
39
+
40
+ def mote_cache
41
+ Thread.current[:_mote_cache] ||= {}
42
+ end
43
+ end
44
+ end
data/makefile ADDED
@@ -0,0 +1,4 @@
1
+ .PHONY: test
2
+
3
+ test:
4
+ cutest test/*.rb
@@ -0,0 +1,3 @@
1
+ % 3.times do
2
+ *
3
+ % end
@@ -0,0 +1 @@
1
+ {{ foo }}
data/test/helpers.rb ADDED
@@ -0,0 +1,29 @@
1
+ require_relative "../lib/hmote"
2
+
3
+ class Cutest::Scope
4
+ include Mote::Helpers
5
+
6
+ def foo
7
+ "foo"
8
+ end
9
+ end
10
+
11
+ scope do
12
+ prepare do
13
+ mote_cache.clear
14
+ end
15
+
16
+ test "helpers" do
17
+ assert_equal " *\n *\n *\n", mote("test/fixtures/basic.mote", n: 3)
18
+ end
19
+
20
+ test "using functions in the context" do
21
+ assert_equal "foo\n", mote("test/fixtures/foo.mote")
22
+ end
23
+
24
+ test "passing in a context" do
25
+ assert_raise(NameError) do
26
+ mote("test/fixtures/foo.mote", {}, TOPLEVEL_BINDING)
27
+ end
28
+ end
29
+ end
data/test/hmote.rb ADDED
@@ -0,0 +1,151 @@
1
+ require_relative "../lib/hmote"
2
+
3
+ scope do
4
+ test "empty lines" do
5
+ example = Mote.parse("\n\n \n")
6
+ assert_equal "\n\n \n", example.call
7
+ end
8
+
9
+ test "empty lines with mixed code" do
10
+ example = Mote.parse("\n% true\n\n% false\n\n")
11
+ assert_equal "\n\n\n", example.call
12
+ end
13
+
14
+ test "empty lines with control flow" do
15
+ example = Mote.parse("\n% if true\n\n\n% else\n\n% end\n")
16
+ assert_equal "\n\n\n", example.call
17
+ end
18
+
19
+ test "control flow without final newline" do
20
+ example = Mote.parse("\n% if true\n\n\n% else\n\n% end")
21
+ assert_equal "\n\n\n", example.call
22
+ end
23
+
24
+ test "assignment" do
25
+ example = Mote.parse("{{ \"***\" }}")
26
+ assert_equal "***", example.call
27
+ end
28
+
29
+ test "comment" do
30
+ template = (<<-EOT).gsub(/ {4}/, "")
31
+ *
32
+ % # "*"
33
+ *
34
+ EOT
35
+
36
+ example = Mote.parse(template)
37
+ assert_equal "*\n*\n", example.call.squeeze("\n")
38
+ end
39
+
40
+ test "control flow" do
41
+ template = (<<-EOT).gsub(/ {4}/, "")
42
+ % if false
43
+ *
44
+ % else
45
+ ***
46
+ % end
47
+ EOT
48
+
49
+ example = Mote.parse(template)
50
+ assert_equal " ***\n", example.call
51
+ end
52
+
53
+ test "block evaluation" do
54
+ template = (<<-EOT).gsub(/ {4}/, "")
55
+ % 3.times {
56
+ *
57
+ % }
58
+ EOT
59
+
60
+ example = Mote.parse(template)
61
+ assert_equal "*\n*\n*\n", example.call
62
+ end
63
+
64
+ test "parameters" do
65
+ template = (<<-EOT).gsub(/ {4}/, "")
66
+ % params[:n].times {
67
+ *
68
+ % }
69
+ EOT
70
+
71
+ example = Mote.parse(template)
72
+ assert_equal "*\n*\n*\n", example[:n => 3]
73
+ assert_equal "*\n*\n*\n*\n", example[:n => 4]
74
+ end
75
+
76
+ test "multiline" do
77
+ example = Mote.parse("The\nMan\nAnd\n{{\"The\"}}\nSea")
78
+ assert_equal "The\nMan\nAnd\nThe\nSea", example[:n => 3]
79
+ end
80
+
81
+ test "quotes" do
82
+ example = Mote.parse("'foo' 'bar' 'baz'")
83
+ assert_equal "'foo' 'bar' 'baz'", example.call
84
+ end
85
+
86
+ test "context" do
87
+ context = Object.new
88
+ def context.user; "Bruno"; end
89
+
90
+ example = Mote.parse("{{ context.user }}", context, [:context])
91
+ assert_equal "Bruno", example.call(context: context)
92
+ end
93
+
94
+ test "locals" do
95
+ example = Mote.parse("{{ user }}", TOPLEVEL_BINDING, [:user])
96
+ assert_equal "Bruno", example.call(user: "Bruno")
97
+ end
98
+
99
+ test "nil" do
100
+ example = Mote.parse("{{ params[:user] }}", TOPLEVEL_BINDING, [:user])
101
+ assert_equal "", example.call(user: nil)
102
+ end
103
+
104
+ test "curly bug" do
105
+ example = Mote.parse("{{ [1, 2, 3].map { |i| i * i }.join(',') }}")
106
+ assert_equal "1,4,9", example.call
107
+ end
108
+
109
+ test "multi-line XML-style directives" do
110
+ template = (<<-EOT).gsub(/^ /, "")
111
+ <? res = ""
112
+ [1, 2, 3].each_with_index do |item, idx|
113
+ res << "%d. %d\n" % [idx + 1, item * item]
114
+ end
115
+ ?>
116
+ {{ res }}
117
+ EOT
118
+
119
+ example = Mote.parse(template)
120
+ assert_equal "\n1. 1\n2. 4\n3. 9\n\n", example.call
121
+ end
122
+
123
+ test "preserve XML directives" do
124
+ template = (<<-EOT).gsub(/^ /, "")
125
+ <?xml "hello" ?>
126
+ EOT
127
+
128
+ example = Mote.parse(template)
129
+ assert_equal "<?xml \"hello\" ?>\n", example.call
130
+ end
131
+
132
+ test "escapes html" do
133
+ template = (<<-EOT).gsub(/^ /, "")
134
+ % res = '<img src="img.jpeg">'
135
+ {{ res }}
136
+ EOT
137
+
138
+ example = Mote.parse(template)
139
+ assert_equal "&lt;img src=&quot;img.jpeg&quot;&gt;\n", example.call
140
+ end
141
+
142
+ test "outputs raw html" do
143
+ template = (<<-EOT).gsub(/^ /, "")
144
+ % res = '<img src="img.jpeg">'
145
+ {{> res }}
146
+ EOT
147
+
148
+ example = Mote.parse(template)
149
+ assert_equal "<img src=\"img.jpeg\">\n", example.call
150
+ end
151
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hmote
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Francesco Rodríguez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: hache
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cutest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A minimum operational template that escapes HTML tags by default.
42
+ email:
43
+ - frodsan@me.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gems"
49
+ - LICENSE
50
+ - README.md
51
+ - hmote.gemspec
52
+ - lib/hmote.rb
53
+ - makefile
54
+ - test/fixtures/basic.mote
55
+ - test/fixtures/foo.mote
56
+ - test/helpers.rb
57
+ - test/hmote.rb
58
+ homepage: http://github.com/frodsan/hmote
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.2.2
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: A minimum operational template that escapes HTML tags by default.
82
+ test_files: []