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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +5 -12
- data/Gemfile.lock +40 -18
- data/LICENSE.txt +2 -0
- data/README.md +15 -146
- data/Rakefile +2 -16
- data/lib/liquid_assets/config.rb +36 -9
- data/lib/liquid_assets/engine.rb +4 -4
- data/lib/liquid_assets/eval.rb +20 -0
- data/lib/liquid_assets/{tilt_engine.rb → pipeline_template_engine.rb} +8 -12
- data/lib/liquid_assets/resolver.rb +68 -0
- data/lib/liquid_assets/template_handler.rb +6 -20
- data/lib/liquid_assets/tiny_liquid.rb +11 -7
- data/lib/liquid_assets/version.rb +1 -1
- data/lib/liquid_assets.rb +5 -2
- data/liquid_assets.gemspec +23 -71
- data/test/helper.rb +1 -1
- data/test/test_liquid_assets.rb +49 -6
- data/vendor/assets/javascripts/liquid_assets.js.erb +228 -0
- data/vendor/tinyliquid.js +9 -6
- metadata +53 -85
- data/.document +0 -5
- data/VERSION +0 -1
- data/vendor/assets/javascripts/liquid_assets.js +0 -57
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
|
-
|
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 :
|
13
|
+
autoload :PipelineTemplateEngine, 'liquid_assets/pipeline_template_engine'
|
11
14
|
|
12
15
|
if defined? Rails
|
13
16
|
require 'liquid_assets/engine'
|
data/liquid_assets.gemspec
CHANGED
@@ -1,76 +1,28 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
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 |
|
7
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
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
data/test/test_liquid_assets.rb
CHANGED
@@ -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::
|
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::
|
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.
|
2143
|
-
script += 'if ( ' + partial_function + '){'
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
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.
|
2230
|
+
context.namespace = options.namespace;
|
2228
2231
|
context.customTags = options.tags; // 自定义的标记解析
|
2229
2232
|
context.loop = 0; // { 嵌套层数
|
2230
2233
|
context.loopName = []; // 当前嵌套标记名称
|