UNPKG

litejs

Version:

Full-stack web framework in a tiny package

423 lines (385 loc) 12 kB
!function(exports, Object) { /* jshint unused:true, eqnull:true, -W064 */ "use strict"; var getFns = Object.create(null) , setFns = Object.create(null) , filterFns = Object.create(null) , KEYS = Object.keys , FILTER_ERR = "Invalid filter: " , escRe = /['\n\r\u2028\u2029]|\\(?!x2e)/g , pathRe = /(^$|[\s\S]+?)(?:(?:\[((?:\[[^\]]+\]|[^\]])*)\]|\{([^}]*)})(?:([*^])(.*))?)?(?:\.(?=([^.]))|(?:;(.+))?$)/g , pathArgs = "i,j,I,J,K,m,p,f,r,e,t" , pattRe = /(\w+)(?::((?:(['"\/])(?:\\\3|.)*?\3[gim]*|[^;])*))?/g , reEscRe = /[.+^=:${}()|\/\\]/g , keyRe = /\[(.*?)\]/g , globRe = /\[.+?\]|[?*]/ , globReplace = /\?|(?=\*)/g , globGroup = /\[!(?=.*\])/g , primitiveRe = /^(-?(\d*\.)?\d+|true|false|null)$/ , valRe = /("|')(?:\\\1|.)*?\1|(\w*)\{((?:("|')(?:\\\4|.)*?\4|\w*\{(?:("|')(?:\\\5|.)*?\5|[^}])*?\}|.)*?)\}|([@$]?)([^,]+)/g , filterRe = /(!?)(\$?)((?:[-+:.\/\w]|\[[^\]]+\]|\{[^}]+}|\\x2e)+)(\[]|\{}|)(?:(!(?=\1)==?|(?=\1)[<>=]=?)((?:("|')(?:\\\7|.)*?\7|\w*\{(?:("|')(?:\\\8|.)*?\8|\{(?:("|')(?:\\\9|.)*?\9|[^}])*?\}|[^{"'])*?\}|[^|&()])*))?(?=[;)|&]|$)|(([;&|])\11*|([()])|.)/g , onlyFilterRe = RegExp("^(?:([@*])|" + filterRe.source.slice(0, -10) + "))+$") , cleanRe = /(\(o=d\)&&(?!.*o=o).*)\(o=d\)&&/g , fns = { "==": "a==d", "===": "a===d", ">": "a<d", ">=": "a<=d", "<": "a>d", "<=": "a>=d", "~": "typeof d==='string'&&a.test(d)" } , fnMap = { w: "Day()||7", Y: "FullYear()%100", M: "Month()+1", D: "Date()", h: "Hours()", H: "Hours()%12||12", m: "Minutes()", s: "Seconds()", S: "Milliseconds()" } , hasOwn = fns.hasOwnProperty , tmpDate = new Date() , isArray = Array.isArray exports.clone = clone exports.matcher = matcher exports.get = function(obj, pointer, fallback) { return pathFn(pointer)(obj, fallback) } exports.isObject = isObject exports.mergePatch = mergePatch exports.set = function(obj, pointer, value) { return pathFn(pointer, true)(obj, value) } exports.setForm = setForm exports.tr = tr exports.get.str = pathStr matcher.re = filterRe matcher.str = filterStr matcher.valRe = valRe exports.ext = { toNum: function(str, dec) { var out = typeof str === "string" ? parseFloat( str.replace(dec || ".", "\ufdff").replace(/[^-e\d\ufdff]/g, "").replace("\ufdff", ".") ) : NaN return out === out ? out : null }, toDate: Date.parse } function quote(str) { return "'" + (str || "").replace(escRe, escFn) + "'" } /** * JSON Merge Patch * @see https://tools.ietf.org/html/rfc7396 */ function mergePatch(target, patch, changed, previous, pointer) { var undef, key, oldVal, val, len, nextPointer if (isObject(patch)) { if (!pointer) { pointer = "" } if (!isObject(target)) { target = {} } for (key in patch) if ( undef !== (oldVal = target[key], val = patch[key]) && hasOwn.call(patch, key) && ( undef == val ? undef !== oldVal && delete target[key] : target[key] !== val ) ) { nextPointer = pointer + "/" + key.replace(/~/g, "~0").replace(/\//g, "~1") len = changed && isObject(target[key]) && changed.length if (undef != val) { target[key] = mergePatch(target[key], val, changed, previous, nextPointer) } if (len === false || changed && len != changed.length) { changed.push(nextPointer) if (previous && !isObject(oldVal)) { previous[nextPointer] = oldVal } } } } else { if (changed && isObject(target)) { val = {} for (key in target) if (hasOwn.call(target, key)) { val[key] = null } mergePatch(target, val, changed, previous, pointer) } target = patch } return target } function escFn(str) { return escape(str).replace(/%u/g, "\\u").replace(/%/g, "\\x") } function pathStr(str, set) { return ( str.charAt(0) === "/" ? str.slice(1).replace(/\./g, "\\x2e").replace(/\//g, ".").replace(/~1/g, "/").replace(/~0/g, "~") : str ) .replace(pathRe, set === true ? pathSet : pathGet) } function pathGet(str, path, arr, obj, arrExt, arrSup, dot, ext) { var v = dot ? "(o=" : "(c=" , sub = arr || obj if (sub && !(sub = onlyFilterRe.exec(sub))) throw Error(FILTER_ERR + str) v = ( sub || arrExt ? pathGet(0, path, 0, 0, 0, 0, 1) + (arr || arr === "" ? "i" : "j") + "(o)&&" + v + ( arrExt ? "f(o," + (sub ? "m(" + quote(sub[0]) + ")" : "1") + ( arrSup ? (arrExt === "*" ? ",p(" : ",r(") + quote(arrSup) + "))" : ")" ) : sub[1] ? (arr ? "o" : "K(o)") + (sub[0] === "*" ? "" : ".length") : +arr == arr ? "o[" + (arr < 0 ? "o.length" + arr : arr) + "]" : sub[0].charAt(0) === "@" ? "o[p(" + quote(sub[0].slice(1)) + ")(d)]" : (arr ? "I" : "J") + "(o,m(" + quote(sub[0]) + "))" ) + ")" : v + "o[" + quote(path) + "])" + ( arr === "" ? "&&i(c)&&c" : obj === "" ? "&&j(c)&&c" : "" ) ) + (dot ? "&&" : "") if (ext) for (; sub = pattRe.exec(ext); ) { v = "(c=e." + sub[1] + "(" + v + (sub[2] ? "," + sub[2] : "") + "))" } return v } function pathSet(str, path, arr, obj, arrExt, arrSup, dot) { var op = "o[" + quote(path) + "]" , out = "" , sub = arr || obj if (sub || arrExt) { out = "(o=" + (arr || arr === "" ? "i(" : "j(") + op + ")?" + op + ":(" + op + (arr || arr === "" ? "=[]" : "={}") +"))&&" if (arr === "-") { op = "o[o.length]" } else if (+arr == arr) { op = "o[" + (arr < 0 ? "o.length" + arr : arr) + "]" } else if (sub.charAt(0) === "@") { op = "o[p(" + quote(sub.slice(1)) + ")(d)]" } else if (!arrExt) { if (!onlyFilterRe.test(arr)) throw Error(FILTER_ERR + str) op = "o[t]" out += "(t=" + (arr ? "I" : "J") + "(o,m(" + quote(sub) + "),1))!=null&&" } } return out + ( arrExt ? "(c=f(o," + (sub ? "m(" + quote(sub) + ")" : 1) + (arrSup ? ",p(" + quote(arrSup) + ",true),v))" : ",0,v))") : dot ? "(o=typeof " + op + "==='object'&&" + op + "||(" + op + "={}))&&" : "((c=" + op + "),(" + op + "=v),c)" ) } function pathFn(str, set) { var map = set === true ? setFns : getFns return map[str] || (map[str] = Function( pathArgs, "return function(d,v,b){var c,o;return (o=d)&&" + pathStr(str, set) + (set ? ",c}": "!==void 0?c:v}") )(isArray, isObject, inArray, inObject, KEYS, matcher, pathFn, filterObj, tr, exports.ext)) } function clone(obj) { var temp, key if (obj && typeof obj == "object") { // new Date().constructor() returns a string temp = obj instanceof Date ? new Date(+obj) : obj instanceof RegExp ? RegExp(obj.source, (""+obj).split("/").pop()) : obj.constructor() for (key in obj) if (hasOwn.call(obj, key)) { temp[key] = clone(obj[key]) } obj = temp } return obj } function matcher(str, prefix, opts, getter, tmp) { var optimized , arr = [] , key = (prefix || "") + (fns[str] || filterStr(str, opts, arr, getter)) , fn = filterFns[key] if (!fn) { for (optimized = key; optimized != (optimized = optimized.replace(cleanRe, "$1")); ); fn = filterFns[key] = Function( fns[str] ? "a" : "a," + pathArgs, "return function(d,b){var o;return " + optimized + "}" ) fn.source = optimized } return fns[str] ? fn : fn( arr, isArray, isObject, inArray, inObject, KEYS, matcher, pathFn, filterObj, tr, exports.ext, tmp ) } // Date{day=1,2} // sliceable[start:stop:step] // Geo{distance=200km&lat=40&lon=-70} // ?pos=Geo{distance=200km&lat=@lat&lon=@lon} // [lon, lat] in The GeoJSON Format RFC 7946 // IP{net=127.0.0.1/30} // var re = /^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?:\.(?=.)|$)){4}$/ // ["1.2.3.4", "127.0.0.1", "192.175.255.254."].map(re.test, re) matcher.date = function(str) { return matcher(str, "(t.setTime(typeof d==='string'?Date.parse(d):+d)>=0)&&", null, dateGetter, tmpDate) } function dateGetter(name) { return "(t.get" + fnMap[name] + ")" } function filterStr(qs, opts, arr, getter) { return qs.replace(filterRe, worker).replace(/^[1&]&+|&+1?$/g, "") || "1" function worker(all, not, isOption, attr, isArray, op, val, q1, q2, q3, ext, ok2, ok1) { if (ext) { if (!ok2 && !ok1) { throw Error(FILTER_ERR + qs) } return ok1 ? ok1 : ok2 == ";" ? "&&" : ok2 + ok2 } if (isOption) { if (opts) opts[attr] = val return "1" } var idd, m, v, isRe , a = [] , pre = "(o=d)&&" attr = (getter || pathStr)(attr) if (m = attr.match(/\(c=(.*?)\)$/)) { if (m[1] == "K(o)") { pre += attr + "&&" attr = "c" } else { if (m.index) pre += attr.slice(0, m.index) attr = m[1] } } if (op == "!=" || op == "!==") { not = "!" op = op.slice(1) } if (isArray) { pre += not + (isArray === "[]" ? "i(" : "j(") + attr + ")" } if (!op) { return isArray === "" ? pre + not + attr : pre } if (op == "=" || op == "==") op += "=" if (val === "") val="''" for (; m = valRe.exec(val); ) { // quote, extension, subquery, subQuote, subSubQuote, at // Parameterized query ?name=$name|name=:name isRe = 0 v = m[6] == "$" ? "b['"+ m[7] +"']" : arrIdx(arr, m[1] || m[3] ? m[0].slice(m[3] ? m[2].length + 1 : 1, -1) : m[6] ? m[7] : primitiveRe.test(m[0]) ? exports.parse(m[0]) : (isRe = globRe.test(m[0])) ? RegExp( "^" + m[0] .replace(reEscRe, "\\$&") .replace(globReplace, ".") .replace(globGroup, "[^") + "$", op === "==" ? "i" : "" ) : m[0] ) idd = ( m[2] ? "m." + m[2].toLowerCase() : m[3] ? "m" : isArray || attr === "c" ? arrIdx(arr, matcher(isRe ? "~" : op)) : "" ) + "(" + v a.push( isArray || attr === "c" ? (isArray == "{}" ? "J(" : "I(") + attr + "," + idd + "))" : m[2] || m[3] ? idd + ")(" + attr + ")" : isRe ? "typeof " + attr + "==='string'&&" + v + ".test(" + attr + ")" : m[6] ? attr + "!==void 0&&" + attr + op + ( m[6] == "$" ? "b['"+ m[7] +"']" : "p(" + v + ")(o)" ) : attr + op + v ) } return pre + ( isArray ? (not ? "||" : "&&") : "" ) + not + "(" + a.join("||") + ")" } } function arrIdx(arr, val) { for ( var i = arr.length; 0 <= --i && !( arr[i] === val || val && val.source && val.source === arr[i].source ); ); return "a[" + (-1 < i ? i : arr.push(val) - 1) + "]" } function setForm(map, key_, val) { for (var match, key = key_, step = map; match = keyRe.exec(key_); ) { if (step === map) key = key.slice(0, match.index) match = match[1] step = step[key] || ( step[key] = match && +match != match ? {} : [] ) key = match } if (isArray(step)) { step.push(val) } else if (isArray(step[key])) { step[key].push(val) } else { step[key] = step[key] != null ? [step[key], val] : val } } function tr(attrs, aclFn) { var attr, tmp , arr = [] , map = {} , i = 0 for (; attr = valRe.exec(attrs); ) { tmp = attr[0].split(":") exports.set(map, tmp[0], i) arr[i++] = pathFn(tmp[1] ? attr[0].slice(tmp[0].length+1) : tmp[0]) } return Function( "g,a", "return function(o,a){return " + exports.stringify(map).replace(/:(\d+)/g,":g[$1](o)") + "}" )(arr, aclFn) } function isObject(obj) { return !!obj && obj.constructor === Object } function inArray(a, fn, idx) { for (var i = -1, len = a.length; ++i < len; ) { if (fn(a[i])) return idx == null ? a[i] : i } return idx != null && len } function inObject(o, fn, idx) { for (var key in o) { if (fn(o[key])) return idx == null ? o[key] : key } return null } function filterObj(a, match, get, val) { var out = [] , i = -1 , len = a.length if (isObject(a)) { for (i in a) if (hasOwn.call(a, i) && (match === 1 || match(a[i]))) { out.push(get ? get(a[i], val) : a[i]) if (get === 0) a[i] = val } } else { for (; ++i < len; ) if (match === 1 || match(a[i])) { out.push(get ? get(a[i], val) : a[i]) if (get === 0) a[i] = val } } return out } // `this` refers to the `window` in browser and to the `exports` in Node.js. }(JSON, Object) // jshint ignore:line