lita 4.1.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f7cb3c5b605c35c60bdff103c47df2488814712
4
- data.tar.gz: 22be31cadc4608c676923ea7253a9a3b6456e5ad
3
+ metadata.gz: 24b9a37965d639387442b0a419f4c1c860f726b9
4
+ data.tar.gz: 59d805329cc2aeab6724473f78dda55e01a1e970
5
5
  SHA512:
6
- metadata.gz: 5f11b1e00ff16c75e0a5c56a7c96b6d658d27ef207444deb2808265471409f5fc5d6c2d3c585b3c56434e8097515ce5eee85f7d02de983979e005a47435e415b
7
- data.tar.gz: 2bb7b4fd5497735d4e4a78559b26878f4de79e016901bf1c123c56b78fa37bc6d3c1e7b430875fd7fd820f55026b5f66e3d54ac1ee7be13a96c74a7941304eb3
6
+ metadata.gz: 06734db0a8f1de6b83acabcea2546db17df71900876ee1864ef524c7607c60a3a223919dbb9aa30602915bce5d10aeacdedf84e6f7da324575d3bc0701eb305b
7
+ data.tar.gz: c94be903e979b6a5a0d3c3eae0cfcf8d1d457d5895c087d5b64070fddcf0cf88b647c425123e427d0caae149b188863f3fc1e9b0f7395189a0516093b222d382
@@ -94,6 +94,8 @@ require_relative "lita/logger"
94
94
  require_relative "lita/callback"
95
95
  require_relative "lita/configurable"
96
96
  require_relative "lita/namespace"
97
+ require_relative "lita/template"
98
+ require_relative "lita/template_resolver"
97
99
  require_relative "lita/handler/common"
98
100
  require_relative "lita/handler/chat_router"
99
101
  require_relative "lita/handler/http_router"
@@ -172,6 +172,9 @@ module Lita
172
172
  )
173
173
  template("plugin/spec/spec_helper.tt", "#{target}/spec/spec_helper.rb", config)
174
174
  template("plugin/locales/en.yml.tt", "#{target}/locales/en.yml", config)
175
+ if config[:plugin_type] == "handler"
176
+ copy_file("plugin/templates/gitkeep", "#{target}/templates/.gitkeep")
177
+ end
175
178
  copy_file("plugin/Gemfile", "#{target}/Gemfile")
176
179
  template("plugin/gemspec.tt", "#{target}/#{gem_name}.gemspec", config)
177
180
  copy_file("plugin/gitignore", "#{target}/.gitignore")
@@ -11,4 +11,13 @@ module Lita
11
11
  # An exception raised when Lita can't connect to Redis in test mode.
12
12
  # @since 4.0.3
13
13
  class RedisError < Error; end
14
+
15
+ # An exception raised when attempting to resolve a template that doesn't exist.
16
+ # @since 4.2.0
17
+ class MissingTemplateError < Error; end
18
+
19
+ # An exception raised when a handler attempts to render a template without having set its
20
+ # template root.
21
+ # @since 4.2.0
22
+ class MissingTemplateRootError < Error; end
14
23
  end
@@ -13,6 +13,20 @@ module Lita
13
13
 
14
14
  # Common class-level methods for all handlers.
15
15
  module ClassMethods
16
+ # Gets (and optionally sets) the directory where the handler's templates are stored.
17
+ # @param path [String] If provided, sets the template root to this value.
18
+ # @return [String] The template root path.
19
+ # @raise [MissingTemplateRootError] If accessed without setting a value first.
20
+ def template_root(path = nil)
21
+ @template_root = path if path
22
+
23
+ if defined?(@template_root)
24
+ return @template_root
25
+ else
26
+ raise MissingTemplateRootError
27
+ end
28
+ end
29
+
16
30
  # Returns the translation for a key, automatically namespaced to the handler.
17
31
  # @param key [String] The key of the translation.
18
32
  # @param hash [Hash] An optional hash of values to be interpolated in the string.
@@ -90,6 +104,10 @@ module Lita
90
104
  Lita.logger
