mote 1.1.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (8) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +58 -4
  4. data/lib/mote.rb +25 -19
  5. data/mote.gemspec +0 -1
  6. data/test/mote_test.rb +34 -15
  7. metadata +9 -11
  8. data/Rakefile +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 26b0b54d5537850b18d7faa452776b6d079ac0da
4
- data.tar.gz: 8da3ff5b57972c1b4189561b660bb01e49457784
2
+ SHA256:
3
+ metadata.gz: 505a571d37072d62d6a1de88ef80388861411beb832dee8a959a0aaf44250b3c
4
+ data.tar.gz: e71a2d24a0f66ad9d12e006114b0c3ab8c2e2d0f08c945e76042aa6bd1ab3505
5
5
  SHA512:
6
- metadata.gz: b1110be61eedc588a5e1f3682c1dd6cf75c86655508d9adba51137e1936e86b69422a8a3f493546fdc19fb38ce22584dcd3be8b2d633e62dab6c6151681ad773
7
- data.tar.gz: 03be6b8178add22491fefeb362b40c737f05d3248187eddd60e864180e40d92084f40cd3ce90330152c25feedadab8b6f8c435a6ea3a5d5c0c547871f9d683a1
6
+ metadata.gz: 41df91b9f277c509c6b5d438ac7039f07e5265889e58e8235d8d630bd4db7c263e2a9406776b691b86e0310736da1c3b91cff1d84d0b3cad86723844748d81b7
7
+ data.tar.gz: 1587c00e41e9bfeaf5a180b8297e3fb1f84e097c0c2d432fa2b2f86e7e7b4da921ab3919ced687d954733bcfaad5a6c028ea12000f52453ef9db0d4f8e721f89
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011, 2012 Michel Martens
1
+ Copyright (c) 2011 Michel Martens
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -22,16 +22,26 @@ Silly example, you may say, and I would agree. What follows is a short list of
22
22
  the different use cases you may face:
23
23
 
24
24
  ```
25
+ % # This is a comment
25
26
  % if user == "Bruno"
26
27
  {{user}} rhymes with Piano
27
28
  % elsif user == "Brutus"
28
29
  {{user}} rhymes with Opus
29
30
  % end
31
+
32
+ <?
33
+ # Multiline code evaluation
34
+ lucky = [1, 3, 7, 9, 13, 15]
35
+ prime = [2, 3, 5, 7, 11, 13]
36
+ ?>
37
+
38
+ {{ lucky & prime }}
30
39
  ```
31
40
 
32
41
  ## Control flow
33
42
 
34
- Lines that start with `%` are evaluated as Ruby code.
43
+ Lines that start with `%` are evaluated as Ruby code. Anything between
44
+ `<?` and `?>`, including new lines, is also evaluated as Ruby code.
35
45
 
36
46
  ## Assignment
37
47
 
@@ -45,7 +55,6 @@ There's nothing special about comments, it's just a `#` inside your Ruby code:
45
55
  % # This is a comment.
46
56
  ```
47
57
 
48
-
49
58
  ## Block evaluation
50
59
 
51
60
  As with control instructions, it happens naturally:
@@ -77,7 +86,7 @@ free to include it in your code. To do it, just type:
77
86
  include Mote::Helpers
78
87
  ```
79
88
 
80
- ## mote
89
+ ### Using the mote helper
81
90
 
82
91
  The `mote` helper receives a file name and a hash and returns the rendered
83
92
  version of its content. The compiled template is cached for subsequent calls.
@@ -86,9 +95,54 @@ version of its content. The compiled template is cached for subsequent calls.
86
95
  assert_equal "***\n", mote("test/basic.mote", n: 3)
87
96
  ```
88
97
 
98
+ ### Template caching
99
+
100
+ When the `mote` helper is first called with a template name, the
101
+ file is read and parsed, and a proc is created and stored in the
102
+ current thread. The parameters passed are defined as local
103
+ variables in the template. If you want to provide more parameters
104
+ once the template was cached, you won't be able to access the
105
+ values as local variables, but you can always access the `params`
106
+ hash.
107
+
108
+ For example:
109
+
110
+ ```ruby
111
+ # First call
112
+ mote("foo.mote", a: 1, b: 2)
113
+ ```
114
+
115
+ ## Command line tool
116
+
117
+ Mote ships with a command line tool to render mote templates. The
118
+ result is redirected to standard output.
119
+
120
+ ```
121
+ mote FILE [param1 value1 ... paramN valueN]
122
+ ```
123
+
124
+ The extra parameters supplied will be passed to the template.
125
+ Note that all the parameter values will be treated as strings.
126
+
127
+ ### Example usage
128
+
129
+ If your template is called foo.mote, you can render it with the
130
+ following command:
131
+
132
+ mote foo.mote
133
+
134
+ To write the result to a new file, just redirect the output:
135
+
136
+ mote foo.mote > foo.html
137
+
138
+ If the template uses a local variable `bar`, you can pass a
139
+ value from the command line:
140
+
141
+ mote foo.mote bar 42
142
+
89
143
  ## Installation
90
144
 
91
- As usual, you can install it using rubygems.
145
+ You can install it using rubygems.
92
146
 
93
147
  ```
