bem-xjst
Version:
Declarative Template Engine for the browser and server
256 lines (208 loc) • 5.09 kB
JavaScript
var amp = '&';
var lt = '<';
var gt = '>';
var quot = '"';
var singleQuot = ''';
var matchXmlRegExp = /[&<>]/;
function isEmpty(string) {
return typeof string === 'undefined' ||
string === null ||
(typeof string === 'number' && isNaN(string));
}
exports.xmlEscape = function(string) {
if (isEmpty(string))
return '';
var str = '' + string;
var match = matchXmlRegExp.exec(str);
if (!match)
return str;
var escape;
var html = '';
var index = 0;
var lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 38: // &
escape = amp;
break;
case 60: // <
escape = lt;
break;
case 62: // >
escape = gt;
break;
default:
continue;
}
if (lastIndex !== index)
html += str.substring(lastIndex, index);
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index ?
html + str.substring(lastIndex, index) :
html;
};
var matchAttrRegExp = /["&<>]/;
exports.attrEscape = function(string) {
if (isEmpty(string))
return '';
var str = '' + string;
var match = matchAttrRegExp.exec(str);
if (!match)
return str;
var escape;
var html = '';
var index = 0;
var lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 34: // "
escape = quot;
break;
case 38: // &
escape = amp;
break;
case 60: // <
escape = lt;
break;
case 62: // >
escape = gt;
break;
default:
continue;
}
if (lastIndex !== index)
html += str.substring(lastIndex, index);
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index ?
html + str.substring(lastIndex, index) :
html;
};
var matchJsAttrRegExp = /['&]/;
exports.jsAttrEscape = function(string) {
if (isEmpty(string))
return '';
var str = '' + string;
var match = matchJsAttrRegExp.exec(str);
if (!match)
return str;
var escape;
var html = '';
var index = 0;
var lastIndex = 0;
for (index = match.index; index < str.length; index++) {
switch (str.charCodeAt(index)) {
case 38: // &
escape = amp;
break;
case 39: // '
escape = singleQuot;
break;
default:
continue;
}
if (lastIndex !== index)
html += str.substring(lastIndex, index);
lastIndex = index + 1;
html += escape;
}
return lastIndex !== index ?
html + str.substring(lastIndex, index) :
html;
};
exports.extend = function(o1, o2) {
if (!o1 || !o2)
return o1 || o2;
var res = {};
var n;
for (n in o1)
/* istanbul ignore else */
if (o1.hasOwnProperty(n))
res[n] = o1[n];
for (n in o2)
/* istanbul ignore else */
if (o2.hasOwnProperty(n))
res[n] = o2[n];
return res;
};
var SHORT_TAGS = { // hash for quick check if tag short
area: 1, base: 1, br: 1, col: 1, command: 1, embed: 1, hr: 1, img: 1,
input: 1, keygen: 1, link: 1, meta: 1, param: 1, source: 1, wbr: 1
};
exports.isShortTag = function(t) {
return SHORT_TAGS.hasOwnProperty(t);
};
exports.isSimple = function isSimple(obj) {
if (!obj ||
obj === true ||
typeof obj === 'string' ||
typeof obj === 'number')
return true;
if (!obj.block &&
!obj.elem &&
!obj.tag &&
!obj.cls &&
!obj.attrs &&
obj.hasOwnProperty('html') &&
isSimple(obj.html))
return true;
return false;
};
exports.isObj = function(val) {
return val && typeof val === 'object' && !Array.isArray(val) &&
val !== null;
};
var uniqCount = 0;
var uniqId = +new Date();
var uniqExpando = '__' + uniqId;
var uniqPrefix = 'uniq' + uniqId;
function getUniq() {
return uniqPrefix + (++uniqCount);
}
exports.getUniq = getUniq;
exports.identify = function(obj, onlyGet) {
if (!obj)
return getUniq();
if (onlyGet || obj[uniqExpando])
return obj[uniqExpando];
var u = getUniq();
obj[uniqExpando] = u;
return u;
};
exports.fnToString = function(code) {
// It is fine to compile without templates at first
if (!code)
return '';
if (typeof code === 'function') {
// Examples for regular function
// function () { … }
// function name() { … }
// function (a, b) { … }
// function name(a, b) { … }
//
// Examples for arrow function
// () => { … }
// (a, b) => { … }
// _ => { … }
code = code.toString();
code = code.replace(
code.indexOf('function') === 0 ?
/^function\s*[^{]+{|}$/g :
/^(_|\(\w|[^=>]+\))\s=>\s{|}$/g,
'');
}
return code;
};
/**
* regexp for check may attribute be unquoted
*
* https://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.2
* https://www.w3.org/TR/html5/syntax.html#attributes
*/
var UNQUOTED_ATTR_REGEXP = /^[:\w.-]+$/;
exports.isUnquotedAttr = function(str) {
return str && UNQUOTED_ATTR_REGEXP.exec(str);
};