91
105
  end
92
106
 
107
+ def render_template(template_name, variables = {})
108
+ Template.from_file(file_for_template(template_name)).render(variables)
109
+ end
110
+
93
111
  # @see .translate
94
112
  def translate(*args)
95
113
  self.class.translate(*args)
@@ -105,6 +123,14 @@ module Lita
105
123
  { headers: { "User-Agent" => "Lita v#{VERSION}" } }
106
124
  end
107
125
 
126
+ def file_for_template(template_name)
127
+ TemplateResolver.new(
128
+ self.class.template_root,
129
+ template_name,
130
+ robot.config.robot.adapter
131
+ ).resolve
132
+ end
133
+
108
134
  # The handler's namespace for Redis.
109
135
  def redis_namespace
110
136
  "handlers:#{self.class.namespace}"
@@ -0,0 +1,53 @@
1
+ module Lita
2
+ # A simple wrapper around ERB to render text from files or strings.
3
+ # @since 4.2.0
4
+ class Template
5
+ # A clean room object to use as the binding for ERB rendering.
6
+ # @api private
7
+ class TemplateEvaluationContext
8
+ # Returns the evaluation context's binding.
9
+ # @return [Binding] The binding.
10
+ def __get_binding
11
+ binding
12
+ end
13
+ end
14
+
15
+ class << self
16
+ # Initializes a new Template with the contents of the file at the given path.
17
+ # @param path [String] The path to the file to use as the template content.
18
+ # @return Template
19
+ def from_file(path)
20
+ new(File.read(path).chomp)
21
+ end
22
+ end
23
+
24
+ # @param source [String] A string to use as the template's content.
25
+ def initialize(source)
26
+ @erb = ERB.new(source, $SAFE, "<>")
27
+ end
28
+
29
+ # Render the template with the provided variables.
30
+ # @param variables [Hash] A collection of variables for interpolation. Each key-value pair will
31
+ # make the value available inside the template as an instance variable with the key as its
32
+ # name.
33
+ def render(variables = {})
34
+ erb.result(context_binding(variables))
35
+ end
36
+
37
+ private
38
+
39
+ # Create an empty object to use as the ERB context and set any provided variables in it.
40
+ def context_binding(variables)
41
+ context = TemplateEvaluationContext.new
42
+
43
+ variables.each do |k, v|
44
+ context.instance_variable_set("@#{k}", v)
45
+ end
46
+
47
+ context.__get_binding
48
+ end
49
+
50
+ # The underlying ERB object.
51
+ attr_reader :erb
52
+ end
53
+ end
@@ -0,0 +1,45 @@
1
+ module Lita
2
+ # Finds the file path of the most appropriate template for the given adapter.
3
+ # @api private
4
+ # @since 4.2.0
5
+ class TemplateResolver
6
+ # @param template_root [String] The directory to search for templates.
7
+ # @param template_name [String] The name of the template to search for.
8
+ # @param adapter_name [String, Symbol] The name of the current adapter.
9
+ def initialize(template_root, template_name, adapter_name)
10
+ @template_root = template_root
11
+ @template_name = template_name
12
+ @adapter_name = adapter_name
13
+ end
14
+
15
+ # Returns the adapter-specific template, falling back to a generic template.
16
+ # @return [String] The path of the template to use.
17
+ # @raises [MissingTemplateError] If no templates with the given name exist.
18
+ def resolve
19
+ return adapter_template if File.exist?(adapter_template)
20
+ return generic_template if File.exist?(generic_template)
21
+ raise MissingTemplateError, I18n.t("lita.template.missing_template", path: generic_template)
22
+ end
23
+
24
+ private
25
+
26
+ # The directory to search for templates.
27
+ attr_reader :template_root
28
+
29
+ # The name of the template to search for.
30
+ attr_reader :template_name
31
+
32
+ # The name of the current adapter.
33
+ attr_reader :adapter_name
34
+
35
+ # Path to the adapter-specific template.
36
+ def adapter_template
37
+ @adapter_template ||= File.join(template_root, "#{template_name}.#{adapter_name}.erb")
38
+ end
39
+
40
+ # Path to the generic template.
41
+ def generic_template
42
+ @generic_template ||= File.join(template_root, "#{template_name}.erb")
43
+ end
44
+ end
45
+ end
@@ -1,4 +1,4 @@
1
1
  module Lita
