mote 1.1.2 → 1.3.1

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.
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