94
148
  $ gem install mote
data/lib/mote.rb CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011, 2012 Michel Martens
1
+ # Copyright (c) 2011 Michel Martens
2
2
  #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  # of this software and associated documentation files (the "Software"), to deal
@@ -18,41 +18,47 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
  class Mote
21
- VERSION = "1.1.2"
21
+ VERSION = "1.3.1"
22
22
 
23
- PATTERN = /^(\n+)|^\s*(%)\s*(.*?)\n|(<\?)\s+(.*?)\s+\?>|(\{\{)(.*?)\}\}/m
23
+ # The regex has three alternative blocks that capture the embedded
24
+ # Ruby code. The rest is left as is.
25
+ PATTERN = /
26
+ ^[^\S\n]*(%)[^\S\n]*(.*?)(?:\n|\Z) | # Ruby evaluated lines
27
+ (<\?)\s+(.*?)\s+\?> | # Multiline Ruby blocks
28
+ (\{\{)(.*?)\}\} # Ruby evaluated to strings
29
+ /mx
24
30
 
25
- def self.parse(template, context = self, vars = [])
31
+ def self.src(template, vars = [])
26
32
  terms = template.split(PATTERN)
27
33
 
28
- parts = "Proc.new do |params, __o|\n params ||= {}; __o ||= ''\n"
34
+ code = "Proc.new do |params, __o| params ||= {}; __o ||= '';"
29
35
 
30
36
  vars.each do |var|
31
- parts << "%s = params[%s]\n" % [var, var.inspect]
37
+ code << "%s = params[%p];" % [var, var]
32
38
  end
33
39
 
34
- while term = terms.shift
40
+ while (term = terms.shift)
35
41
  case term
36
- when "<?" then parts << "#{terms.shift}\n"
37
- when "%" then parts << "#{terms.shift}\n"
38
- when "{{" then parts << "__o << (#{terms.shift}).to_s\n"
39
- else parts << "__o << #{term.dump}\n"
42
+ when "<?" then code << "#{terms.shift}\n"
43
+ when "%" then code << "#{terms.shift}\n"
44
+ when "{{" then code << "__o << (#{terms.shift}).to_s\n"
45
+ else code << "__o << #{term.dump}\n"
40
46
  end
41
47
  end
42
48
 
43
- parts << "__o; end"
44
-
45
- compile(context, parts)
49
+ code << "__o; end"
46
50
  end
47
51
 
48
- def self.compile(context, parts)
49
- context.instance_eval(parts)
52
+ def self.parse(_template, _context = self, _vars = [], _name = "template")
53
+ _context.instance_eval(src(_template, _vars), _name, -1)
50
54
  end
51
55
 
52
56
  module Helpers
53
- def mote(filename, params = {}, context = self)
54
- mote_cache[filename] ||= Mote.parse(File.read(filename), context, params.keys)
55
- mote_cache[filename][params]
57
+ def mote(file, params = {}, context = self)
58
+ template = File.read(file)
59
+
60
+ mote_cache[file] ||= Mote.parse(template, context, params.keys, file)
61
+ mote_cache[file][params]
56
62
  end
57
63
 
58
64
  def mote_cache
data/mote.gemspec CHANGED
@@ -12,7 +12,6 @@ Gem::Specification.new do |s|
12
12
  "LICENSE",
13
13
  "AUTHORS",
14
14
  "README.md",
15
- "Rakefile",
16
15
  "lib/**/*.rb",
17
16
  "*.gemspec",
18
17
  "test/**/*.rb"
data/test/mote_test.rb CHANGED
@@ -16,8 +16,13 @@ scope do
16
16
  assert_equal "\n\n\n", example.call
17
17
  end
18
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
+
19
24
  test "assignment" do
20
- example = Mote.parse("{{ \"***\" }}")
25
+ example = Mote.parse("{{ '***' }}")
21
26
  assert_equal "***", example.call