2
2
  # The current version of Lita.
3
- VERSION = "4.1.0"
3
+ VERSION = "4.2.0"
4
4
  end
@@ -171,6 +171,33 @@ describe Lita::Handler::Common, lita: true do
171
171
  end
172
172
  end
173
173
 
174
+ describe "#render_template" do
175
+ context "with the template root set" do
176
+ before do
177
+ handler.template_root(File.expand_path(File.join("..", "..", "..", "templates"), __FILE__))
178
+ end
179
+
180
+ it "renders the given template to a string" do
181
+ expect(subject.render_template("basic")).to eq("Template rendered from a file!")
182
+ end
183
+
184
+ it "interpolates variables into the rendered template" do
185
+ result = subject.render_template("interpolated", first: "Carl", last: "Pug")
186
+
187
+ expect(result).to eq("I love Carl Pug!")
188
+ end
189
+
190
+ it "renders adapter-specific templates if available" do
191
+ robot.config.robot.adapter = :irc
192
+ expect(subject.render_template("basic")).to eq("IRC template rendered from a file!")
193
+ end
194
+ end
195
+
196
+ it "raises an exception if the template root hasn't been set" do
197
+ expect { subject.render_template("basic") }.to raise_error(Lita::MissingTemplateRootError)
198
+ end
199
+ end
200
+
174
201
  describe "timer methods" do
175
202
  let(:queue) { Queue.new }
