123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- 'use strict';
-
- /**
- * Merge two attribute objects giving precedence
- * to values in object `b`. Classes are special-cased
- * allowing for arrays and merging/joining appropriately
- * resulting in a string.
- *
- * @param {Object} a
- * @param {Object} b
- * @return {Object} a
- * @api private
- */
-
- exports.merge = function merge(a, b) {
- if (arguments.length === 1) {
- var attrs = a[0];
- for (var i = 1; i < a.length; i++) {
- attrs = merge(attrs, a[i]);
- }
- return attrs;
- }
- var ac = a['class'];
- var bc = b['class'];
-
- if (ac || bc) {
- ac = ac || [];
- bc = bc || [];
- if (!Array.isArray(ac)) ac = [ac];
- if (!Array.isArray(bc)) bc = [bc];
- a['class'] = ac.concat(bc).filter(nulls);
- }
-
- for (var key in b) {
- if (key != 'class') {
- a[key] = b[key];
- }
- }
-
- return a;
- };
-
- /**
- * Filter null `val`s.
- *
- * @param {*} val
- * @return {Boolean}
- * @api private
- */
-
- function nulls(val) {
- return val != null && val !== '';
- }
-
- /**
- * join array as classes.
- *
- * @param {*} val
- * @return {String}
- */
- exports.joinClasses = joinClasses;
- function joinClasses(val) {
- return Array.isArray(val) ? val.map(joinClasses).filter(nulls).join(' ') : val;
- }
-
- /**
- * Render the given classes.
- *
- * @param {Array} classes
- * @param {Array.<Boolean>} escaped
- * @return {String}
- */
- exports.cls = function cls(classes, escaped) {
- var buf = [];
- for (var i = 0; i < classes.length; i++) {
- if (escaped && escaped[i]) {
- buf.push(exports.escape(joinClasses([classes[i]])));
- } else {
- buf.push(joinClasses(classes[i]));
- }
- }
- var text = joinClasses(buf);
- if (text.length) {
- return ' class="' + text + '"';
- } else {
- return '';
- }
- };
-
- /**
- * Render the given attribute.
- *
- * @param {String} key
- * @param {String} val
- * @param {Boolean} escaped
- * @param {Boolean} terse
- * @return {String}
- */
- exports.attr = function attr(key, val, escaped, terse) {
- if ('boolean' == typeof val || null == val) {
- if (val) {
- return ' ' + (terse ? key : key + '="' + key + '"');
- } else {
- return '';
- }
- } else if (0 == key.indexOf('data') && 'string' != typeof val) {
- return ' ' + key + "='" + JSON.stringify(val).replace(/'/g, ''') + "'";
- } else if (escaped) {
- return ' ' + key + '="' + exports.escape(val) + '"';
- } else {
- return ' ' + key + '="' + val + '"';
- }
- };
-
- /**
- * Render the given attributes object.
- *
- * @param {Object} obj
- * @param {Object} escaped
- * @return {String}
- */
- exports.attrs = function attrs(obj, terse){
- var buf = [];
-
- var keys = Object.keys(obj);
-
- if (keys.length) {
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i]
- , val = obj[key];
-
- if ('class' == key) {
- if (val = joinClasses(val)) {
- buf.push(' ' + key + '="' + val + '"');
- }
- } else {
- buf.push(exports.attr(key, val, false, terse));
- }
- }
- }
-
- return buf.join('');
- };
-
- /**
- * Escape the given string of `html`.
- *
- * @param {String} html
- * @return {String}
- * @api private
- */
-
- exports.escape = function escape(html){
- var result = String(html)
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"');
- if (result === '' + html) return html;
- else return result;
- };
-
- /**
- * Re-throw the given `err` in context to the
- * the jade in `filename` at the given `lineno`.
- *
- * @param {Error} err
- * @param {String} filename
- * @param {String} lineno
- * @api private
- */
-
- exports.rethrow = function rethrow(err, filename, lineno, str){
- if (!(err instanceof Error)) throw err;
- if ((typeof window != 'undefined' || !filename) && !str) {
- err.message += ' on line ' + lineno;
- throw err;
- }
- try {
- str = str || require('fs').readFileSync(filename, 'utf8')
- } catch (ex) {
- rethrow(err, null, lineno)
- }
- var context = 3
- , lines = str.split('\n')
- , start = Math.max(lineno - context, 0)
- , end = Math.min(lines.length, lineno + context);
-
- // Error context
- var context = lines.slice(start, end).map(function(line, i){
- var curr = i + start + 1;
- return (curr == lineno ? ' > ' : ' ')
- + curr
- + '| '
- + line;
- }).join('\n');
-
- // Alter exception message
- err.path = filename;
- err.message = (filename || 'Jade') + ':' + lineno
- + '\n' + context + '\n\n' + err.message;
- throw err;
- };
|