зеркало из https://github.com/mozilla/djangode.git
Implemented url and regroup tags
This commit is contained in:
Родитель
abad5beb35
Коммит
3ccef9d7cc
|
@ -94,7 +94,8 @@ exports.makeApp = function(urls, options) {
|
|||
options = options || {};
|
||||
var show_404 = (options.show_404 || default_show_404);
|
||||
var show_500 = (options.show_500 || default_show_500);
|
||||
return function(req, res) {
|
||||
|
||||
var app = function(req, res) {
|
||||
debuginfo.last_request = req;
|
||||
debuginfo.last_response = res;
|
||||
var path = url.parse(req.url)["pathname"];
|
||||
|
@ -120,6 +121,9 @@ exports.makeApp = function(urls, options) {
|
|||
show_500(req, res, e);
|
||||
}
|
||||
}
|
||||
app.urls = {};
|
||||
urls.forEach(function (item) { app.urls[item[2]] = item[0]; });
|
||||
return app;
|
||||
}
|
||||
|
||||
function default_show_404(req, res) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
var dj = require('djangode');
|
||||
var dj = require('./djangode');
|
||||
|
||||
var app = dj.makeApp([
|
||||
['^/$', function(req, res) {
|
||||
|
|
|
@ -23,17 +23,12 @@ NOTE:
|
|||
Missing tags:
|
||||
|
||||
ssi (will require ALLOWED_INCLUDE_ROOTS somehow)
|
||||
|
||||
debug
|
||||
|
||||
regroup
|
||||
widthratio
|
||||
|
||||
url
|
||||
|
||||
NOTE:
|
||||
cycle tag does not support legacy syntax (row1,row2,row3)
|
||||
load takes a path - like require. Loaded module must expose tags and filters objects.
|
||||
url tag relies on app being set in process.djangode_app_config
|
||||
*/
|
||||
|
||||
var filters = exports.filters = {
|
||||
|
@ -590,8 +585,43 @@ var nodes = exports.nodes = {
|
|||
|
||||
callback(false, Math.round(current_val / max_val * constant_val) + "");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
RegroupNode: function (item, key, name) {
|
||||
return function (context, callback) {
|
||||
var list = context.get(item);
|
||||
if (!list instanceof Array) { callback(false, ''); }
|
||||
|
||||
var dict = {};
|
||||
var grouped = list
|
||||
.map(function (x) { return x[key]; })
|
||||
.filter(function (x) { var val = dict[x]; dict[x] = x; return !val; })
|
||||
.map(function (grp) {
|
||||
return { grouper: grp, list: list.filter(function (o) { return o[key] === grp }) };
|
||||
});
|
||||
|
||||
context.set(name, grouped);
|
||||
callback(false, '');
|
||||
}
|
||||
},
|
||||
|
||||
UrlNode: function (url_name, replacements, item_name) {
|
||||
|
||||
return function (context, callback) {
|
||||
var match = process.djangode_urls[context.get(url_name)]
|
||||
if (!match) { return callback('no matching urls for ' + url_name_val); }
|
||||
|
||||
var url = string_utils.regex_to_string(match, replacements.map(function (x) { return context.get(x); }));
|
||||
url = '/' + url;
|
||||
|
||||
if (item_name) {
|
||||
context.set( item_name, url);
|
||||
callback(false, '');
|
||||
} else {
|
||||
callback(false, url);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var tags = exports.tags = {
|
||||
|
@ -798,5 +828,25 @@ var tags = exports.tags = {
|
|||
return nodes.SpacelessNode(node_list);
|
||||
},
|
||||
'widthratio': simple_tag(nodes.WithRatioNode, { argcount: 3 }),
|
||||
'regroup': simple_tag(nodes.RegroupNode, { argcount: 5, mustbe: { 2: 'by', 4: 'as' }, exclude: [2, 4] }),
|
||||
|
||||
'url': function (parser, token) {
|
||||
var parts = token.split_contents();
|
||||
parts.shift();
|
||||
|
||||
var url_name = parts.shift();
|
||||
|
||||
if (parts[parts.length - 2] === 'as') {
|
||||
var item_name = parts.pop();
|
||||
parts.pop();
|
||||
}
|
||||
|
||||
// TODO: handle qouted strings with commas in them correctly
|
||||
var replacements = parts.join('').split(/\s*,\s*/)
|
||||
|
||||
return nodes.UrlNode(url_name, replacements, item_name);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -243,19 +243,9 @@ testcase('include')
|
|||
make_parse_and_execute_test('her er en hestgiraf.', '{% include name %}');
|
||||
|
||||
testcase('load')
|
||||
|
||||
exports.filters = { testfilter: function () { return 'hestgiraf'; } }
|
||||
exports.tags = {
|
||||
testtag: function () {
|
||||
return function (context, callback) {
|
||||
callback('', 'hestgiraf')
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
make_parse_and_execute_test('hestgiraf', '{% load ./template_defaults.tags.test %}{{ 100|testfilter }}');
|
||||
make_parse_and_execute_test('hestgiraf', '{% load "./template_defaults.tags.test" %}{{ 100|testfilter }}');
|
||||
make_parse_and_execute_test('hestgiraf', '{% load ./template_defaults.tags.test %}{% testtag %}');
|
||||
make_parse_and_execute_test('hestgiraf', '{% load ./load_tag_test %}{{ 100|testfilter }}');
|
||||
make_parse_and_execute_test('hestgiraf', '{% load "./load_tag_test" %}{{ 100|testfilter }}');
|
||||
make_parse_and_execute_test('hestgiraf', '{% load ./load_tag_test %}{% testtag %}');
|
||||
|
||||
testcase('templatetag')
|
||||
make_parse_and_execute_test('{%', '{% templatetag openblock %}');
|
||||
|
@ -275,5 +265,51 @@ testcase('widthratio')
|
|||
setup(function () { return {obj:{this_value: 175, max_value: 200 } }; });
|
||||
make_parse_and_execute_test('88', '{% widthratio this_value max_value 100 %}');
|
||||
|
||||
testcase('regroup')
|
||||
setup(function () {
|
||||
return {
|
||||
obj: {
|
||||
people: [
|
||||
{'first_name': 'George', 'last_name': 'Bush', 'gender': 'Male'},
|
||||
{'first_name': 'Bill', 'last_name': 'Clinton', 'gender': 'Male'},
|
||||
{'first_name': 'Margaret', 'last_name': 'Thatcher', 'gender': 'Female'},
|
||||
{'first_name': 'Condoleezza', 'last_name': 'Rice', 'gender': 'Female'},
|
||||
{'first_name': 'Pat', 'last_name': 'Smith', 'gender': 'Unknown'}
|
||||
]
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
make_parse_and_execute_test('<ul>' +
|
||||
'<li>Male:<ul><li>George Bush</li><li>Bill Clinton</li></ul></li>' +
|
||||
'<li>Female:<ul><li>Margaret Thatcher</li><li>Condoleezza Rice</li></ul></li>' +
|
||||
'<li>Unknown:<ul><li>Pat Smith</li></ul></li></ul>',
|
||||
'{% regroup people by gender as gender_list %}' +
|
||||
'<ul>{% for gender in gender_list %}<li>{{ gender.grouper }}:' +
|
||||
'<ul>{% for item in gender.list %}<li>{{ item.first_name }} {{ item.last_name }}</li>{% endfor %}' +
|
||||
'</ul></li>{% endfor %}</ul>');
|
||||
|
||||
testcase('url')
|
||||
setup(function () {
|
||||
process.djangode_urls = {
|
||||
'news-views-special_case_2003': /^articles\/2003\/$/,
|
||||
'news-views-year_archive': /^articles\/(\d{4})\/$/,
|
||||
'news-views-month_archive': /^articles\/(\d{4})\/(\d{2})\/$/,
|
||||
'news-views-article_detail': /^articles\/(\d{4})\/(\d{2})\/(\d+)\/$/
|
||||
};
|
||||
return { obj: { year: 1981, month: 12, date: 2, url_name: 'news-views-article_detail' } };
|
||||
});
|
||||
teardown( function () {
|
||||
delete process.djangode_urls;
|
||||
});
|
||||
make_parse_and_execute_test("/articles/2003/", "{% url 'news-views-special_case_2003' %}");
|
||||
make_parse_and_execute_test("/articles/1981/", "{% url 'news-views-year_archive' 1981 %}");
|
||||
make_parse_and_execute_test("/articles/1981/12/", "{% url 'news-views-month_archive' 1981 , 12 %}");
|
||||
make_parse_and_execute_test("/articles/1981/12/2/", "{% url url_name year, month, date %}");
|
||||
|
||||
make_parse_and_execute_test("/articles/2003/",
|
||||
"{% url 'news-views-special_case_2003' as the_url %}{{ the_url }}");
|
||||
make_parse_and_execute_test("/articles/1981/12/",
|
||||
"{% url 'news-views-month_archive' 1981, 12 as the_url %}{{ the_url }}");
|
||||
run();
|
||||
|
||||
|
|
|
@ -59,4 +59,5 @@ var app = dj.makeApp([
|
|||
]);
|
||||
|
||||
dj.serve(app, 8009);
|
||||
process.djangode_urls = app.urls;
|
||||
|
||||
|
|
|
@ -203,4 +203,57 @@ function wordwrap (str, int_width, str_break, cut) {
|
|||
exports.wordwrap = wordwrap;
|
||||
|
||||
|
||||
// replace groups in regex like string with replacer
|
||||
function replace_groups(input, replacer) {
|
||||
var i, out = '', cnt = 0;
|
||||
for (i = 0; i < input.length; i += 1) {
|
||||
if (input[i] === '\\') {
|
||||
if (cnt === 0) {
|
||||
out += input[i] + input[i + 1];
|
||||
}
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (cnt === 0 && input[i] !== '(') {
|
||||
out += input[i];
|
||||
continue;
|
||||
}
|
||||
if (input[i] === '(') {
|
||||
cnt += 1;
|
||||
} else if (input[i] === ')') {
|
||||
cnt -= 1;
|
||||
if (cnt === 0) {
|
||||
out += replacer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
exports.regex_to_string = function (re, group_replacements) {
|
||||
var s = re.toString();
|
||||
|
||||
// remove leading and trailing slashes
|
||||
s = s.substr(1, s.length - 2);
|
||||
|
||||
// replace groups with '(())'
|
||||
s = replace_groups(s, '(())');
|
||||
|
||||
// remove special chars
|
||||
s = s.replace(/\^|\$|\*|\+|\?|\.|\\cX|\\xhh|\\uhhhh|\\./g, function (m) {
|
||||
if (m[0] === '\\') {
|
||||
if (m.substr(1).match(/f|r|n|t|v|\d+|b|s|S|w|W|d|D|b|B/)) { return ''; }
|
||||
if (m.substr(1).match(/c.|x..|u..../)) { return eval("'" + m + "'"); }
|
||||
return m[1];
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
// replace groups with replacers
|
||||
s = s.replace(/\(\(\)\)/g, function () { return (group_replacements || []).shift() || ''; });
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var sys = require('sys');
|
||||
|
||||
process.mixin(GLOBAL, require('./test').dsl);
|
||||
process.mixin(GLOBAL, require('./string'));
|
||||
|
||||
|
@ -29,5 +30,19 @@ testcase('wrap')
|
|||
test('should wrap text', function () {
|
||||
assertEquals('Joel \nis a \nslug', wordwrap('Joel is a slug', 5));
|
||||
});
|
||||
testcase('regex_to_string')
|
||||
test('should work without groups', function () {
|
||||
assertEquals('hest', regex_to_string(/hest/));
|
||||
assertEquals('hest', regex_to_string(/^hest$/));
|
||||
assertEquals('hestgiraf', regex_to_string(/hest\s*giraf\d+/));
|
||||
assertEquals('hest*', regex_to_string(/hest\*/));
|
||||
assertEquals('hestgiraf', regex_to_string(/hest(tobis)giraf/));
|
||||
});
|
||||
|
||||
test('should replace groups with input', function () {
|
||||
assertEquals('shows/hest/34/', regex_to_string(/^shows\/(\w+)\/(\d+)\/$/, ['hest', 34]));
|
||||
assertEquals('shows/giraf/90/', regex_to_string(/^shows\/(hest(?:laks|makrel))\/(\d+)\/$/, ['giraf', 90]));
|
||||
});
|
||||
|
||||
run();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче