liquid_assets 0.1.1 → 0.3.2

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.
data/lib/liquid_assets.rb CHANGED
@@ -1,13 +1,16 @@
1
1
  require 'liquid_assets/version'
2
+ require 'liquid_assets/eval'
2
3
  require 'liquid_assets/config'
3
4
  require 'liquid_assets/template_handler'
4
- require 'liquid_assets/tilt_engine'
5
+
6
+ require 'liquid_assets/resolver'
7
+
5
8
  module LiquidAssets
6
9
 
7
10
  extend Config
8
11
 
9
12
  autoload :TinyLiquid, 'liquid_assets/tiny_liquid'
10
- autoload :TiltEngine, 'liquid_assets/tilt_engine'
13
+ autoload :PipelineTemplateEngine, 'liquid_assets/pipeline_template_engine'
11
14
 
12
15
  if defined? Rails
13
16
  require 'liquid_assets/engine'
@@ -1,76 +1,28 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'liquid_assets/version'
5
5
 
6
- Gem::Specification.new do |s|
7
- s.name = "liquid_assets"
8
- s.version = "0.1.0"
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "liquid_assets"
8
+ spec.version = LiquidAssets::VERSION
9
+ spec.authors = ["Nathan Stitt"]
10
+ spec.email = ["nathan@stitt.org"]
11
+ spec.description = %q{A rails engine that supports writing both server and client side templates in Liqud markup}
12
+ spec.summary = %q{Liquid formmated views and assets}
13
+ spec.homepage = "http://github.com/nathanstitt/liquid_assets"
14
+ spec.license = "MIT"
9
15
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Nathan Stitt"]
12
- s.date = "2013-03-14"
13
- s.description = "Allows you to use Liquid format templates in Rails, both as\nview templates and as compiled JavaScript via the asset_pipeline."
14
- s.email = "nathan@stitt.org"
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.md"
18
- ]
19
- s.files = [
20
- ".document",
21
- "Gemfile",
22
- "Gemfile.lock",
23
- "LICENSE.txt",
24
- "README.md",
25
- "Rakefile",
26
- "VERSION",
27
- "lib/liquid_assets.rb",
28
- "lib/liquid_assets/config.rb",
29
- "lib/liquid_assets/engine.rb",
30
- "lib/liquid_assets/template_handler.rb",
31
- "lib/liquid_assets/tilt_engine.rb",
32
- "lib/liquid_assets/tiny_liquid.rb",
33
- "lib/liquid_assets/version.rb",
34
- "liquid_assets.gemspec",
35
- "test/helper.rb",
36
- "test/test_liquid_assets.rb",
37
- "vendor/assets/javascripts/liquid_assets.js",
38
- "vendor/tinyliquid.js"
39
- ]
40
- s.homepage = "http://github.com/nathanstitt/liquid_assets"
41
- s.licenses = ["MIT"]
42
- s.require_paths = ["lib"]
43
- s.rubygems_version = "1.8.23"
44
- s.summary = "Liquid formmated views and assets"
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
45
20
 
46
- if s.respond_to? :specification_version then
47
- s.specification_version = 3
21
+ spec.add_dependency 'liquid'
22
+ spec.add_dependency 'tilt'
23
+ spec.add_dependency 'execjs'
24
+ spec.add_dependency 'actionpack', '>=3.2'
48
25
 
