nulogy-poirot 0.2.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in poirot.gemspec
4
+ gemspec
5
+ gem 'rails', '>=3.0.0'
6
+ gem 'mustache'
@@ -0,0 +1,83 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ nulogy-poirot (0.2.4.1)
5
+ mustache
6
+ railties (> 3)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ abstract (1.0.0)
12
+ actionmailer (3.0.9)
13
+ actionpack (= 3.0.9)
14
+ mail (~> 2.2.19)
15
+ actionpack (3.0.9)
16
+ activemodel (= 3.0.9)
17
+ activesupport (= 3.0.9)
18
+ builder (~> 2.1.2)
19
+ erubis (~> 2.6.6)
20
+ i18n (~> 0.5.0)
21
+ rack (~> 1.2.1)
22
+ rack-mount (~> 0.6.14)
23
+ rack-test (~> 0.5.7)
24
+ tzinfo (~> 0.3.23)
25
+ activemodel (3.0.9)
26
+ activesupport (= 3.0.9)
27
+ builder (~> 2.1.2)
28
+ i18n (~> 0.5.0)
29
+ activerecord (3.0.9)
30
+ activemodel (= 3.0.9)
31
+ activesupport (= 3.0.9)
32
+ arel (~> 2.0.10)
33
+ tzinfo (~> 0.3.23)
34
+ activeresource (3.0.9)
35
+ activemodel (= 3.0.9)
36
+ activesupport (= 3.0.9)
37
+ activesupport (3.0.9)
38
+ arel (2.0.10)
39
+ builder (2.1.2)
40
+ erubis (2.6.6)
41
+ abstract (>= 1.0.0)
42
+ i18n (0.5.0)
43
+ mail (2.2.19)
44
+ activesupport (>= 2.3.6)
45
+ i18n (>= 0.4.0)
46
+ mime-types (~> 1.16)
47
+ treetop (~> 1.4.8)
48
+ mime-types (1.16)
49
+ mustache (0.99.4)
50
+ polyglot (0.3.1)
51
+ rack (1.2.3)
52
+ rack-mount (0.6.14)
53
+ rack (>= 1.0.0)
54
+ rack-test (0.5.7)
55
+ rack (>= 1.0)
56
+ rails (3.0.9)
57
+ actionmailer (= 3.0.9)
58
+ actionpack (= 3.0.9)
59
+ activerecord (= 3.0.9)
60
+ activeresource (= 3.0.9)
61
+ activesupport (= 3.0.9)
62
+ bundler (~> 1.0)
63
+ railties (= 3.0.9)
64
+ railties (3.0.9)
65
+ actionpack (= 3.0.9)
66
+ activesupport (= 3.0.9)
67
+ rake (>= 0.8.7)
68
+ rdoc (~> 3.4)
69
+ thor (~> 0.14.4)
70
+ rake (0.9.2)
71
+ rdoc (3.8)
72
+ thor (0.14.6)
73
+ treetop (1.4.9)
74
+ polyglot (>= 0.3.1)
75
+ tzinfo (0.3.29)
76
+
77
+ PLATFORMS
78
+ ruby
79
+
80
+ DEPENDENCIES
81
+ mustache
82
+ nulogy-poirot!
83
+ rails (>= 3.0.0)
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,84 @@
1
+ # Poirot
2
+
3
+ ## Description
4
+
5
+ Allows you to use [Mustache](http://mustache.github.com/) template partials in Rails, also
6
+ ads a helper method to easily allow JavaScript to re-use the same templates.
7
+
8
+ ## Usage
9
+
10
+ Create a partial just like you would with erb, prefixing the name with an underscore.
11
+
12
+ app/views/posts/_post_list.html.mustache
13
+
14
+ The template will have access to all normal rails helper methods and any instance variables
15
+ that were set in the controller. If you need more than this an optional view class can be
16
+ included, it should have the same name as the partial, but without the underscore.
17
+
18
+ app/views/posts/post_list_view.rb
19
+
20
+ module Posts
21
+ class PostListView < Poirot::View
22
+ def foo
23
+ "bar"
24
+ end
25
+
26
+ def post_link
27
+ post_path(post)
28
+ end
29
+ end
30
+ end
31
+
32
+ The view class has access to all the normal Rails helpers and access to the controller
33
+ instance variables, e.g @post becomes the method post.
34
+
35
+ Also included is a simple view helper for including mustache templates in a page ready for
36
+ use by JavaScript.
37
+
38
+ <%= template_include_tag 'post_list' %>
39
+
40
+ The above will insert a script tag with the contents of the partial called `post_list`, the
41
+ type will be set as `text/mustache` and the id will be `post-list-template`.
42
+
43
+ <script id="post-list-template" type="text/mustache">
44
+ <!-- template will be here! -->
45
+ </script>
46
+
47
+ ### Javascript Helper
48
+
49
+ Poirot also adds a javascript helper for using mustache templates from the browser. In Rails 3.1 this will be automatically added to the asset pipeline, you just need to add `//= require poirot` in your application.js file.
50
+
51
+ If you are using rails 3 then you can run the `rails g poirot:install` to install the javascripts in your application.
52
+
53
+ Using the poirot javascript helper is simple, given a template added to the page using `template_include_tag`
54
+
55
+ <%= template_include_tag 'post_list' %>
56
+
57
+ You can render this template from javascript by doing the following
58
+
59
+ poirot.postList()
60
+
61
+ This will return the contents of the `post_list` template wrapped in a jQuery object, ready for inserting into the dom. If you have data to pass to the template then you can pass it as the argument to the function, e.g.
62
+
63
+ poirot.postList({foo: "bar"})
64
+
65
+ #### Using Handlebars.js
66
+
67
+ It is possible to use handlebars instead of mustache when rendering templates client side. To do this you need to first include the handlebars.js source. The instead of including `//= require poirot` in the asset pipeline you should include `//= require poirot-handlebars`
68
+
69
+ #### Using Hogan.js
70
+
71
+ It is also possible to use hogan.js instead of mustache when rendering templates client side. To do this you need to first include the hogan.js source. The instead of including `//= require poirot` in the asset pipeline you should include `//= require poirot-hogan`
72
+
73
+ ## Dependencies
74
+
75
+ * Rails >3.0.0
76
+ * Mustache
77
+
78
+ ## More
79
+
80
+ An [example](http://github.com/olivernn/notepad) app using Poirot
81
+
82
+ ## Credits
83
+
84
+ [Mark Evans](http://github.com/markevans) & [Oliver Nightingale](http://github.com/olivernn)
@@ -0,0 +1,31 @@
1
+ require 'rails'
2
+
3
+ module Poirot
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+
7
+ desc "This generator installs Poirot JavaScript helper"
8
+ source_root File.expand_path('../../../../../vendor/assets/javascripts', __FILE__)
9
+
10
+ def copy_mustache
11
+ say_status("copying", "Mustache.js", :green)
12
+ copy_file "poirot-mustache/mustache.js", "public/javascripts/mustache.js"
13
+ end
14
+
15
+ def copy_poirot
16
+ say_status("copying", "poirot.js", :green)
17
+ copy_file "poirot-base/poirot.js", "public/javascripts/poirot.js"
18
+ end
19
+
20
+ def copy_poirot_handlebars
21
+ say_status("copying", "poirot-handlebars.js", :green)
22
+ copy_file "poirot-handlebars/poirot-handlebars.js", "public/javascripts/poirot-handlebars.js"
23
+ end
24
+
25
+ def copy_poirot_hogan
26
+ say_status("copying", "poirot-hogan.js", :green)
27
+ copy_file "poirot-hogan/poirot-hogan.js", "public/javascripts/poirot-hogan.js"
28
+ end
29
+ end
30
+ end
31
+ end if ::Rails.version < "3.1"
@@ -0,0 +1,17 @@
1
+ require 'mustache'
2
+ require 'poirot/handler'
3
+ require 'poirot/view_helper'
4
+ require 'poirot/view'
5
+ require 'poirot/asset_helper'
6
+
7
+ ActionView::Template.register_template_handler(:mustache, Poirot::Handler)
8
+ ActionView::Base.send :include, Poirot::AssetHelper
9
+
10
+ module Poirot
11
+ class Engine < Rails::Engine ; end if Rails.version >= "3.1"
12
+ class Railtie < Rails::Railtie
13
+ config.before_configuration do |app|
14
+ app.config.autoload_paths += %W(#{app.config.root}/app/views)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ module Poirot
2
+ module AssetHelper
3
+ def template_include_tag(*sources)
4
+ sources.collect do |source|
5
+ template = File.open(resolve_partial_path(source), "rb")
6
+ content_tag :script, template.read.html_safe, :type => "text/mustache", :id => "#{template_name(source).parameterize.dasherize}-template"
7
+ end.join("\n").html_safe
8
+ end
9
+
10
+ private
11
+
12
+ def is_absolute_path?(source)
13
+ source.to_s =~ /^\//
14
+ end
15
+
16
+ def template_name(source)
17
+ if is_absolute_path?(source)
18
+ source.to_s.split('/').last
19
+ else
20
+ source
21
+ end
22
+ end
23
+
24
+ def resolve_partial_path(source)
25
+ if is_absolute_path?(source)
26
+ segments = source.to_s.split('/')
27
+ partial_name = "_#{segments.pop}.html.mustache"
28
+ segments << partial_name
29
+ Rails.root.join('app/views', *segments)
30
+ else
31
+ Rails.root.join('app/views', controller_name, "_#{source}.html.mustache")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ module Poirot
2
+ class Handler
3
+ def self.call(template)
4
+ view_path = "#{template.virtual_path}_view"
5
+ abs_view_path = Rails.root.join('app/views', view_path)
6
+ view_class = begin
7
+ view_path.classify.constantize
8
+ rescue NameError => e
9
+ Rails.logger.info ">>> #{e}"
10
+ Poirot::View
11
+ end
12
+ "#{view_class}.new(self, '#{template.source.gsub(/'/, "\\\\'")}').render.html_safe"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ module Poirot
2
+ VERSION = "0.2.4.1"
3
+ end
@@ -0,0 +1,76 @@
1
+ module Poirot
2
+ class View < Mustache
3
+
4
+ include Poirot::ViewHelper
5
+
6
+ def initialize(view_context, template_source)
7
+ @view_context = view_context
8
+ @params = view_context.params || {}
9
+ self.template = template_source
10
+ assign_variables!
11
+ end
12
+
13
+ self.template_extension = 'html.mustache'
14
+
15
+ def self.inherited(view_class)
16
+ self.template_path = Rails.root.join('app', 'views', view_class.name.split('::').first.downcase)
17
+ end
18
+
19
+ def respond_to?(method_sym, include_private = false)
20
+ if view_context.respond_to?(method_sym)
21
+ true
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def render_buffer(buffer)
28
+ self.render(buffer, context).html_safe
29
+ end
30
+
31
+ def include_partial(name)
32
+ path = ["app/views", controller_name]
33
+ path += name.split("/")
34
+ path.delete(nil)
35
+ path.last.replace("_#{path.last}.html.mustache")
36
+
37
+ filename = path.join("/")
38
+
39
+ Dir.chdir(Rails.root) do
40
+ render_buffer(File.read(filename))
41
+ end
42
+ end
43
+
44
+ def method_missing(method_name, *args, &block)
45
+ if instance_variable_names.include?("@#{method_name}") && args.empty?
46
+ instance_variable_get("@#{method_name}")
47
+ else
48
+ view_context.send(method_name,*args, &block)
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ attr_reader :view_context
55
+ attr_reader :params
56
+
57
+ def assign_variables!
58
+ variables = view_context.instance_variable_names.select{|name| name =~ /^@[^_]/}
59
+ variables.each do |name|
60
+ instance_var = view_context.instance_variable_get(name)
61
+ instance_variable_set(name, instance_var)
62
+ self[name.tr('@','').to_sym] = instance_var
63
+ end
64
+
65
+ if Rails.version >= "3.1"
66
+ # get the locals from the view context, is there a better way?
67
+ locals = view_context.send(:view_renderer).send(:_partial_renderer).instance_variable_get("@locals") || {}
68
+
69
+ locals.each do |name, val|
70
+ instance_variable_set("@#{name}", val)
71
+ self[name] = val
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,7 @@
1
+ module Poirot
2
+ module ViewHelper
3
+ def csrf_token
4
+ tag(:input, :name => 'authenticity_token', :type => 'hidden', :value => form_authenticity_token)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "poirot/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nulogy-poirot"
7
+ s.version = Poirot::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Oliver Nightingale", "Mark Evans"]
10
+ s.email = ["oliver.nightingale1@gmail.com"]
11
+ s.homepage = "http://rubygems.org/gems/poirot"
12
+ s.summary = %q{mustache support for rails}
13
+ s.description = %q{mustaches are cool}
14
+
15
+ s.add_dependency('railties', '>3')
16
+ s.add_dependency('mustache')
17
+
18
+ s.rubyforge_project = "poirot"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
@@ -0,0 +1 @@
1
+ //= require ./poirot
@@ -0,0 +1,28 @@
1
+ var poirot = (function ($) {
2
+
3
+ var viewFactory = function (template, partials) {
4
+ return function (data) {
5
+ return $(Mustache.to_html(template, data, partials))
6
+ }
7
+ }
8
+
9
+ var poirot = {
10
+ _partials: {},
11
+ _viewFactory: viewFactory
12
+ }
13
+
14
+ $(document).ready(function () {
15
+ $('script[type="text/mustache"]').each(function () {
16
+ var template = $(this).html()
17
+ var methodName = this.id.replace(/-([a-z])/g, function (str) {
18
+ return str.replace("-", "").toUpperCase()
19
+ }).replace("Template", "")
20
+
21
+ poirot._partials[methodName] = template
22
+
23
+ poirot[methodName] = poirot._viewFactory(template, poirot._partials)
24
+ })
25
+ })
26
+
27
+ return poirot
28
+ })(jQuery)
@@ -0,0 +1,2 @@
1
+ //= require poirot-base
2
+ //= require ./poirot-handlebars
@@ -0,0 +1,8 @@
1
+ ;(function () {
2
+ poirot._viewFactory = function (template, partials) {
3
+ var compiledTemplate = Handlebars.compile(template)
4
+ return function (data) {
5
+ return $(compiledTemplate(data))
6
+ }
7
+ }
8
+ })()
@@ -0,0 +1,2 @@
1
+ //= require poirot-base
2
+ //= require ./poirot-hogan
@@ -0,0 +1,8 @@
1
+ ;(function () {
2
+ poirot._viewFactory = function (template, partials) {
3
+ var compiledTemplate = Hogan.compile(template)
4
+ return function (data) {
5
+ return $(compiledTemplate.render(data, partials))
6
+ }
7
+ }
8
+ })()
@@ -0,0 +1 @@
1
+ //= require ./mustache
@@ -0,0 +1,536 @@
1
+ /*!
2
+ * mustache.js - Logic-less {{mustache}} templates with JavaScript
3
+ * http://github.com/janl/mustache.js
4
+ */
5
+ var Mustache = (typeof module !== "undefined" && module.exports) || {};
6
+
7
+ (function (exports) {
8
+
9
+ exports.name = "mustache.js";
10
+ exports.version = "0.5.0-dev";
11
+ exports.tags = ["{{", "}}"];
12
+ exports.parse = parse;
13
+ exports.compile = compile;
14
+ exports.render = render;
15
+ exports.clearCache = clearCache;
16
+
17
+ // This is here for backwards compatibility with 0.4.x.
18
+ exports.to_html = function (template, view, partials, send) {
19
+ var result = render(template, view, partials);
20
+
21
+ if (typeof send === "function") {
22
+ send(result);
23
+ } else {
24
+ return result;
25
+ }
26
+ };
27
+
28
+ var _toString = Object.prototype.toString;
29
+ var _isArray = Array.isArray;
30
+ var _forEach = Array.prototype.forEach;
31
+ var _trim = String.prototype.trim;
32
+
33
+ var isArray;
34
+ if (_isArray) {
35
+ isArray = _isArray;
36
+ } else {
37
+ isArray = function (obj) {
38
+ return _toString.call(obj) === "[object Array]";
39
+ };
40
+ }
41
+
42
+ var forEach;
43
+ if (_forEach) {
44
+ forEach = function (obj, callback, scope) {
45
+ return _forEach.call(obj, callback, scope);
46
+ };
47
+ } else {
48
+ forEach = function (obj, callback, scope) {
49
+ for (var i = 0, len = obj.length; i < len; ++i) {
50
+ callback.call(scope, obj[i], i, obj);
51
+ }
52
+ };
53
+ }
54
+
55
+ var spaceRe = /^\s*$/;
56
+
57
+ function isWhitespace(string) {
58
+ return spaceRe.test(string);
59
+ }
60
+
61
+ var trim;
62
+ if (_trim) {
63
+ trim = function (string) {
64
+ return string == null ? "" : _trim.call(string);
65
+ };
66
+ } else {
67
+ var trimLeft, trimRight;
68
+
69
+ if (isWhitespace("\xA0")) {
70
+ trimLeft = /^\s+/;
71
+ trimRight = /\s+$/;
72
+ } else {
73
+ // IE doesn't match non-breaking spaces with \s, thanks jQuery.
74
+ trimLeft = /^[\s\xA0]+/;
75
+ trimRight = /[\s\xA0]+$/;
76
+ }
77
+
78
+ trim = function (string) {
79
+ return string == null ? "" :
80
+ String(string).replace(trimLeft, "").replace(trimRight, "");
81
+ };
82
+ }
83
+
84
+ var escapeMap = {
85
+ "&": "&amp;",
86
+ "<": "&lt;",
87
+ ">": "&gt;",
88
+ '"': '&quot;',
89
+ "'": '&#39;'
90
+ };
91
+
92
+ function escapeHTML(string) {
93
+ return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
94
+ return escapeMap[s] || s;
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Adds the `template`, `line`, and `file` properties to the given error
100
+ * object and alters the message to provide more useful debugging information.
101
+ */
102
+ function debug(e, template, line, file) {
103
+ file = file || "<template>";
104
+
105
+ var lines = template.split("\n"),
106
+ start = Math.max(line - 3, 0),
107
+ end = Math.min(lines.length, line + 3),
108
+ context = lines.slice(start, end);
109
+
110
+ var c;
111
+ for (var i = 0, len = context.length; i < len; ++i) {
112
+ c = i + start + 1;
113
+ context[i] = (c === line ? " >> " : " ") + context[i];
114
+ }
115
+
116
+ e.template = template;
117
+ e.line = line;
118
+ e.file = file;
119
+ e.message = [file + ":" + line, context.join("\n"), "", e.message].join("\n");
120
+
121
+ return e;
122
+ }
123
+
124
+ /**
125
+ * Looks up the value of the given `name` in the given context `stack`.
126
+ */
127
+ function lookup(name, stack, defaultValue) {
128
+ if (name === ".") {
129
+ return stack[stack.length - 1];
130
+ }
131
+
132
+ var names = name.split(".");
133
+ var lastIndex = names.length - 1;
134
+ var target = names[lastIndex];
135
+
136
+ var value, context, i = stack.length, j, localStack;
137
+ while (i) {
138
+ localStack = stack.slice(0);
139
+ context = stack[--i];
140
+
141
+ j = 0;
142
+ while (j < lastIndex) {
143
+ context = context[names[j++]];
144
+
145
+ if (context == null) {
146
+ break;
147
+ }
148
+
149
+ localStack.push(context);
150
+ }
151
+
152
+ if (context && typeof context === "object" && target in context) {
153
+ value = context[target];
154
+ break;
155
+ }
156
+ }
157
+
158
+ // If the value is a function, call it in the current context.
159
+ if (typeof value === "function") {
160
+ value = value.call(localStack[localStack.length - 1]);
161
+ }
162
+
163
+ if (value == null) {
164
+ return defaultValue;
165
+ }
166
+
167
+ return value;
168
+ }
169
+
170
+ function renderSection(name, stack, callback, inverted) {
171
+ var buffer = "";
172
+ var value = lookup(name, stack);
173
+
174
+ if (inverted) {
175
+ // From the spec: inverted sections may render text once based on the
176
+ // inverse value of the key. That is, they will be rendered if the key
177
+ // doesn't exist, is false, or is an empty list.
178
+ if (value == null || value === false || (isArray(value) && value.length === 0)) {
179
+ buffer += callback();
180
+ }
181
+ } else if (isArray(value)) {
182
+ forEach(value, function (value) {
183
+ stack.push(value);
184
+ buffer += callback();
185
+ stack.pop();
186
+ });
187
+ } else if (typeof value === "object") {
188
+ stack.push(value);
189
+ buffer += callback();
190
+ stack.pop();
191
+ } else if (typeof value === "function") {
192
+ var scope = stack[stack.length - 1];
193
+ var scopedRender = function (template) {
194
+ return render(template, scope);
195
+ };
196
+ buffer += value.call(scope, callback(), scopedRender) || "";
197
+ } else if (value) {
198
+ buffer += callback();
199
+ }
200
+
201
+ return buffer;
202
+ }
203
+
204
+ /**
205
+ * Parses the given `template` and returns the source of a function that,
206
+ * with the proper arguments, will render the template. Recognized options
207
+ * include the following:
208
+ *
209
+ * - file The name of the file the template comes from (displayed in
210
+ * error messages)
211
+ * - tags An array of open and close tags the `template` uses. Defaults
212
+ * to the value of Mustache.tags
213
+ * - debug Set `true` to log the body of the generated function to the
214
+ * console
215
+ * - space Set `true` to preserve whitespace from lines that otherwise
216
+ * contain only a {{tag}}. Defaults to `false`
217
+ */
218
+ function parse(template, options) {
219
+ options = options || {};
220
+
221
+ var tags = options.tags || exports.tags,
222
+ openTag = tags[0],
223
+ closeTag = tags[tags.length - 1];
224
+
225
+ var code = [
226
+ 'var buffer = "";', // output buffer
227
+ "\nvar line = 1;", // keep track of source line number
228
+ "\ntry {",
229
+ '\nbuffer += "'
230
+ ];
231
+
232
+ var spaces = [], // indices of whitespace in code on the current line
233
+ hasTag = false, // is there a {{tag}} on the current line?
234
+ nonSpace = false; // is there a non-space char on the current line?
235
+
236
+ // Strips all space characters from the code array for the current line
237
+ // if there was a {{tag}} on it and otherwise only spaces.
238
+ var stripSpace = function () {
239
+ if (hasTag && !nonSpace && !options.space) {
240
+ while (spaces.length) {
241
+ code.splice(spaces.pop(), 1);
242
+ }
243
+ } else {
244
+ spaces = [];
245
+ }
246
+
247
+ hasTag = false;
248
+ nonSpace = false;
249
+ };
250
+
251
+ var sectionStack = [], updateLine, nextOpenTag, nextCloseTag;
252
+
253
+ var setTags = function (source) {
254
+ tags = trim(source).split(/\s+/);
255
+ nextOpenTag = tags[0];
256
+ nextCloseTag = tags[tags.length - 1];
257
+ };
258
+
259
+ var includePartial = function (source) {
260
+ code.push(
261
+ '";',
262
+ updateLine,
263
+ '\nvar partial = partials["' + trim(source) + '"];',
264
+ '\nif (partial) {',
265
+ '\n buffer += render(partial,stack[stack.length - 1],partials);',
266
+ '\n}',
267
+ '\nbuffer += "'
268
+ );
269
+ };
270
+
271
+ var openSection = function (source, inverted) {
272
+ var name = trim(source);
273
+
274
+ if (name === "") {
275
+ throw debug(new Error("Section name may not be empty"), template, line, options.file);
276
+ }
277
+
278
+ sectionStack.push({name: name, inverted: inverted});
279
+
280
+ code.push(
281
+ '";',
282
+ updateLine,
283
+ '\nvar name = "' + name + '";',
284
+ '\nvar callback = (function () {',
285
+ '\n return function () {',
286
+ '\n var buffer = "";',
287
+ '\nbuffer += "'
288
+ );
289
+ };
290
+
291
+ var openInvertedSection = function (source) {
292
+ openSection(source, true);
293
+ };
294
+
295
+ var closeSection = function (source) {
296
+ var name = trim(source);
297
+ var openName = sectionStack.length != 0 && sectionStack[sectionStack.length - 1].name;
298
+
299
+ if (!openName || name != openName) {
300
+ throw debug(new Error('Section named "' + name + '" was never opened'), template, line, options.file);
301
+ }
302
+
303
+ var section = sectionStack.pop();
304
+
305
+ code.push(
306
+ '";',
307
+ '\n return buffer;',
308
+ '\n };',
309
+ '\n})();'
310
+ );
311
+
312
+ if (section.inverted) {
313
+ code.push("\nbuffer += renderSection(name,stack,callback,true);");
314
+ } else {
315
+ code.push("\nbuffer += renderSection(name,stack,callback);");
316
+ }
317
+
318
+ code.push('\nbuffer += "');
319
+ };
320
+
321
+ var sendPlain = function (source) {
322
+ code.push(
323
+ '";',
324
+ updateLine,
325
+ '\nbuffer += lookup("' + trim(source) + '",stack,"");',
326
+ '\nbuffer += "'
327
+ );
328
+ };
329
+
330
+ var sendEscaped = function (source) {
331
+ code.push(
332
+ '";',
333
+ updateLine,
334
+ '\nbuffer += escapeHTML(lookup("' + trim(source) + '",stack,""));',
335
+ '\nbuffer += "'
336
+ );
337
+ };
338
+
339
+ var line = 1, c, callback;
340
+ for (var i = 0, len = template.length; i < len; ++i) {
341
+ if (template.slice(i, i + openTag.length) === openTag) {
342
+ i += openTag.length;
343
+ c = template.substr(i, 1);
344
+ updateLine = '\nline = ' + line + ';';
345
+ nextOpenTag = openTag;
346
+ nextCloseTag = closeTag;
347
+ hasTag = true;
348
+
349
+ switch (c) {
350
+ case "!": // comment
351
+ i++;
352
+ callback = null;
353
+ break;
354
+ case "=": // change open/close tags, e.g. {{=<% %>=}}
355
+ i++;
356
+ closeTag = "=" + closeTag;
357
+ callback = setTags;
358
+ break;
359
+ case ">": // include partial
360
+ i++;
361
+ callback = includePartial;
362
+ break;
363
+ case "#": // start section
364
+ i++;
365
+ callback = openSection;
366
+ break;
367
+ case "^": // start inverted section
368
+ i++;
369
+ callback = openInvertedSection;
370
+ break;
371
+ case "/": // end section
372
+ i++;
373
+ callback = closeSection;
374
+ break;
375
+ case "{": // plain variable
376
+ closeTag = "}" + closeTag;
377
+ // fall through
378
+ case "&": // plain variable
379
+ i++;
380
+ nonSpace = true;
381
+ callback = sendPlain;
382
+ break;
383
+ default: // escaped variable
384
+ nonSpace = true;
385
+ callback = sendEscaped;
386
+ }
387
+
388
+ var end = template.indexOf(closeTag, i);
389
+
390
+ if (end === -1) {
391
+ throw debug(new Error('Tag "' + openTag + '" was not closed properly'), template, line, options.file);
392
+ }
393
+
394
+ var source = template.substring(i, end);
395
+
396
+ if (callback) {
397
+ callback(source);
398
+ }
399
+
400
+ // Maintain line count for \n in source.
401
+ var n = 0;
402
+ while (~(n = source.indexOf("\n", n))) {
403
+ line++;
404
+ n++;
405
+ }
406
+
407
+ i = end + closeTag.length - 1;
408
+ openTag = nextOpenTag;
409
+ closeTag = nextCloseTag;
410
+ } else {
411
+ c = template.substr(i, 1);
412
+
413
+ switch (c) {
414
+ case '"':
415
+ case "\\":
416
+ nonSpace = true;
417
+ code.push("\\" + c);
418
+ break;
419
+ case "\r":
420
+ // Ignore carriage returns.
421
+ break;
422
+ case "\n":
423
+ spaces.push(code.length);
424
+ code.push("\\n");
425
+ stripSpace(); // Check for whitespace on the current line.
426
+ line++;
427
+ break;
428
+ default:
429
+ if (isWhitespace(c)) {
430
+ spaces.push(code.length);
431
+ } else {
432
+ nonSpace = true;
433
+ }
434
+
435
+ code.push(c);
436
+ }
437
+ }
438
+ }
439
+
440
+ if (sectionStack.length != 0) {
441
+ throw debug(new Error('Section "' + sectionStack[sectionStack.length - 1].name + '" was not closed properly'), template, line, options.file);
442
+ }
443
+
444
+ // Clean up any whitespace from a closing {{tag}} that was at the end
445
+ // of the template without a trailing \n.
446
+ stripSpace();
447
+
448
+ code.push(
449
+ '";',
450
+ "\nreturn buffer;",
451
+ "\n} catch (e) { throw {error: e, line: line}; }"
452
+ );
453
+
454
+ // Ignore `buffer += "";` statements.
455
+ var body = code.join("").replace(/buffer \+= "";\n/g, "");
456
+
457
+ if (options.debug) {
458
+ if (typeof console != "undefined" && console.log) {
459
+ console.log(body);
460
+ } else if (typeof print === "function") {
461
+ print(body);
462
+ }
463
+ }
464
+
465
+ return body;
466
+ }
467
+
468
+ /**
469
+ * Used by `compile` to generate a reusable function for the given `template`.
470
+ */
471
+ function _compile(template, options) {
472
+ var args = "view,partials,stack,lookup,escapeHTML,renderSection,render";
473
+ var body = parse(template, options);
474
+ var fn = new Function(args, body);
475
+
476
+ // This anonymous function wraps the generated function so we can do
477
+ // argument coercion, setup some variables, and handle any errors
478
+ // encountered while executing it.
479
+ return function (view, partials) {
480
+ partials = partials || {};
481
+
482
+ var stack = [view]; // context stack
483
+
484
+ try {
485
+ return fn(view, partials, stack, lookup, escapeHTML, renderSection, render);
486
+ } catch (e) {
487
+ throw debug(e.error, template, e.line, options.file);
488
+ }
489
+ };
490
+ }
491
+
492
+ // Cache of pre-compiled templates.
493
+ var _cache = {};
494
+
495
+ /**
496
+ * Clear the cache of compiled templates.
497
+ */
498
+ function clearCache() {
499
+ _cache = {};
500
+ }
501
+
502
+ /**
503
+ * Compiles the given `template` into a reusable function using the given
504
+ * `options`. In addition to the options accepted by Mustache.parse,
505
+ * recognized options include the following:
506
+ *
507
+ * - cache Set `false` to bypass any pre-compiled version of the given
508
+ * template. Otherwise, a given `template` string will be cached
509
+ * the first time it is parsed
510
+ */
511
+ function compile(template, options) {
512
+ options = options || {};
513
+
514
+ // Use a pre-compiled version from the cache if we have one.
515
+ if (options.cache !== false) {
516
+ if (!_cache[template]) {
517
+ _cache[template] = _compile(template, options);
518
+ }
519
+
520
+ return _cache[template];
521
+ }
522
+
523
+ return _compile(template, options);
524
+ }
525
+
526
+ /**
527
+ * High-level function that renders the given `template` using the given
528
+ * `view` and `partials`. If you need to use any of the template options (see
529
+ * `compile` above), you must compile in a separate step, and then call that
530
+ * compiled function.
531
+ */
532
+ function render(template, view, partials) {
533
+ return compile(template)(view, partials);
534
+ }
535
+
536
+ })(Mustache);
@@ -0,0 +1,2 @@
1
+ //= require poirot-base
2
+ //= require poirot-mustache
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nulogy-poirot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Oliver Nightingale
9
+ - Mark Evans
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-10-01 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>'
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>'
29
+ - !ruby/object:Gem::Version
30
+ version: '3'
31
+ - !ruby/object:Gem::Dependency
32
+ name: mustache
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: mustaches are cool
48
+ email:
49
+ - oliver.nightingale1@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - Gemfile.lock
57
+ - Rakefile
58
+ - Readme.markdown
59
+ - lib/generators/poirot/install/install_generator.rb
60
+ - lib/poirot.rb
61
+ - lib/poirot/asset_helper.rb
62
+ - lib/poirot/handler.rb
63
+ - lib/poirot/version.rb
64
+ - lib/poirot/view.rb
65
+ - lib/poirot/view_helper.rb
66
+ - poirot.gemspec
67
+ - vendor/assets/javascripts/poirot-base/index.js
68
+ - vendor/assets/javascripts/poirot-base/poirot.js
69
+ - vendor/assets/javascripts/poirot-handlebars/index.js
70
+ - vendor/assets/javascripts/poirot-handlebars/poirot-handlebars.js
71
+ - vendor/assets/javascripts/poirot-hogan/index.js
72
+ - vendor/assets/javascripts/poirot-hogan/poirot-hogan.js
73
+ - vendor/assets/javascripts/poirot-mustache/index.js
74
+ - vendor/assets/javascripts/poirot-mustache/mustache.js
75
+ - vendor/assets/javascripts/poirot/index.js
76
+ homepage: http://rubygems.org/gems/poirot
77
+ licenses: []
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ segments:
89
+ - 0
90
+ hash: 2462592963835808659
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ segments:
98
+ - 0
99
+ hash: 2462592963835808659
100
+ requirements: []
101
+ rubyforge_project: poirot
102
+ rubygems_version: 1.8.24
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: mustache support for rails
106
+ test_files: []