22
27
  end
23
28
 
@@ -70,7 +75,7 @@ scope do
70
75
 
71
76
  test "multiline" do
72
77
  example = Mote.parse("The\nMan\nAnd\n{{\"The\"}}\nSea")
73
- assert_equal "The\nMan\nAnd\nThe\nSea", example[:n => 3]
78
+ assert_equal "The\nMan\nAnd\nThe\nSea", example.call
74
79
  end
75
80
 
76
81
  test "quotes" do
@@ -82,8 +87,16 @@ scope do
82
87
  context = Object.new
83
88
  def context.user; "Bruno"; end
84
89
 
85
- example = Mote.parse("{{ context.user }}", context, [:context])
86
- assert_equal "Bruno", example.call(context: context)
90
+ example = Mote.parse("{{ user }}", context)
91
+ assert_equal "Bruno", example.call
92
+ end
93
+
94
+ test "context with name" do
95
+ context = Object.new
96
+ def context.name; "Sebas"; end
97
+
98
+ example = Mote.parse("{{ self.name }}", context)
99
+ assert_equal "Sebas", example.call
87
100
  end
88
101
 
89
102
  test "locals" do
@@ -96,23 +109,19 @@ scope do
96
109
  assert_equal "", example.call(user: nil)
97
110
  end
98
111
 
99
- test "curly bug" do
100
- example = Mote.parse("{{ [1, 2, 3].map { |i| i * i }.join(',') }}")
101
- assert_equal "1,4,9", example.call
102
- end
103
-
104
112
  test "multi-line XML-style directives" do
105
113
  template = (<<-EOT).gsub(/^ /, "")
106
- <? res = ""
107
- [1, 2, 3].each_with_index do |item, idx|
108
- res << "%d. %d\n" % [idx + 1, item * item]
109
- end
114
+ <?
115
+ # Multiline code evaluation
116
+ lucky = [1, 3, 7, 9, 13, 15]
117
+ prime = [2, 3, 5, 7, 11, 13]
110
118
  ?>
111
- {{ res }}
119
+
120
+ {{ lucky & prime }}
112
121
  EOT
113
122
 
114
123
  example = Mote.parse(template)
115
- assert_equal "\n1. 1\n2. 4\n3. 9\n\n", example.call
124
+ assert_equal "\n\n[3, 7, 13]\n", example.call
116
125
  end
117
126
 
118
127
  test "preserve XML directives" do
@@ -138,6 +147,16 @@ scope do
138
147
  mote_cache.clear
139
148
  end
140
149
 
150
+ test "syntax errors" do
151
+ begin
152
+ mote("test/error.mote")
153
+ rescue SyntaxError => error
154
+ end
155
+
156
+ assert_equal SyntaxError, error.class
157
+ assert error.message["test/error.mote:4: syntax error"]
158
+ end
159
+
141
160
  test "helpers" do
142
161
  assert_equal " *\n *\n *\n", mote("test/basic.mote", :n => 3)
143
162
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mote
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-15 00:00:00.000000000 Z
11
+ date: 2021-04-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cutest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  description: Mote is a very simple and fast template engine.
@@ -32,14 +32,13 @@ executables:
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
- - LICENSE
36
35
  - AUTHORS
36
+ - LICENSE
37
37
  - README.md
38
- - Rakefile
38
+ - bin/mote
39
39
  - lib/mote.rb
40
40
  - mote.gemspec
41
41
  - test/mote_test.rb
42
- - bin/mote
43
42
  homepage: http://github.com/soveran/mote
44
43
  licenses: []
45
44
  metadata: {}
@@ -49,17 +48,16 @@ require_paths:
49
48
  - lib
50
49
  required_ruby_version: !ruby/object:Gem::Requirement
51
50
  requirements:
52
- - - '>='
51
+ - - ">="
53
52
  - !ruby/object:Gem::Version
54
53
  version: '0'
55
54
  required_rubygems_version: !ruby/object:Gem::Requirement
56
55
  requirements:
57
- - - '>='
56
+ - - ">="
58
57
  - !ruby/object:Gem::Version
59
58
  version: '0'
60
59
  requirements: []
61
- rubyforge_project:
62
- rubygems_version: 2.0.3
60
+ rubygems_version: 3.0.3
63
61
  signing_key:
64
62
  specification_version: 4
65
63
  summary: Minimum Operational Template.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- task :test do
2
- require "cutest"
3
- Cutest.run(Dir["test/*.rb"])
4
- end
5
-
6
- task :default => :test