49
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
- s.add_runtime_dependency(%q<liquid>, [">= 0"])
51
- s.add_runtime_dependency(%q<tilt>, [">= 0"])
52
- s.add_runtime_dependency(%q<sprockets>, [">= 0"])
53
- s.add_runtime_dependency(%q<execjs>, [">= 0"])
54
- s.add_development_dependency(%q<rdoc>, [">= 0"])
55
- s.add_development_dependency(%q<bundler>, [">= 0"])
56
- s.add_development_dependency(%q<jeweler>, [">= 0"])
57
- else
58
- s.add_dependency(%q<liquid>, [">= 0"])
59
- s.add_dependency(%q<tilt>, [">= 0"])
60
- s.add_dependency(%q<sprockets>, [">= 0"])
61
- s.add_dependency(%q<execjs>, [">= 0"])
62
- s.add_dependency(%q<rdoc>, [">= 0"])
63
- s.add_dependency(%q<bundler>, [">= 0"])
64
- s.add_dependency(%q<jeweler>, [">= 0"])
65
- end
66
- else
67
- s.add_dependency(%q<liquid>, [">= 0"])
68
- s.add_dependency(%q<tilt>, [">= 0"])
69
- s.add_dependency(%q<sprockets>, [">= 0"])
70
- s.add_dependency(%q<execjs>, [">= 0"])
71
- s.add_dependency(%q<rdoc>, [">= 0"])
72
- s.add_dependency(%q<bundler>, [">= 0"])
73
- s.add_dependency(%q<jeweler>, [">= 0"])
74
- end
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
75
28
  end
76
-
data/test/helper.rb CHANGED
@@ -15,7 +15,7 @@ require 'liquid_assets'
15
15
 
16
16
  module LiquidAssets::Config
17
17
  def reset!
18
- %w(env path_prefix template_namespace filters ).each do |option|
18
+ %w(env path_prefix namespace filters ).each do |option|
19
19
  send "#{option}=", nil
20
20
  end
21
21
  end
@@ -9,18 +9,17 @@ class TestLiquidAssets < Test::Unit::TestCase
9
9
  end
10
10
 
11
11
  def test_mime_type
12
- assert_equal 'application/javascript', LiquidAssets::TiltEngine.default_mime_type
12
+ assert_equal 'application/javascript', LiquidAssets::PipelineTemplateEngine.default_mime_type
13
13
  end
14
14
 
15
15
  def test_tilt_engine_rendering
16
16
  scope = make_scope '/myapp/app/assets/javascripts', 'path/to/template.mustache'
17
17
 
18
- template = LiquidAssets::TiltEngine.new(scope.s_path) { "This is {{me}}" }
18
+ template = LiquidAssets::PipelineTemplateEngine.new(scope.s_path) { "This is {{me}}" }
19
+
20
+ tmpl="LQT.Templates[\"path/to/template\"] = function(locals,filters){\n var $_tmpbuf, $_html = LQT._FNS.html, $_err = LQT._FNS.err,\n $_rethrow=LQT._FNS.rethrow, $_merge=LQT._FNS.merge,\n $_range=LQT._FNS.range, $_array=LQT._FNS.array;\n /* == Template Begin == */\nvar $_buf = '';\nvar $_line_num = 0;\n/* == define cycles == */\nvar $_cycle_next = function (n) {\nn.i++;\nif (n.i >= n.length) n.i = 0;\n}\n$_buf+=('This is ');\n$_line_num = 1;\n$_tmpbuf = locals.me;\n$_buf+=($_tmpbuf===null||typeof($_tmpbuf)===\"undefined\"?\"\":$_tmpbuf);\n return $_buf;\n }\n;"
21
+ assert_equal tmpl, template.render(scope, {})
19
22
 
20
- assert_equal <<-END_EXPECTED, template.render(scope, {})
21
- this.LQT || (this.LQT = {});
22
- this.LQT[\"path/to/template\"] = function(locals,filters){\nvar $_tmpbuf, $_html = LQT._FNS.html, $_err = LQT._FNS.err, $_rethrow=LQT._FNS.rethrow, $_merge=LQT._FNS.merge, $_range=LQT._FNS.range, $_array=LQT._FNS.array;\n/* == Template Begin == */\nvar $_buf = '';\nvar $_line_num = 0;\n/* == define cycles == */\nvar $_cycle_next = function (n) {\nn.i++;\nif (n.i >= n.length) n.i = 0;\n}\n$_buf+=('This is ');\n$_line_num = 1;\n$_tmpbuf = locals.me;\n$_buf+=($_tmpbuf===null||typeof($_tmpbuf)===\"undefined\"?\"\":$_tmpbuf);\nreturn $_buf;\n};
23
- END_EXPECTED
24
23
  end
25
24
 
26
25
  def test_template_rendering
@@ -30,4 +29,48 @@ class TestLiquidAssets < Test::Unit::TestCase
30
29
  assert_equal 'foo=bar', template
31
30
  end
32
31
 
32
+
33
+ def test_resolver
34
+ LiquidAssets::Config.content_provider = lambda do | path |
35
+ 'good' == path ? 'Hello {{bob|upcase}}' : false
36
+ end
37
+
38
+ details = {:formats=>[:liquid], :locale=>[:en], :handlers=>[] }
39
+ resolver = LiquidAssets::Resolver.instance
40
+
41
+ assert_empty resolver.find_all('bad','',false, details )
42
+ assert_not_empty resolver.find_all('good','',false, details )
43
+ end
44
+
45
+ def test_resolver_caches
46
+ times_called = 0
47
+ LiquidAssets::Config.content_provider = lambda do | path |
48
+ times_called += 1
49
+ 'foo/bar/good' == path ? 'Hello {{bob|upcase}}' : false
50
+ end
51
+
52
+ details = {:formats=>[:liquid], :locale=>[:en], :handlers=>[] }
53
+ resolver = LiquidAssets::Resolver.instance
54
+ key = 'dumb-key'
55
+ (0...3).each do
56
+ resolver.find_all('foo/bar/good',nil ,false, details, key )
57
+ end
58
+ assert_equal 1, times_called
59
+
60
+ times_called = 0
61
+
62
+ resolver.clear_cache_for( 'bad' ) # shouldn't clear cache for 'good'
63
+
64
+ resolver.find_all('foo/bar/good',nil,false, details, key )
65
+
66
+ assert_equal 0, times_called
67
+
68
+ resolver.clear_cache_for( 'foo/bar/good' )
69
+
70
+ resolver.find_all('foo/bar/good',nil,false, details, key )
71
+
72
+ assert_equal 1, times_called
73
+
74
+
75
+ end
33
76
  end
@@ -0,0 +1,228 @@
1
+ (function( namespace, document, undefined) {
2
+
3
+ namespace = namespace.<%= LiquidAssets::Config.namespace%> || (namespace.<%=LiquidAssets::Config.namespace%>={});
4
+ namespace.Templates || ( namespace.Templates={} );
5
+
6
+ namespace.Globals || ( namespace.Globals = {} );
7
+ var server_globals = <%= LiquidAssets::Config.globals.to_json.html_safe %>;
8
+ for ( var key in server_globals ){
9
+ namespace.Globals[ key ] = server_globals[key];
10
+ }
11
+
12
+ namespace.Render = function( name, data ){
13
+ if (data == null) {
14
+ data = {};
15
+ }
16
+ for ( var key in namespace.Globals )
17
+ if (! data.hasOwnProperty(key) )
18
+ data[key] = namespace.Globals[key];
19
+
20
+ return namespace.Templates[name]( data, namespace.Filters );
21
+ };
22
+
23
+ namespace.RenderPartial = function( name, data ){
24
+ var path, parts = name.split('/');
25
+ if ( parts.length > 1 )
26
+ path = parts.slice( 0, parts.length-1) +'/_'+parts[ parts.length-1 ];
27
+ else
28
+ path = '_' + parts[ parts.length-1 ];
29
+ return namespace.Render( path, data );
30
+ };
31
+
32
+ namespace._FNS = {
33
+ html: function (html) {
34
+ return html.replace(/\\/g, '\\\\')
35
+ .replace(/'/g, '\\\'')
36
+ .replace(/"/g, '\\\"')
37
+ .replace(/\r/g, '\\r')
38
+ .replace(/\n/g, '\\n');
39
+ },
40
+ err: function (msg) {
41
+ var html = '<pre style="font-family:Courier; font-weight:bold; \
42
+ font-size:14px; color:red; padding:4px 20px 4px 20px; border:1px solid #CCC; \
43
+ background-color:#FFF5F0; line-height:1.6em; white-space:pre-wrap; \
44
+ white-space:-moz-pre-wrap; white-space:-pre-wrap; white-space:-o-pre-wrap; \
45
+ word-wrap:break-word; z-index:9999">' + msg + '</pre>';
46
+ return html;
47
+ },
48
+ rethrow: function (err, filename) {
49
+ var msg = 'An error occurred while rendering\n' +
50
+ 'Line: ' + $_line_num + (filename ? ' File: ' + filename : '') +
51
+ '\n ' + err;
52
+ $_buf += $_err(msg);
53
+ },
54
+ merge: function () {
55
+ var ret = {};
56
+ for (var i in arguments) {
57
+ var obj = arguments[i];
58
+ for (var j in obj) {
59
+ ret[j] = obj[j];
60
+ }
61
+ }
62
+ return ret;
63
+ },
64
+ range: function (s, e) {
65
+ s = parseInt(s);
66
+ e = parseInt(e);
67
+ var r = [];
68
+ if (isNaN(s) || isNaN(e)) return r;
69
+ for (; s <= e; s++) {
70
+ r.push(s);
71
+ }
72
+ return r;
73
+ },
74
+ 'array': function (data) {
75
+ if (Array.isArray(data)) return data;
76
+ var ret = [];
77
+ for (var i in data) {
78
+ if (i !== 'size') {
79
+ ret.push(data[i]);
80
+ }
81
+ }
82
+ return ret;
83
+ }
84
+ };
85
+
86
+ var toNumber = function(input) {
87
+ return Number(input);
88
+ };
89
+
90
+ var toString = function(input) {
91
+ if (!input) {
92
+ return '';
93
+ }
94
+ if (_.isString(input)) {
95
+ return input;
96
+ } else if (typeof input.toString === "function") {
97
+ return input.toString();
98
+ } else {
99
+ return Object.prototype.toString.call(input);
100
+ }
101
+ };
102
+
103
+ namespace.Filters = {
104
+ size: function(input) {
105
+ return input.length;
106
+ },
107
+ downcase: function(input) {
108
+ return toString(input).toLowerCase();
109
+ },
110
+ upcase: function(input) {
111
+ return toString(input).toUpperCase();
112
+ },
113
+ append: function(input, other) {
114
+ return [toString(input), toString(other)].join();
115
+ },
116
+ prepend: function(input, other) {
117
+ return [toString(other), toString(input)].join();
118
+ },
119
+ empty: function(input) {
120
+ if (!input) {
121
+ return true;
122
+ }
123
+ if (input.length == null) {
124
+ return false;
125
+ }
126
+ return true;
127
+ },
128
+ truncate: function(input, length, truncateString) {
129
+ var l;
130
+
131
+ if (length == null) {
132
+ length = 50;
133
+ }
134
+ if (truncateString == null) {
135
+ truncateString = '...';
136
+ }
137
+ input = toString(input);
138
+ truncateString = toString(truncateString);
139
+ if (input == null) {
140
+ return '';
141
+ }
142
+ if (!input.slice) {
143
+ return '';
144
+ }
145
+ length = toNumber(length);
146
+ l = length - truncateString.length;
147
+ if (l < 0) {
148
+ l = 0;
149
+ }
150
+ if (input.length > length) {
151
+ return input.slice(0, +l + 1 || 9e9) + truncateString;
152
+ } else {
153
+ return input;
154
+ }
155
+ },
156
+ truncatewords: function(input, words, truncateString) {
157
+ var l, wordlist;
158
+
159
+ if (words == null) {
160
+ words = 15;
161
+ }
162
+ if (truncateString == null) {
163
+ truncateString = '...';
164
+ }
165
+ input = toString(input);
166
+ if (input == null) {
167
+ return '';
168
+ }
169
+ if (!input.slice) {
170
+ return '';
171
+ }
172
+ wordlist = input.split(" ");
173
+ words = toNumber(words);
174
+ l = words - 1;
175
+ if (l < 0) {
176
+ l = 0;
177
+ }
178
+ if (wordlist.length > l) {
179
+ return wordlist.slice(0, +l + 1 || 9e9).join(" ") + truncateString;
180
+ } else {
181
+ return input;
182
+ }
183
+ },
184
+ split: function(input, pattern) {
185
+ input = toString(input);
186
+ if (!input) {
187
+ return null;
188
+ }
189
+ return input.split(pattern);
190
+ },
191
+ join: function(input, glue) {
192
+ if (glue == null) {
193
+ glue = ' ';
194
+ }
195
+ return _(input).flatten().join(glue);
196
+ },
197
+ first: function(array) {
198
+ if (array.length > 0) {
199
+ return array[0];
200
+ } else {
201
+ return null;
202
+ }
203
+ },
204
+ last: function(array) {
205
+ if (array.length > 0) {
206
+ return array[array.length - 1];
207
+ } else {
208
+ return null;
209
+ }
210
+ },
211
+ plus: function(input, operand) {
212
+ return toNumber(input) + toNumber(operand);
213
+ },
214
+ minus: function(input, operand) {
215
+ return toNumber(input) - toNumber(operand);
216
+ },
217
+ times: function(input, operand) {
218
+ return toNumber(input) * toNumber(operand);
219
+ },
220
+ dividedBy: function(input, operand) {
221
+ return toNumber(input) / toNumber(operand);
222
+ },
223
+ modulo: function(input, operand) {
224
+ return toNumber(input) % toNumber(operand);
225
+ }
226
+ };
227
+
228
+ }(window, document));
data/vendor/tinyliquid.js CHANGED
@@ -2139,11 +2139,14 @@ exports.tags = function (text, start, context) {
2139
2139
  setLineNumber();
2140
2140
  var include_parts = inc_tag.name.split('/');
2141
2141
  include_parts[ include_parts.length-1] = '_' + include_parts[ include_parts.length - 1 ];
2142
- var partial_function = context.partials_namespace + '[\'' + include_parts.join('/') + '\']';
2143
- script += 'if ( ' + partial_function + '){' +
2144
- ' $_buf+=' + partial_function + '(' + (inc_tag.with ? inc_tag.with : 'locals') + ',filters);' +
2145
- '} else {' +
2146
- ' $_buf+=\'No such template ' + include_parts.join('/') + '\';' +
2142
+ var partial_function = context.namespace + '.Templates[\'' + include_parts.join('/') + '\']';
2143
+ script += 'if ( ' + partial_function + '){';
2144
+ if ( inc_tag.with )
2145
+ script+=' $_buf+=' + partial_function + '({\'' + inc_tag.with + '\': locals.' + (inc_tag.with) + '},filters);';
2146
+ else
2147
+ script+=' $_buf+=' + partial_function + '(locals,filters);';
2148
+ script+='} else {' +
2149
+ ' $_buf+=\'Partial not found: ' + include_parts.join('/') + '\';' +
2147
2150
  '}';
2148
2151
  // script += '/* === include "' + inc_tag.name + '"' +
2149
2152
  // (inc_tag.with ? ' with "' + inc_tag.with + '"' : '') +
@@ -2224,7 +2227,7 @@ exports.parse = function (text, options) {
2224
2227
  };
2225
2228
 
2226
2229
  // 初始化编译环境
2227
- context.partials_namespace = options.partials_namespace;
2230
+ context.namespace = options.namespace;
2228
2231
  context.customTags = options.tags; // 自定义的标记解析
2229
2232
  context.loop = 0; // { 嵌套层数
2230
2233
  context.loopName = []; // 当前嵌套标记名称