jim 0.1.2 → 0.2.0
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/HISTORY +28 -0
- data/README.rdoc +1 -1
- data/Rakefile +2 -1
- data/jim.gemspec +67 -9
- data/lib/jim/bundler.rb +14 -11
- data/lib/jim/cli.rb +51 -9
- data/lib/jim/index.rb +3 -7
- data/lib/jim/installer.rb +140 -22
- data/lib/jim/templates/commands +21 -6
- data/lib/jim/version_parser.rb +2 -3
- data/lib/jim.rb +19 -2
- data/test/fixtures/jimfile +3 -3
- data/test/fixtures/sammy-0.5.0/HISTORY.md +135 -0
- data/test/fixtures/sammy-0.5.0/LICENSE +22 -0
- data/test/fixtures/sammy-0.5.0/README.md +81 -0
- data/test/fixtures/sammy-0.5.0/Rakefile +174 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/README.md +23 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/Rakefile +15 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.rb +17 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/app.ru +3 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/app.js +106 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.cloudkit.js +840 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/jquery.js +19 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/javascripts/sammy.js +1013 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/index.html.erb +11 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/public/templates/task_details.html.erb +4 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/app.sass +63 -0
- data/test/fixtures/sammy-0.5.0/examples/backend/views/index.haml +18 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/files/form.html +12 -0
- data/test/fixtures/sammy-0.5.0/examples/form_handling/index.html +65 -0
- data/test/fixtures/sammy-0.5.0/examples/hello_world/index.html +50 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/README.md +15 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/data.html +110 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/index.html +79 -0
- data/test/fixtures/sammy-0.5.0/examples/location_override/test.html +121 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-0.5.0.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/min/sammy-lastest.min.js +5 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.cache.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.haml.js +539 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.json.js +362 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.mustache.js +415 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.nested_params.js +118 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.storage.js +515 -0
- data/test/fixtures/sammy-0.5.0/lib/plugins/sammy.template.js +117 -0
- data/test/fixtures/sammy-0.5.0/lib/sammy.js +1367 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.html +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.noengine +1 -0
- data/test/fixtures/sammy-0.5.0/test/fixtures/partial.template +1 -0
- data/test/fixtures/sammy-0.5.0/test/index.html +84 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_application.js +953 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_event_context.js +252 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_location_proxy.js +91 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_plugins.js +296 -0
- data/test/fixtures/sammy-0.5.0/test/test_sammy_storage.js +175 -0
- data/test/fixtures/sammy-0.5.0/test/test_server +27 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.js +6078 -0
- data/test/fixtures/sammy-0.5.0/vendor/jquery-1.4.1.min.js +152 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/doc.haml +58 -0
- data/test/fixtures/sammy-0.5.0/vendor/jsdoc/jsdoc.rb +143 -0
- data/test/fixtures/sammy-0.5.0/vendor/jslitmus.js +670 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.css +119 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit/qunit.js +1043 -0
- data/test/fixtures/sammy-0.5.0/vendor/qunit-spec.js +127 -0
- data/test/helper.rb +23 -3
- data/test/test_jim_bundler.rb +9 -8
- data/test/test_jim_cli.rb +21 -12
- data/test/test_jim_installer.rb +152 -35
- data/test/test_jim_version_parser.rb +4 -0
- metadata +117 -27
- data/.document +0 -5
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// name: sammy.cache
|
|
2
|
+
// version: 0.5.0
|
|
3
|
+
// ** deprecated
|
|
4
|
+
(function($) {
|
|
5
|
+
|
|
6
|
+
Sammy = Sammy || {};
|
|
7
|
+
|
|
8
|
+
// A simple cache strategy that stores key/values in memory.
|
|
9
|
+
Sammy.MemoryCacheProxy = function(initial) {
|
|
10
|
+
this._cache = initial || {};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
$.extend(Sammy.MemoryCacheProxy.prototype, {
|
|
14
|
+
exists: function(name) {
|
|
15
|
+
return (typeof this._cache[name] != "undefined");
|
|
16
|
+
},
|
|
17
|
+
set: function(name, value) {
|
|
18
|
+
return this._cache[name] = value;
|
|
19
|
+
},
|
|
20
|
+
get: function(name) {
|
|
21
|
+
return this._cache[name];
|
|
22
|
+
},
|
|
23
|
+
clear: function(name) {
|
|
24
|
+
delete this._cache[name];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// A simple cache strategy that stores key/values <tt>$element.data()</tt> with a <tt>cache.</tt> prefix
|
|
29
|
+
Sammy.DataCacheProxy = function(initial, $element) {
|
|
30
|
+
initial = initial || {};
|
|
31
|
+
this.$element = $element;
|
|
32
|
+
$.each(initial, function(key, value) {
|
|
33
|
+
$element.data('cache.' + key, value);
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
$.extend(Sammy.DataCacheProxy.prototype, {
|
|
38
|
+
exists: function(name) {
|
|
39
|
+
return (typeof this.$element.data('cache.' + name) != "undefined");
|
|
40
|
+
},
|
|
41
|
+
set: function(name, value) {
|
|
42
|
+
return this.$element.data('cache.' + name, value);
|
|
43
|
+
},
|
|
44
|
+
get: function(name) {
|
|
45
|
+
return this.$element.data('cache.' + name);
|
|
46
|
+
},
|
|
47
|
+
clear: function(name) {
|
|
48
|
+
this.$element.removeData('cache.' + name);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Sammy.Cache provides helpers for caching data within the lifecycle of a
|
|
53
|
+
// Sammy app. The plugin provides two main methods on <tt>Sammy.Application<tt>,
|
|
54
|
+
// <tt>cache</tt> and <tt>clearCache</tt>. Each app has its own cache store so that
|
|
55
|
+
// you dont have to worry about collisions. There are currently two different 'cache proxies'
|
|
56
|
+
// that share the same API but store the data in different ways.
|
|
57
|
+
//
|
|
58
|
+
// === Arguments
|
|
59
|
+
//
|
|
60
|
+
// +proxy+:: decides which caching proxy to use, either 'memory'(default) or 'data'
|
|
61
|
+
//
|
|
62
|
+
Sammy.Cache = function(app, proxy) {
|
|
63
|
+
|
|
64
|
+
app.log('**WARNING:** This version of Sammy.Cache has been deprecated in favor of using the version in Sammy.Storage and will be removed in 1.0')
|
|
65
|
+
|
|
66
|
+
if (proxy == 'data') {
|
|
67
|
+
this.cache_proxy = new Sammy.DataCacheProxy({}, this.$element());
|
|
68
|
+
} else {
|
|
69
|
+
this.cache_proxy = new Sammy.MemoryCacheProxy({});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
app.cache_partials = true;
|
|
73
|
+
|
|
74
|
+
$.extend(app, {
|
|
75
|
+
// cache is the main method for interacting with the cache store. The same
|
|
76
|
+
// method is used for both setting and getting the value. The API is similar
|
|
77
|
+
// to jQuery.fn.attr()
|
|
78
|
+
//
|
|
79
|
+
// === Examples
|
|
80
|
+
//
|
|
81
|
+
// // setting a value
|
|
82
|
+
// cache('key', 'value');
|
|
83
|
+
//
|
|
84
|
+
// // getting a value
|
|
85
|
+
// cache('key'); //=> 'value'
|
|
86
|
+
//
|
|
87
|
+
// // setting a value with a callback
|
|
88
|
+
// cache('key', function() {
|
|
89
|
+
// // this is the app
|
|
90
|
+
// return app.element_selector;
|
|
91
|
+
// });
|
|
92
|
+
//
|
|
93
|
+
cache: function(name, value) {
|
|
94
|
+
if (typeof value == 'undefined') {
|
|
95
|
+
return this.cache_proxy.get(name);
|
|
96
|
+
} else if ($.isFunction(value) && !this.cache_proxy.exists(name)) {
|
|
97
|
+
return this.cache_proxy.set(name, value.apply(this));
|
|
98
|
+
} else {
|
|
99
|
+
return this.cache_proxy.set(name, value)
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
// clears the cached value for <tt>name</tt>
|
|
104
|
+
clearCache: function(name) {
|
|
105
|
+
return this.cache_proxy.clear(name);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
app.helpers({
|
|
110
|
+
// a helper shortcut for use in <tt>Sammy.EventContext</tt>
|
|
111
|
+
cache: function(name, value) {
|
|
112
|
+
return this.app.cache(name, value);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
})(jQuery);
|
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
(function($) {
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
port of http://github.com/creationix/haml-js
|
|
5
|
+
by Tim Caswell <tim@creationix.com>
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
var matchers, self_close_tags, embedder;
|
|
9
|
+
|
|
10
|
+
function html_escape(text) {
|
|
11
|
+
if (typeof text !== 'string') {
|
|
12
|
+
text = text + "";
|
|
13
|
+
}
|
|
14
|
+
return text.
|
|
15
|
+
replace(/&/g, "&").
|
|
16
|
+
replace(/</g, "<").
|
|
17
|
+
replace(/>/g, ">").
|
|
18
|
+
replace(/\"/g, """);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function render_attribs(attribs) {
|
|
22
|
+
var key, value, result = [];
|
|
23
|
+
for (key in attribs) {
|
|
24
|
+
if (key !== 'content' && attribs.hasOwnProperty(key)) {
|
|
25
|
+
switch (attribs[key]) {
|
|
26
|
+
case 'undefined':
|
|
27
|
+
case 'false':
|
|
28
|
+
case 'null':
|
|
29
|
+
case '""':
|
|
30
|
+
break;
|
|
31
|
+
default:
|
|
32
|
+
try {
|
|
33
|
+
value = JSON.parse("[" + attribs[key] +"]")[0];
|
|
34
|
+
if (value === true) {
|
|
35
|
+
value = key;
|
|
36
|
+
}
|
|
37
|
+
result.push(" " + key + '=\\"' + html_escape(value) + '\\"');
|
|
38
|
+
} catch (e) {
|
|
39
|
+
result.push(" " + key + '=\\"" + html_escape(' + attribs[key] + ') + "\\"');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result.join("");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Parse the attribute block using a state machine
|
|
48
|
+
function parse_attribs(line) {
|
|
49
|
+
var attributes = {},
|
|
50
|
+
l = line.length,
|
|
51
|
+
i, c,
|
|
52
|
+
count = 1,
|
|
53
|
+
quote = false,
|
|
54
|
+
skip = false,
|
|
55
|
+
open, close, joiner, seperator,
|
|
56
|
+
pair = {
|
|
57
|
+
start: 1,
|
|
58
|
+
middle: null,
|
|
59
|
+
end: null
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (!(l > 0 && (line.charAt(0) === '{' || line.charAt(0) === '('))) {
|
|
63
|
+
return {
|
|
64
|
+
content: line[0] === ' ' ? line.substr(1, l) : line
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
open = line.charAt(0);
|
|
68
|
+
close = (open === '{') ? '}' : ')';
|
|
69
|
+
joiner = (open === '{') ? ':' : '=';
|
|
70
|
+
seperator = (open === '{') ? ',' : ' ';
|
|
71
|
+
|
|
72
|
+
function process_pair() {
|
|
73
|
+
var key = line.substr(pair.start, pair.middle - pair.start).trim(),
|
|
74
|
+
value = line.substr(pair.middle + 1, pair.end - pair.middle - 1).trim();
|
|
75
|
+
attributes[key] = value;
|
|
76
|
+
pair = {
|
|
77
|
+
start: null,
|
|
78
|
+
middle: null,
|
|
79
|
+
end: null
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (i = 1; count > 0; i += 1) {
|
|
84
|
+
|
|
85
|
+
// If we reach the end of the line, then there is a problem
|
|
86
|
+
if (i > l) {
|
|
87
|
+
throw "Malformed attribute block";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
c = line.charAt(i);
|
|
91
|
+
if (skip) {
|
|
92
|
+
skip = false;
|
|
93
|
+
} else {
|
|
94
|
+
if (quote) {
|
|
95
|
+
if (c === '\\') {
|
|
96
|
+
skip = true;
|
|
97
|
+
}
|
|
98
|
+
if (c === quote) {
|
|
99
|
+
quote = false;
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
if (c === '"' || c === "'") {
|
|
103
|
+
quote = c;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (count === 1) {
|
|
107
|
+
if (c === joiner) {
|
|
108
|
+
pair.middle = i;
|
|
109
|
+
}
|
|
110
|
+
if (c === seperator || c === close) {
|
|
111
|
+
pair.end = i;
|
|
112
|
+
process_pair();
|
|
113
|
+
if (c === seperator) {
|
|
114
|
+
pair.start = i + 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (c === open) {
|
|
120
|
+
count += 1;
|
|
121
|
+
}
|
|
122
|
+
if (c === close) {
|
|
123
|
+
count -= 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
attributes.content = line.substr(i, line.length);
|
|
129
|
+
return attributes;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Split interpolated strings into an array of literals and code fragments.
|
|
133
|
+
function parse_interpol(value) {
|
|
134
|
+
var items = [],
|
|
135
|
+
pos = 0,
|
|
136
|
+
next = 0,
|
|
137
|
+
match;
|
|
138
|
+
while (true) {
|
|
139
|
+
// Match up to embedded string
|
|
140
|
+
next = value.substr(pos).search(embedder);
|
|
141
|
+
if (next < 0) {
|
|
142
|
+
if (pos < value.length) {
|
|
143
|
+
items.push(JSON.stringify(value.substr(pos)));
|
|
144
|
+
}
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
items.push(JSON.stringify(value.substr(pos, next)));
|
|
148
|
+
pos += next;
|
|
149
|
+
|
|
150
|
+
// Match embedded string
|
|
151
|
+
match = value.substr(pos).match(embedder);
|
|
152
|
+
next = match[0].length;
|
|
153
|
+
if (next < 0) { break; }
|
|
154
|
+
items.push(match[1] || match[2]);
|
|
155
|
+
pos += next;
|
|
156
|
+
}
|
|
157
|
+
return items.join(" + ");
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Used to find embedded code in interpolated strings.
|
|
161
|
+
embedder = /\#\{([^}]*)\}/;
|
|
162
|
+
|
|
163
|
+
self_close_tags = ["meta", "img", "link", "br", "hr", "input", "area", "base"];
|
|
164
|
+
|
|
165
|
+
// All matchers' regexps should capture leading whitespace in first capture
|
|
166
|
+
// and trailing content in last capture
|
|
167
|
+
matchers = [
|
|
168
|
+
// html tags
|
|
169
|
+
{
|
|
170
|
+
regexp: /^(\s*)((?:[.#%][a-z_\-][a-z0-9_\-]*)+)(.*)$/i,
|
|
171
|
+
process: function () {
|
|
172
|
+
var tag, classes, ids, attribs, content;
|
|
173
|
+
tag = this.matches[2];
|
|
174
|
+
classes = tag.match(/\.([a-z_\-][a-z0-9_\-]*)/gi);
|
|
175
|
+
ids = tag.match(/\#([a-z_\-][a-z0-9_\-]*)/gi);
|
|
176
|
+
tag = tag.match(/\%([a-z_\-][a-z0-9_\-]*)/gi);
|
|
177
|
+
|
|
178
|
+
// Default to <div> tag
|
|
179
|
+
tag = tag ? tag[0].substr(1, tag[0].length) : 'div';
|
|
180
|
+
|
|
181
|
+
attribs = this.matches[3];
|
|
182
|
+
if (attribs) {
|
|
183
|
+
attribs = parse_attribs(attribs);
|
|
184
|
+
if (attribs.content) {
|
|
185
|
+
this.contents.unshift(attribs.content.trim());
|
|
186
|
+
delete(attribs.content);
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
attribs = {};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (classes) {
|
|
193
|
+
classes = classes.map(function (klass) {
|
|
194
|
+
return klass.substr(1, klass.length);
|
|
195
|
+
}).join(' ');
|
|
196
|
+
if (attribs['class']) {
|
|
197
|
+
try {
|
|
198
|
+
attribs['class'] = JSON.stringify(classes + " " + JSON.parse(attribs['class']));
|
|
199
|
+
} catch (e) {
|
|
200
|
+
attribs['class'] = JSON.stringify(classes + " ") + " + " + attribs['class'];
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
attribs['class'] = JSON.stringify(classes);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (ids) {
|
|
207
|
+
ids = ids.map(function (id) {
|
|
208
|
+
return id.substr(1, id.length);
|
|
209
|
+
}).join(' ');
|
|
210
|
+
if (attribs.id) {
|
|
211
|
+
attribs.id = JSON.stringify(ids + " ") + attribs.id;
|
|
212
|
+
} else {
|
|
213
|
+
attribs.id = JSON.stringify(ids);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
attribs = render_attribs(attribs);
|
|
218
|
+
|
|
219
|
+
content = this.render_contents();
|
|
220
|
+
if (content === '""') {
|
|
221
|
+
content = '';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (self_close_tags.indexOf(tag) == -1) {
|
|
225
|
+
return '"<' + tag + attribs + '>"' +
|
|
226
|
+
(content.length > 0 ? ' + \n' + content : "") +
|
|
227
|
+
' + \n"</' + tag + '>"';
|
|
228
|
+
} else {
|
|
229
|
+
return '"<' + tag + attribs + ' />"';
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
// each loops
|
|
235
|
+
{
|
|
236
|
+
regexp: /^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i,
|
|
237
|
+
process: function () {
|
|
238
|
+
var ivar = this.matches[2] || '__key__', // index
|
|
239
|
+
vvar = this.matches[3], // value
|
|
240
|
+
avar = this.matches[4], // array
|
|
241
|
+
rvar = '__result__'; // results
|
|
242
|
+
|
|
243
|
+
if (this.matches[5]) {
|
|
244
|
+
this.contents.unshift(this.matches[5]);
|
|
245
|
+
}
|
|
246
|
+
return '(function () { ' +
|
|
247
|
+
'var ' + rvar + ' = [], ' + ivar + ', ' + vvar + '; ' +
|
|
248
|
+
'for (' + ivar + ' in ' + avar + ') { ' +
|
|
249
|
+
'if (' + avar + '.hasOwnProperty(' + ivar + ')) { ' +
|
|
250
|
+
vvar + ' = ' + avar + '[' + ivar + ']; ' +
|
|
251
|
+
rvar + '.push(\n' + (this.render_contents() || "''") + '\n); ' +
|
|
252
|
+
'} } return ' + rvar + '.join(""); }).call(this)';
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
// if statements
|
|
257
|
+
{
|
|
258
|
+
regexp: /^(\s*):if\s+(.*)\s*$/i,
|
|
259
|
+
process: function () {
|
|
260
|
+
var condition = this.matches[2];
|
|
261
|
+
return '(function () { ' +
|
|
262
|
+
'if (' + condition + ') { ' +
|
|
263
|
+
'return (\n' + (this.render_contents() || '') + '\n);' +
|
|
264
|
+
'} else { return ""; } }).call(this)';
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
|
|
268
|
+
// declarations
|
|
269
|
+
{
|
|
270
|
+
regexp: /^()!!!(?:\s*(.*))\s*$/,
|
|
271
|
+
process: function () {
|
|
272
|
+
var line = '';
|
|
273
|
+
switch ((this.matches[2] || '').toLowerCase()) {
|
|
274
|
+
case '':
|
|
275
|
+
// XHTML 1.0 Transitional
|
|
276
|
+
line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
|
|
277
|
+
break;
|
|
278
|
+
case 'strict':
|
|
279
|
+
case '1.0':
|
|
280
|
+
// XHTML 1.0 Strict
|
|
281
|
+
line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
|
|
282
|
+
break;
|
|
283
|
+
case 'frameset':
|
|
284
|
+
// XHTML 1.0 Frameset
|
|
285
|
+
line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
|
|
286
|
+
break;
|
|
287
|
+
case '5':
|
|
288
|
+
// XHTML 5
|
|
289
|
+
line = '<!DOCTYPE html>';
|
|
290
|
+
break;
|
|
291
|
+
case '1.1':
|
|
292
|
+
// XHTML 1.1
|
|
293
|
+
line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
|
|
294
|
+
break;
|
|
295
|
+
case 'basic':
|
|
296
|
+
// XHTML Basic 1.1
|
|
297
|
+
line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">';
|
|
298
|
+
break;
|
|
299
|
+
case 'mobile':
|
|
300
|
+
// XHTML Mobile 1.2
|
|
301
|
+
line = '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">';
|
|
302
|
+
break;
|
|
303
|
+
case 'xml':
|
|
304
|
+
// XML
|
|
305
|
+
line = "<?xml version='1.0' encoding='utf-8' ?>";
|
|
306
|
+
break;
|
|
307
|
+
case 'xml iso-8859-1':
|
|
308
|
+
// XML iso-8859-1
|
|
309
|
+
line = "<?xml version='1.0' encoding='iso-8859-1' ?>";
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
return JSON.stringify(line + "\n");
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
// script blocks
|
|
317
|
+
{
|
|
318
|
+
regexp: /^(\s*):(?:java)?script\s*$/,
|
|
319
|
+
process: function () {
|
|
320
|
+
return parse_interpol('\n<script type="text/javascript">\n' +
|
|
321
|
+
'//<![CDATA[\n ' +
|
|
322
|
+
this.contents.join("\n ") +
|
|
323
|
+
"\n//]]>\n</script>\n");
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
// css blocks
|
|
328
|
+
{
|
|
329
|
+
regexp: /^(\s*):css\s*$/,
|
|
330
|
+
process: function () {
|
|
331
|
+
return JSON.stringify('\n<style type="text/css">\n ' +
|
|
332
|
+
this.contents.join("\n ") +
|
|
333
|
+
"\n</style>\n");
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
];
|
|
338
|
+
|
|
339
|
+
function compile(lines) {
|
|
340
|
+
var block = false,
|
|
341
|
+
output = [];
|
|
342
|
+
|
|
343
|
+
// If lines is a string, turn it into an array
|
|
344
|
+
if (typeof lines === 'string') {
|
|
345
|
+
lines = lines.trim().split("\n");
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
lines.forEach(function(line) {
|
|
349
|
+
var match, found = false;
|
|
350
|
+
|
|
351
|
+
// Collect all text as raw until outdent
|
|
352
|
+
if (block) {
|
|
353
|
+
match = block.check_indent(line);
|
|
354
|
+
if (match) {
|
|
355
|
+
block.contents.push(match[1] || "");
|
|
356
|
+
return;
|
|
357
|
+
} else {
|
|
358
|
+
output.push(block.process());
|
|
359
|
+
block = false;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
matchers.forEach(function (matcher) {
|
|
364
|
+
if (!found) {
|
|
365
|
+
match = matcher.regexp(line);
|
|
366
|
+
if (match) {
|
|
367
|
+
block = {
|
|
368
|
+
contents: [],
|
|
369
|
+
matches: match,
|
|
370
|
+
check_indent: new RegExp("^(?:\\s*|" + match[1] + " (.*))$"),
|
|
371
|
+
process: matcher.process,
|
|
372
|
+
render_contents: function () {
|
|
373
|
+
return compile(this. contents);
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
found = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// Match plain text
|
|
382
|
+
if (!found) {
|
|
383
|
+
output.push(function () {
|
|
384
|
+
// Escaped plain text
|
|
385
|
+
if (line[0] === '\\') {
|
|
386
|
+
return JSON.stringify(line.substr(1, line.length) + "\n");
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Plain variable data
|
|
390
|
+
if (line[0] === '=') {
|
|
391
|
+
line = line.substr(1, line.length).trim();
|
|
392
|
+
try {
|
|
393
|
+
return JSON.stringify(JSON.parse(line) +"\n");
|
|
394
|
+
} catch (e) {
|
|
395
|
+
return line + ' +\n"\\n"';
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// HTML escape variable data
|
|
400
|
+
if (line.substr(0, 2) === "&=") {
|
|
401
|
+
line = line.substr(2, line.length).trim();
|
|
402
|
+
try {
|
|
403
|
+
return JSON.stringify(html_escape(JSON.parse(line)) +"\n");
|
|
404
|
+
} catch (e2) {
|
|
405
|
+
return 'html_escape(' + line + ') +\n"\\n"';
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Plain text
|
|
410
|
+
return JSON.stringify(line + "\n");
|
|
411
|
+
}());
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
});
|
|
415
|
+
if (block) {
|
|
416
|
+
output.push(block.process());
|
|
417
|
+
}
|
|
418
|
+
return output.join(' + \n');
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
function optimize(js) {
|
|
422
|
+
var new_js = [], buffer = [], part, end;
|
|
423
|
+
|
|
424
|
+
function flush() {
|
|
425
|
+
if (buffer.length > 0) {
|
|
426
|
+
new_js.push(JSON.stringify(buffer.join("")) + end);
|
|
427
|
+
buffer = [];
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
js.split("\n").forEach(function (line) {
|
|
431
|
+
part = line.match(/^(\".*\")(\s*\+\s*)?$/);
|
|
432
|
+
if (!part) {
|
|
433
|
+
flush();
|
|
434
|
+
new_js.push(line);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
end = part[2] || "";
|
|
438
|
+
part = part[1];
|
|
439
|
+
try {
|
|
440
|
+
buffer.push(JSON.parse(part));
|
|
441
|
+
} catch (e) {
|
|
442
|
+
flush();
|
|
443
|
+
new_js.push(line);
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
flush();
|
|
447
|
+
return new_js.join("\n");
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
function execute(js, self, locals) {
|
|
451
|
+
return (function () {
|
|
452
|
+
with(locals || {}) {
|
|
453
|
+
try {
|
|
454
|
+
return eval("(" + js + ")");
|
|
455
|
+
} catch (e) {
|
|
456
|
+
return "\n<pre class='error'>" + html_escape(e.stack) + "</pre>\n";
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
}
|
|
460
|
+
}).call(self);
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
Sammy = Sammy || {};
|
|
465
|
+
|
|
466
|
+
// <tt>Sammy.Haml</tt> provides a quick way of using haml style templates in your app.
|
|
467
|
+
// The plugin itself includes the haml-js library created by Tim Caswell at
|
|
468
|
+
// at http://github.com/creationix/haml-js
|
|
469
|
+
//
|
|
470
|
+
// Haml is an alternative HTML syntax that is really great for describing
|
|
471
|
+
// the structure of HTML documents.
|
|
472
|
+
//
|
|
473
|
+
// By default using Sammy.Haml in your app adds the <tt>haml()</tt> method to the EventContext
|
|
474
|
+
// prototype. However, just like <tt>Sammy.Template</tt> you can change the default name of the method
|
|
475
|
+
// by passing a second argument (e.g. you could use the hml() as the method alias so that all the template
|
|
476
|
+
// files could be in the form file.hml instead of file.haml)
|
|
477
|
+
//
|
|
478
|
+
// === Example
|
|
479
|
+
//
|
|
480
|
+
// The template (mytemplate.haml):
|
|
481
|
+
//
|
|
482
|
+
// %h1&= title
|
|
483
|
+
//
|
|
484
|
+
// Hey, #{name}! Welcome to Haml!
|
|
485
|
+
//
|
|
486
|
+
// The app:
|
|
487
|
+
//
|
|
488
|
+
// var $.app = $.sammy(function() {
|
|
489
|
+
// // include the plugin
|
|
490
|
+
// this.use(Sammy.Haml);
|
|
491
|
+
//
|
|
492
|
+
// this.get('#/hello/:name', function() {
|
|
493
|
+
// // set local vars
|
|
494
|
+
// this.title = 'Hello!'
|
|
495
|
+
// this.name = this.params.name;
|
|
496
|
+
// // render the template and pass it through mustache
|
|
497
|
+
// this.partial('mytemplate.haml');
|
|
498
|
+
// });
|
|
499
|
+
//
|
|
500
|
+
// });
|
|
501
|
+
//
|
|
502
|
+
// If I go to #/hello/AQ in the browser, Sammy will render this to the <tt>body</tt>:
|
|
503
|
+
//
|
|
504
|
+
// <h1>Hello!</h1>
|
|
505
|
+
//
|
|
506
|
+
// Hey, AQ! Welcome to HAML!
|
|
507
|
+
//
|
|
508
|
+
// Note: You dont have to include the haml.js file on top of the plugin as the plugin
|
|
509
|
+
// includes the full source.
|
|
510
|
+
//
|
|
511
|
+
Sammy.Haml = function(app, method_alias) {
|
|
512
|
+
app.use(Sammy.JSON);
|
|
513
|
+
|
|
514
|
+
var haml_cache = {};
|
|
515
|
+
// *Helper*:: Uses haml-js to parse a template and interpolate and work with the passed data
|
|
516
|
+
//
|
|
517
|
+
// === Arguments
|
|
518
|
+
//
|
|
519
|
+
// +template+:: A String template.
|
|
520
|
+
// +data+:: An Object containing the replacement values for the template.
|
|
521
|
+
// data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
|
|
522
|
+
//
|
|
523
|
+
var haml = function(template, data, name) {
|
|
524
|
+
// use name for caching
|
|
525
|
+
if (typeof name == 'undefined') name = template;
|
|
526
|
+
var code = haml_cache[name];
|
|
527
|
+
if (!code) {
|
|
528
|
+
code = haml_cache[name] = optimize(compile(template));
|
|
529
|
+
}
|
|
530
|
+
return execute(code, {}, $.extend({}, this, data));
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// set the default method name/extension
|
|
534
|
+
if (!method_alias) method_alias = 'haml';
|
|
535
|
+
app.helper(method_alias, haml);
|
|
536
|
+
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
})(jQuery);
|