176
203
 
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe Lita::TemplateResolver do
4
+ subject do
5
+ described_class.new(template_root, template_name, adapter_name)
6
+ end
7
+
8
+ let(:adapter_name) { :shell }
9
+ let(:generic_template) { File.join(template_root, "basic.erb") }
10
+ let(:irc_template) { File.join(template_root, "basic.irc.erb") }
11
+ let(:template_name) { "basic" }
12
+ let(:template_root) { File.expand_path(File.join("..", "..", "templates"), __FILE__) }
13
+
14
+ describe "#resolve" do
15
+ context "when there is a template for the adapter" do
16
+ let(:adapter_name) { :irc }
17
+
18
+ it "returns the path to the adapter-specific template" do
19
+ expect(subject.resolve).to eq(irc_template)
20
+ end
21
+ end
22
+
23
+ context "when there is no template for the adapter" do
24
+ it "returns the path for the generic template" do
25
+ expect(subject.resolve).to eq(generic_template)
26
+ end
27
+ end
28
+
29
+ context "when there is no template with the given name" do
30
+ let(:template_name) { "nonexistent" }
31
+
32
+ it "raises an exception" do
33
+ expect { subject.resolve }.to raise_error(
34
+ Lita::MissingTemplateError,
35
+ %r{templates/nonexistent\.erb}
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe Lita::Template do
4
+ describe ".from_file" do
5
+ context "with a path to an ERB template" do
6
+ subject do
7
+ described_class.from_file(File.expand_path("../../templates/basic.erb", __FILE__))
8
+ end
9
+
10
+ it "uses the source in the file" do
11
+ expect(subject.render).to eq("Template rendered from a file!")
12
+ end
13
+ end
14
+ end
15
+
16
+ describe "#render" do
17
+ context "with a static source template" do
18
+ subject { described_class.new("Hello, Lita!") }
19
+
20
+ it "renders the text" do
21
+ expect(subject.render).to eq("Hello, Lita!")
22
+ end
23
+ end
24
+
25
+ context "with interpolation variables" do
26
+ subject { described_class.new("Hello, <%= @name %>!") }
27
+
28
+ it "renders the text with interpolated values" do
29
+ expect(subject.render(name: "Carl")).to eq("Hello, Carl!")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1 @@
1
+ Template rendered from a file!
@@ -0,0 +1 @@
1
+ IRC template rendered from a file!
@@ -0,0 +1 @@
1
+ I love <%= @first %> <%= @last %>!
@@ -152,3 +152,5 @@ en:
152
152
  `%{old_method}` is deprecated and will be removed in Lita 5.0. Use `%{new_method}` instead.
153
153
  source:
154
154
  user_or_room_required: Either a user or a room is required.
155
+ template:
156
+ missing_template: Missing template file at %{path}.
@@ -18,7 +18,7 @@ gem "<%= config[:gem_name] %>"
18
18
  ```
19
19
  <%- end -%>
20
20
 
21
- <%- unless config[:plugin_type] == "extension" %>
21
+ <%- unless config[:plugin_type] == "extension" -%>
22
22
  ## Configuration
23
23
 
24
24
  TODO: Describe any configuration attributes the plugin exposes.
@@ -5,3 +5,10 @@ Lita.load_locales Dir[File.expand_path(
5
5
  )]
6
6
 
7
7
  require "lita/<%= config[:namespace] %>/<%= config[:name] %>"
8
+ <%- if config[:plugin_type] == "handler" -%>
9
+
10
+ Lita::<%= config[:constant_namespace] %>::<%= config[:constant_name] %>.template_root File.expand_path(
11
+ File.join("..", "..", "templates"),
12
+ __FILE__
13
+ )
14
+ <%- end -%>
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmy Cuadra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-11 00:00:00.000000000 Z
11
+ date: 2015-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -323,6 +323,8 @@ files:
323
323
  - lib/lita/rspec/matchers/event_route_matcher.rb
324
324
  - lib/lita/rspec/matchers/http_route_matcher.rb
325
325
  - lib/lita/source.rb
326
+ - lib/lita/template.rb
327
+ - lib/lita/template_resolver.rb
326
328
  - lib/lita/timer.rb
327
329
  - lib/lita/user.rb
328
330
  - lib/lita/util.rb
@@ -354,11 +356,16 @@ files:
354
356
  - spec/lita/robot_spec.rb
355
357
  - spec/lita/rspec_spec.rb
356
358
  - spec/lita/source_spec.rb
359
+ - spec/lita/template_resolver_spec.rb
360
+ - spec/lita/template_spec.rb
357
361
  - spec/lita/timer_spec.rb
358
362
  - spec/lita/user_spec.rb
359
363
  - spec/lita/util_spec.rb
360
364
  - spec/lita_spec.rb
361
365
  - spec/spec_helper.rb
366
+ - spec/templates/basic.erb
367
+ - spec/templates/basic.irc.erb
368
+ - spec/templates/interpolated.erb
362
369
  - templates/locales/en.yml
363
370
  - templates/plugin/Gemfile
364
371
  - templates/plugin/LICENSE.tt
@@ -371,6 +378,7 @@ files:
371
378
  - templates/plugin/locales/en.yml.tt
372
379
  - templates/plugin/spec/lita/plugin_type/plugin_spec.tt
373
380
  - templates/plugin/spec/spec_helper.tt
381
+ - templates/plugin/templates/gitkeep
374
382
  - templates/plugin/travis.yml
375
383
  - templates/robot/Gemfile
376
384
  - templates/robot/lita_config.rb
@@ -425,8 +433,14 @@ test_files:
425
433
  - spec/lita/robot_spec.rb
426
434
  - spec/lita/rspec_spec.rb
427
435
  - spec/lita/source_spec.rb
436
+ - spec/lita/template_resolver_spec.rb
437
+ - spec/lita/template_spec.rb
428
438
  - spec/lita/timer_spec.rb
429
439
  - spec/lita/user_spec.rb
430
440
  - spec/lita/util_spec.rb
431
441
  - spec/lita_spec.rb
432
442
  - spec/spec_helper.rb
443
+ - spec/templates/basic.erb
444
+ - spec/templates/basic.irc.erb
445
+ - spec/templates/interpolated.erb
446
+ has_rdoc: