Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

filters.js 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. 'use strict';
  2. var lib = require('./lib');
  3. var r = require('./runtime');
  4. var _exports = module.exports = {};
  5. function normalize(value, defaultValue) {
  6. if (value === null || value === undefined || value === false) {
  7. return defaultValue;
  8. }
  9. return value;
  10. }
  11. _exports.abs = Math.abs;
  12. function isNaN(num) {
  13. return num !== num; // eslint-disable-line no-self-compare
  14. }
  15. function batch(arr, linecount, fillWith) {
  16. var i;
  17. var res = [];
  18. var tmp = [];
  19. for (i = 0; i < arr.length; i++) {
  20. if (i % linecount === 0 && tmp.length) {
  21. res.push(tmp);
  22. tmp = [];
  23. }
  24. tmp.push(arr[i]);
  25. }
  26. if (tmp.length) {
  27. if (fillWith) {
  28. for (i = tmp.length; i < linecount; i++) {
  29. tmp.push(fillWith);
  30. }
  31. }
  32. res.push(tmp);
  33. }
  34. return res;
  35. }
  36. _exports.batch = batch;
  37. function capitalize(str) {
  38. str = normalize(str, '');
  39. var ret = str.toLowerCase();
  40. return r.copySafeness(str, ret.charAt(0).toUpperCase() + ret.slice(1));
  41. }
  42. _exports.capitalize = capitalize;
  43. function center(str, width) {
  44. str = normalize(str, '');
  45. width = width || 80;
  46. if (str.length >= width) {
  47. return str;
  48. }
  49. var spaces = width - str.length;
  50. var pre = lib.repeat(' ', spaces / 2 - spaces % 2);
  51. var post = lib.repeat(' ', spaces / 2);
  52. return r.copySafeness(str, pre + str + post);
  53. }
  54. _exports.center = center;
  55. function default_(val, def, bool) {
  56. if (bool) {
  57. return val || def;
  58. } else {
  59. return val !== undefined ? val : def;
  60. }
  61. } // TODO: it is confusing to export something called 'default'
  62. _exports['default'] = default_; // eslint-disable-line dot-notation
  63. function dictsort(val, caseSensitive, by) {
  64. if (!lib.isObject(val)) {
  65. throw new lib.TemplateError('dictsort filter: val must be an object');
  66. }
  67. var array = []; // deliberately include properties from the object's prototype
  68. for (var k in val) {
  69. // eslint-disable-line guard-for-in, no-restricted-syntax
  70. array.push([k, val[k]]);
  71. }
  72. var si;
  73. if (by === undefined || by === 'key') {
  74. si = 0;
  75. } else if (by === 'value') {
  76. si = 1;
  77. } else {
  78. throw new lib.TemplateError('dictsort filter: You can only sort by either key or value');
  79. }
  80. array.sort(function (t1, t2) {
  81. var a = t1[si];
  82. var b = t2[si];
  83. if (!caseSensitive) {
  84. if (lib.isString(a)) {
  85. a = a.toUpperCase();
  86. }
  87. if (lib.isString(b)) {
  88. b = b.toUpperCase();
  89. }
  90. }
  91. return a > b ? 1 : a === b ? 0 : -1; // eslint-disable-line no-nested-ternary
  92. });
  93. return array;
  94. }
  95. _exports.dictsort = dictsort;
  96. function dump(obj, spaces) {
  97. return JSON.stringify(obj, null, spaces);
  98. }
  99. _exports.dump = dump;
  100. function escape(str) {
  101. if (str instanceof r.SafeString) {
  102. return str;
  103. }
  104. str = str === null || str === undefined ? '' : str;
  105. return r.markSafe(lib.escape(str.toString()));
  106. }
  107. _exports.escape = escape;
  108. function safe(str) {
  109. if (str instanceof r.SafeString) {
  110. return str;
  111. }
  112. str = str === null || str === undefined ? '' : str;
  113. return r.markSafe(str.toString());
  114. }
  115. _exports.safe = safe;
  116. function first(arr) {
  117. return arr[0];
  118. }
  119. _exports.first = first;
  120. function forceescape(str) {
  121. str = str === null || str === undefined ? '' : str;
  122. return r.markSafe(lib.escape(str.toString()));
  123. }
  124. _exports.forceescape = forceescape;
  125. function groupby(arr, attr) {
  126. return lib.groupBy(arr, attr, this.env.opts.throwOnUndefined);
  127. }
  128. _exports.groupby = groupby;
  129. function indent(str, width, indentfirst) {
  130. str = normalize(str, '');
  131. if (str === '') {
  132. return '';
  133. }
  134. width = width || 4; // let res = '';
  135. var lines = str.split('\n');
  136. var sp = lib.repeat(' ', width);
  137. var res = lines.map(function (l, i) {
  138. return i === 0 && !indentfirst ? l : "" + sp + l;
  139. }).join('\n');
  140. return r.copySafeness(str, res);
  141. }
  142. _exports.indent = indent;
  143. function join(arr, del, attr) {
  144. del = del || '';
  145. if (attr) {
  146. arr = lib.map(arr, function (v) {
  147. return v[attr];
  148. });
  149. }
  150. return arr.join(del);
  151. }
  152. _exports.join = join;
  153. function last(arr) {
  154. return arr[arr.length - 1];
  155. }
  156. _exports.last = last;
  157. function lengthFilter(val) {
  158. var value = normalize(val, '');
  159. if (value !== undefined) {
  160. if (typeof Map === 'function' && value instanceof Map || typeof Set === 'function' && value instanceof Set) {
  161. // ECMAScript 2015 Maps and Sets
  162. return value.size;
  163. }
  164. if (lib.isObject(value) && !(value instanceof r.SafeString)) {
  165. // Objects (besides SafeStrings), non-primative Arrays
  166. return lib.keys(value).length;
  167. }
  168. return value.length;
  169. }
  170. return 0;
  171. }
  172. _exports.length = lengthFilter;
  173. function list(val) {
  174. if (lib.isString(val)) {
  175. return val.split('');
  176. } else if (lib.isObject(val)) {
  177. return lib._entries(val || {}).map(function (_ref) {
  178. var key = _ref[0],
  179. value = _ref[1];
  180. return {
  181. key: key,
  182. value: value
  183. };
  184. });
  185. } else if (lib.isArray(val)) {
  186. return val;
  187. } else {
  188. throw new lib.TemplateError('list filter: type not iterable');
  189. }
  190. }
  191. _exports.list = list;
  192. function lower(str) {
  193. str = normalize(str, '');
  194. return str.toLowerCase();
  195. }
  196. _exports.lower = lower;
  197. function nl2br(str) {
  198. if (str === null || str === undefined) {
  199. return '';
  200. }
  201. return r.copySafeness(str, str.replace(/\r\n|\n/g, '<br />\n'));
  202. }
  203. _exports.nl2br = nl2br;
  204. function random(arr) {
  205. return arr[Math.floor(Math.random() * arr.length)];
  206. }
  207. _exports.random = random;
  208. /**
  209. * Construct select or reject filter
  210. *
  211. * @param {boolean} expectedTestResult
  212. * @returns {function(array, string, *): array}
  213. */
  214. function getSelectOrReject(expectedTestResult) {
  215. function filter(arr, testName, secondArg) {
  216. if (testName === void 0) {
  217. testName = 'truthy';
  218. }
  219. var context = this;
  220. var test = context.env.getTest(testName);
  221. return lib.toArray(arr).filter(function examineTestResult(item) {
  222. return test.call(context, item, secondArg) === expectedTestResult;
  223. });
  224. }
  225. return filter;
  226. }
  227. _exports.reject = getSelectOrReject(false);
  228. function rejectattr(arr, attr) {
  229. return arr.filter(function (item) {
  230. return !item[attr];
  231. });
  232. }
  233. _exports.rejectattr = rejectattr;
  234. _exports.select = getSelectOrReject(true);
  235. function selectattr(arr, attr) {
  236. return arr.filter(function (item) {
  237. return !!item[attr];
  238. });
  239. }
  240. _exports.selectattr = selectattr;
  241. function replace(str, old, new_, maxCount) {
  242. var originalStr = str;
  243. if (old instanceof RegExp) {
  244. return str.replace(old, new_);
  245. }
  246. if (typeof maxCount === 'undefined') {
  247. maxCount = -1;
  248. }
  249. var res = ''; // Output
  250. // Cast Numbers in the search term to string
  251. if (typeof old === 'number') {
  252. old = '' + old;
  253. } else if (typeof old !== 'string') {
  254. // If it is something other than number or string,
  255. // return the original string
  256. return str;
  257. } // Cast numbers in the replacement to string
  258. if (typeof str === 'number') {
  259. str = '' + str;
  260. } // If by now, we don't have a string, throw it back
  261. if (typeof str !== 'string' && !(str instanceof r.SafeString)) {
  262. return str;
  263. } // ShortCircuits
  264. if (old === '') {
  265. // Mimic the python behaviour: empty string is replaced
  266. // by replacement e.g. "abc"|replace("", ".") -> .a.b.c.
  267. res = new_ + str.split('').join(new_) + new_;
  268. return r.copySafeness(str, res);
  269. }
  270. var nextIndex = str.indexOf(old); // if # of replacements to perform is 0, or the string to does
  271. // not contain the old value, return the string
  272. if (maxCount === 0 || nextIndex === -1) {
  273. return str;
  274. }
  275. var pos = 0;
  276. var count = 0; // # of replacements made
  277. while (nextIndex > -1 && (maxCount === -1 || count < maxCount)) {
  278. // Grab the next chunk of src string and add it with the
  279. // replacement, to the result
  280. res += str.substring(pos, nextIndex) + new_; // Increment our pointer in the src string
  281. pos = nextIndex + old.length;
  282. count++; // See if there are any more replacements to be made
  283. nextIndex = str.indexOf(old, pos);
  284. } // We've either reached the end, or done the max # of
  285. // replacements, tack on any remaining string
  286. if (pos < str.length) {
  287. res += str.substring(pos);
  288. }
  289. return r.copySafeness(originalStr, res);
  290. }
  291. _exports.replace = replace;
  292. function reverse(val) {
  293. var arr;
  294. if (lib.isString(val)) {
  295. arr = list(val);
  296. } else {
  297. // Copy it
  298. arr = lib.map(val, function (v) {
  299. return v;
  300. });
  301. }
  302. arr.reverse();
  303. if (lib.isString(val)) {
  304. return r.copySafeness(val, arr.join(''));
  305. }
  306. return arr;
  307. }
  308. _exports.reverse = reverse;
  309. function round(val, precision, method) {
  310. precision = precision || 0;
  311. var factor = Math.pow(10, precision);
  312. var rounder;
  313. if (method === 'ceil') {
  314. rounder = Math.ceil;
  315. } else if (method === 'floor') {
  316. rounder = Math.floor;
  317. } else {
  318. rounder = Math.round;
  319. }
  320. return rounder(val * factor) / factor;
  321. }
  322. _exports.round = round;
  323. function slice(arr, slices, fillWith) {
  324. var sliceLength = Math.floor(arr.length / slices);
  325. var extra = arr.length % slices;
  326. var res = [];
  327. var offset = 0;
  328. for (var i = 0; i < slices; i++) {
  329. var start = offset + i * sliceLength;
  330. if (i < extra) {
  331. offset++;
  332. }
  333. var end = offset + (i + 1) * sliceLength;
  334. var currSlice = arr.slice(start, end);
  335. if (fillWith && i >= extra) {
  336. currSlice.push(fillWith);
  337. }
  338. res.push(currSlice);
  339. }
  340. return res;
  341. }
  342. _exports.slice = slice;
  343. function sum(arr, attr, start) {
  344. if (start === void 0) {
  345. start = 0;
  346. }
  347. if (attr) {
  348. arr = lib.map(arr, function (v) {
  349. return v[attr];
  350. });
  351. }
  352. return start + arr.reduce(function (a, b) {
  353. return a + b;
  354. }, 0);
  355. }
  356. _exports.sum = sum;
  357. _exports.sort = r.makeMacro(['value', 'reverse', 'case_sensitive', 'attribute'], [], function sortFilter(arr, reversed, caseSens, attr) {
  358. var _this = this;
  359. // Copy it
  360. var array = lib.map(arr, function (v) {
  361. return v;
  362. });
  363. var getAttribute = lib.getAttrGetter(attr);
  364. array.sort(function (a, b) {
  365. var x = attr ? getAttribute(a) : a;
  366. var y = attr ? getAttribute(b) : b;
  367. if (_this.env.opts.throwOnUndefined && attr && (x === undefined || y === undefined)) {
  368. throw new TypeError("sort: attribute \"" + attr + "\" resolved to undefined");
  369. }
  370. if (!caseSens && lib.isString(x) && lib.isString(y)) {
  371. x = x.toLowerCase();
  372. y = y.toLowerCase();
  373. }
  374. if (x < y) {
  375. return reversed ? 1 : -1;
  376. } else if (x > y) {
  377. return reversed ? -1 : 1;
  378. } else {
  379. return 0;
  380. }
  381. });
  382. return array;
  383. });
  384. function string(obj) {
  385. return r.copySafeness(obj, obj);
  386. }
  387. _exports.string = string;
  388. function striptags(input, preserveLinebreaks) {
  389. input = normalize(input, '');
  390. var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|<!--[\s\S]*?-->/gi;
  391. var trimmedInput = trim(input.replace(tags, ''));
  392. var res = '';
  393. if (preserveLinebreaks) {
  394. res = trimmedInput.replace(/^ +| +$/gm, '') // remove leading and trailing spaces
  395. .replace(/ +/g, ' ') // squash adjacent spaces
  396. .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF)
  397. .replace(/\n\n\n+/g, '\n\n'); // squash abnormal adjacent linebreaks
  398. } else {
  399. res = trimmedInput.replace(/\s+/gi, ' ');
  400. }
  401. return r.copySafeness(input, res);
  402. }
  403. _exports.striptags = striptags;
  404. function title(str) {
  405. str = normalize(str, '');
  406. var words = str.split(' ').map(function (word) {
  407. return capitalize(word);
  408. });
  409. return r.copySafeness(str, words.join(' '));
  410. }
  411. _exports.title = title;
  412. function trim(str) {
  413. return r.copySafeness(str, str.replace(/^\s*|\s*$/g, ''));
  414. }
  415. _exports.trim = trim;
  416. function truncate(input, length, killwords, end) {
  417. var orig = input;
  418. input = normalize(input, '');
  419. length = length || 255;
  420. if (input.length <= length) {
  421. return input;
  422. }
  423. if (killwords) {
  424. input = input.substring(0, length);
  425. } else {
  426. var idx = input.lastIndexOf(' ', length);
  427. if (idx === -1) {
  428. idx = length;
  429. }
  430. input = input.substring(0, idx);
  431. }
  432. input += end !== undefined && end !== null ? end : '...';
  433. return r.copySafeness(orig, input);
  434. }
  435. _exports.truncate = truncate;
  436. function upper(str) {
  437. str = normalize(str, '');
  438. return str.toUpperCase();
  439. }
  440. _exports.upper = upper;
  441. function urlencode(obj) {
  442. var enc = encodeURIComponent;
  443. if (lib.isString(obj)) {
  444. return enc(obj);
  445. } else {
  446. var keyvals = lib.isArray(obj) ? obj : lib._entries(obj);
  447. return keyvals.map(function (_ref2) {
  448. var k = _ref2[0],
  449. v = _ref2[1];
  450. return enc(k) + "=" + enc(v);
  451. }).join('&');
  452. }
  453. }
  454. _exports.urlencode = urlencode; // For the jinja regexp, see
  455. // https://github.com/mitsuhiko/jinja2/blob/f15b814dcba6aa12bc74d1f7d0c881d55f7126be/jinja2/utils.py#L20-L23
  456. var puncRe = /^(?:\(|<|&lt;)?(.*?)(?:\.|,|\)|\n|&gt;)?$/; // from http://blog.gerv.net/2011/05/html5_email_address_regexp/
  457. var emailRe = /^[\w.!#$%&'*+\-\/=?\^`{|}~]+@[a-z\d\-]+(\.[a-z\d\-]+)+$/i;
  458. var httpHttpsRe = /^https?:\/\/.*$/;
  459. var wwwRe = /^www\./;
  460. var tldRe = /\.(?:org|net|com)(?:\:|\/|$)/;
  461. function urlize(str, length, nofollow) {
  462. if (isNaN(length)) {
  463. length = Infinity;
  464. }
  465. var noFollowAttr = nofollow === true ? ' rel="nofollow"' : '';
  466. var words = str.split(/(\s+)/).filter(function (word) {
  467. // If the word has no length, bail. This can happen for str with
  468. // trailing whitespace.
  469. return word && word.length;
  470. }).map(function (word) {
  471. var matches = word.match(puncRe);
  472. var possibleUrl = matches ? matches[1] : word;
  473. var shortUrl = possibleUrl.substr(0, length); // url that starts with http or https
  474. if (httpHttpsRe.test(possibleUrl)) {
  475. return "<a href=\"" + possibleUrl + "\"" + noFollowAttr + ">" + shortUrl + "</a>";
  476. } // url that starts with www.
  477. if (wwwRe.test(possibleUrl)) {
  478. return "<a href=\"http://" + possibleUrl + "\"" + noFollowAttr + ">" + shortUrl + "</a>";
  479. } // an email address of the form username@domain.tld
  480. if (emailRe.test(possibleUrl)) {
  481. return "<a href=\"mailto:" + possibleUrl + "\">" + possibleUrl + "</a>";
  482. } // url that ends in .com, .org or .net that is not an email address
  483. if (tldRe.test(possibleUrl)) {
  484. return "<a href=\"http://" + possibleUrl + "\"" + noFollowAttr + ">" + shortUrl + "</a>";
  485. }
  486. return word;
  487. });
  488. return words.join('');
  489. }
  490. _exports.urlize = urlize;
  491. function wordcount(str) {
  492. str = normalize(str, '');
  493. var words = str ? str.match(/\w+/g) : null;
  494. return words ? words.length : null;
  495. }
  496. _exports.wordcount = wordcount;
  497. function float(val, def) {
  498. var res = parseFloat(val);
  499. return isNaN(res) ? def : res;
  500. }
  501. _exports.float = float;
  502. var intFilter = r.makeMacro(['value', 'default', 'base'], [], function doInt(value, defaultValue, base) {
  503. if (base === void 0) {
  504. base = 10;
  505. }
  506. var res = parseInt(value, base);
  507. return isNaN(res) ? defaultValue : res;
  508. });
  509. _exports.int = intFilter; // Aliases
  510. _exports.d = _exports.default;
  511. _exports.e = _exports.escape;