mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-21 07:50:37 +01:00
Merge branch 'master' into develop
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
(function (module) {
|
||||
'use strict';
|
||||
var utils;
|
||||
var fs;
|
||||
var XRegExp;
|
||||
|
||||
var utils, fs, XRegExp;
|
||||
|
||||
if ('undefined' === typeof window) {
|
||||
if (typeof window === 'undefined') {
|
||||
fs = require('fs');
|
||||
XRegExp = require('xregexp');
|
||||
|
||||
@@ -13,24 +15,23 @@
|
||||
|
||||
process.elapsedTimeSince = function (start) {
|
||||
var diff = process.hrtime(start);
|
||||
return diff[0] * 1e3 + diff[1] / 1e6;
|
||||
return (diff[0] * 1e3) + (diff[1] / 1e6);
|
||||
};
|
||||
|
||||
} else {
|
||||
XRegExp = window.XRegExp;
|
||||
}
|
||||
|
||||
|
||||
module.exports = utils = {
|
||||
utils = {
|
||||
generateUUID: function () {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0,
|
||||
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
var r = Math.random() * 16 | 0;
|
||||
var v = c === 'x' ? r : ((r & 0x3) | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
|
||||
//Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
|
||||
// Adapted from http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search
|
||||
walk: function (dir, done) {
|
||||
var results = [];
|
||||
|
||||
@@ -56,13 +57,15 @@
|
||||
}
|
||||
|
||||
results = results.concat(res);
|
||||
if (!--pending) {
|
||||
pending -= 1;
|
||||
if (!pending) {
|
||||
done(null, results);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
results.push(file);
|
||||
if (!--pending) {
|
||||
pending -= 1;
|
||||
if (!pending) {
|
||||
done(null, results);
|
||||
}
|
||||
}
|
||||
@@ -81,13 +84,13 @@
|
||||
isLatin: /^[\w\d\s.,\-@]+$/,
|
||||
languageKeyRegex: /\[\[[\w]+:.+\]\]/,
|
||||
|
||||
//http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
|
||||
// http://dense13.com/blog/2009/05/03/converting-string-to-slug-javascript/
|
||||
slugify: function (str, preserveCase) {
|
||||
if (!str) {
|
||||
return '';
|
||||
}
|
||||
str = str.replace(utils.trimRegex, '');
|
||||
if(utils.isLatin.test(str)) {
|
||||
if (utils.isLatin.test(str)) {
|
||||
str = str.replace(utils.invalidLatinChars, '-');
|
||||
} else {
|
||||
str = XRegExp.replace(str, utils.invalidUnicodeChars, '-');
|
||||
@@ -108,7 +111,7 @@
|
||||
tag = tag.trim().toLowerCase();
|
||||
// see https://github.com/NodeBB/NodeBB/issues/4378
|
||||
tag = tag.replace(/\u202E/gi, '');
|
||||
tag = tag.replace(/[,\/#!$%\^\*;:{}=_`<>'"~()?\|]/g, '');
|
||||
tag = tag.replace(/[,/#!$%^*;:{}=_`<>'"~()?|]/g, '');
|
||||
tag = tag.substr(0, maxLength || 15).trim();
|
||||
var matches = tag.match(/^[.-]*(.+?)[.-]*$/);
|
||||
if (matches && matches.length > 1) {
|
||||
@@ -118,7 +121,7 @@
|
||||
},
|
||||
|
||||
removePunctuation: function (str) {
|
||||
return str.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`<>'"~()?]/g, '');
|
||||
return str.replace(/[.,-/#!$%^&*;:{}=\-_`<>'"~()?]/g, '');
|
||||
},
|
||||
|
||||
isEmailValid: function (email) {
|
||||
@@ -126,7 +129,7 @@
|
||||
},
|
||||
|
||||
isUserNameValid: function (name) {
|
||||
return (name && name !== '' && (/^['"\s\-\+.*0-9\u00BF-\u1FFF\u2C00-\uD7FF\w]+$/.test(name)));
|
||||
return (name && name !== '' && (/^['"\s\-+.*0-9\u00BF-\u1FFF\u2C00-\uD7FF\w]+$/.test(name)));
|
||||
},
|
||||
|
||||
isPasswordValid: function (password) {
|
||||
@@ -143,11 +146,13 @@
|
||||
|
||||
// shallow objects merge
|
||||
merge: function () {
|
||||
var result = {}, obj, keys;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var result = {};
|
||||
var obj;
|
||||
var keys;
|
||||
for (var i = 0; i < arguments.length; i += 1) {
|
||||
obj = arguments[i] || {};
|
||||
keys = Object.keys(obj);
|
||||
for (var j = 0; j < keys.length; j++) {
|
||||
for (var j = 0; j < keys.length; j += 1) {
|
||||
result[keys[j]] = obj[keys[j]];
|
||||
}
|
||||
}
|
||||
@@ -159,29 +164,29 @@
|
||||
},
|
||||
|
||||
extensionMimeTypeMap: {
|
||||
"bmp": "image/bmp",
|
||||
"cmx": "image/x-cmx",
|
||||
"cod": "image/cis-cod",
|
||||
"gif": "image/gif",
|
||||
"ico": "image/x-icon",
|
||||
"ief": "image/ief",
|
||||
"jfif": "image/pipeg",
|
||||
"jpe": "image/jpeg",
|
||||
"jpeg": "image/jpeg",
|
||||
"jpg": "image/jpeg",
|
||||
"png": "image/png",
|
||||
"pbm": "image/x-portable-bitmap",
|
||||
"pgm": "image/x-portable-graymap",
|
||||
"pnm": "image/x-portable-anymap",
|
||||
"ppm": "image/x-portable-pixmap",
|
||||
"ras": "image/x-cmu-raster",
|
||||
"rgb": "image/x-rgb",
|
||||
"svg": "image/svg+xml",
|
||||
"tif": "image/tiff",
|
||||
"tiff": "image/tiff",
|
||||
"xbm": "image/x-xbitmap",
|
||||
"xpm": "image/x-xpixmap",
|
||||
"xwd": "image/x-xwindowdump"
|
||||
bmp: 'image/bmp',
|
||||
cmx: 'image/x-cmx',
|
||||
cod: 'image/cis-cod',
|
||||
gif: 'image/gif',
|
||||
ico: 'image/x-icon',
|
||||
ief: 'image/ief',
|
||||
jfif: 'image/pipeg',
|
||||
jpe: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
jpg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
pbm: 'image/x-portable-bitmap',
|
||||
pgm: 'image/x-portable-graymap',
|
||||
pnm: 'image/x-portable-anymap',
|
||||
ppm: 'image/x-portable-pixmap',
|
||||
ras: 'image/x-cmu-raster',
|
||||
rgb: 'image/x-rgb',
|
||||
svg: 'image/svg+xml',
|
||||
tif: 'image/tiff',
|
||||
tiff: 'image/tiff',
|
||||
xbm: 'image/x-xbitmap',
|
||||
xpm: 'image/x-xpixmap',
|
||||
xwd: 'image/x-xwindowdump',
|
||||
},
|
||||
|
||||
fileMimeType: function (path) {
|
||||
@@ -205,13 +210,12 @@
|
||||
|
||||
makeNumberHumanReadable: function (num) {
|
||||
var n = parseInt(num, 10);
|
||||
if(!n) {
|
||||
if (!n) {
|
||||
return num;
|
||||
}
|
||||
if (n > 999999) {
|
||||
return (n / 1000000).toFixed(1) + 'm';
|
||||
}
|
||||
else if(n > 999) {
|
||||
} else if (n > 999) {
|
||||
return (n / 1000).toFixed(1) + 'k';
|
||||
}
|
||||
return n;
|
||||
@@ -225,7 +229,7 @@
|
||||
|
||||
// takes a string like 1000 and returns 1,000
|
||||
addCommas: function (text) {
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
|
||||
return text.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');
|
||||
},
|
||||
|
||||
toISOString: function (timestamp) {
|
||||
@@ -236,9 +240,9 @@
|
||||
return Date.prototype.toISOString ? new Date(parseInt(timestamp, 10)).toISOString() : timestamp;
|
||||
},
|
||||
|
||||
tags : ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'],
|
||||
tags: ['a', 'abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'b', 'base', 'basefont', 'bdi', 'bdo', 'big', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend', 'li', 'link', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noframes', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'],
|
||||
|
||||
stripTags : ['abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'base', 'basefont',
|
||||
stripTags: ['abbr', 'acronym', 'address', 'applet', 'area', 'article', 'aside', 'audio', 'base', 'basefont',
|
||||
'bdi', 'bdo', 'big', 'blink', 'body', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup',
|
||||
'command', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'em', 'embed',
|
||||
'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
||||
@@ -249,11 +253,11 @@
|
||||
'th', 'thead', 'time', 'title', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'],
|
||||
|
||||
escapeRegexChars: function (text) {
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
},
|
||||
|
||||
escapeHTML: function (raw) {
|
||||
return raw.replace(/&/gm,"&").replace(/</gm,"<").replace(/>/gm,">");
|
||||
return raw.replace(/&/gm, '&').replace(/</gm, '<').replace(/>/gm, '>');
|
||||
},
|
||||
|
||||
isAndroidBrowser: function () {
|
||||
@@ -267,13 +271,13 @@
|
||||
},
|
||||
|
||||
findBootstrapEnvironment: function () {
|
||||
//http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api
|
||||
var envs = ['xs', 'sm', 'md', 'lg'],
|
||||
$el = $('<div>');
|
||||
// http://stackoverflow.com/questions/14441456/how-to-detect-which-device-view-youre-on-using-twitter-bootstrap-api
|
||||
var envs = ['xs', 'sm', 'md', 'lg'];
|
||||
var $el = $('<div>');
|
||||
|
||||
$el.appendTo($('body'));
|
||||
|
||||
for (var i = envs.length - 1; i >= 0; i--) {
|
||||
for (var i = envs.length - 1; i >= 0; i -= 1) {
|
||||
var env = envs[i];
|
||||
|
||||
$el.addClass('hidden-' + env);
|
||||
@@ -292,10 +296,10 @@
|
||||
},
|
||||
|
||||
getHoursArray: function () {
|
||||
var currentHour = new Date().getHours(),
|
||||
labels = [];
|
||||
var currentHour = new Date().getHours();
|
||||
var labels = [];
|
||||
|
||||
for (var i = currentHour, ii = currentHour - 24; i > ii; i--) {
|
||||
for (var i = currentHour, ii = currentHour - 24; i > ii; i -= 1) {
|
||||
var hour = i < 0 ? 24 + i : i;
|
||||
labels.push(hour + ':00');
|
||||
}
|
||||
@@ -304,12 +308,12 @@
|
||||
},
|
||||
|
||||
getDaysArray: function (from) {
|
||||
var currentDay = new Date(from || Date.now()).getTime(),
|
||||
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
labels = [],
|
||||
tmpDate;
|
||||
var currentDay = new Date(from || Date.now()).getTime();
|
||||
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||
var labels = [];
|
||||
var tmpDate;
|
||||
|
||||
for(var x = 29; x >= 0; x--) {
|
||||
for (var x = 29; x >= 0; x -= 1) {
|
||||
tmpDate = new Date(currentDay - (1000 * 60 * 60 * 24 * x));
|
||||
labels.push(months[tmpDate.getMonth()] + ' ' + tmpDate.getDate());
|
||||
}
|
||||
@@ -319,8 +323,8 @@
|
||||
|
||||
/* Retrieved from http://stackoverflow.com/a/7557433 @ 27 Mar 2016 */
|
||||
isElementInViewport: function (el) {
|
||||
//special bonus for those using jQuery
|
||||
if (typeof jQuery === "function" && el instanceof jQuery) {
|
||||
// special bonus for those using jQuery
|
||||
if (typeof jQuery === 'function' && el instanceof jQuery) {
|
||||
el = el[0];
|
||||
}
|
||||
|
||||
@@ -329,14 +333,16 @@
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
|
||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
|
||||
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /* or $(window).height() */
|
||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */
|
||||
);
|
||||
},
|
||||
|
||||
// get all the url params in a single key/value hash
|
||||
params: function (options) {
|
||||
var a, hash = {}, params;
|
||||
var a;
|
||||
var hash = {};
|
||||
var params;
|
||||
|
||||
options = options || {};
|
||||
options.skipToType = options.skipToType || {};
|
||||
@@ -344,12 +350,12 @@
|
||||
if (options.url) {
|
||||
a = utils.urlToLocation(options.url);
|
||||
}
|
||||
params = (a ? a.search : window.location.search).substring(1).split("&");
|
||||
params = (a ? a.search : window.location.search).substring(1).split('&');
|
||||
|
||||
params.forEach(function (param) {
|
||||
var val = param.split('='),
|
||||
key = decodeURI(val[0]),
|
||||
value = options.skipToType[key] ? decodeURI(val[1]) : utils.toType(decodeURI(val[1]));
|
||||
var val = param.split('=');
|
||||
var key = decodeURI(val[0]);
|
||||
var value = options.skipToType[key] ? decodeURI(val[1]) : utils.toType(decodeURI(val[1]));
|
||||
|
||||
if (key) {
|
||||
if (key.substr(-2, 2) === '[]') {
|
||||
@@ -383,25 +389,24 @@
|
||||
toType: function (str) {
|
||||
var type = typeof str;
|
||||
if (type !== 'string') {
|
||||
return str;
|
||||
} else {
|
||||
var nb = parseFloat(str);
|
||||
if (!isNaN(nb) && isFinite(str)) {
|
||||
return nb;
|
||||
}
|
||||
if (str === 'false') {
|
||||
return false;
|
||||
}
|
||||
if (str === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
str = JSON.parse(str);
|
||||
} catch (e) {}
|
||||
|
||||
return str;
|
||||
}
|
||||
var nb = parseFloat(str);
|
||||
if (!isNaN(nb) && isFinite(str)) {
|
||||
return nb;
|
||||
}
|
||||
if (str === 'false') {
|
||||
return false;
|
||||
}
|
||||
if (str === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
str = JSON.parse(str);
|
||||
} catch (e) {}
|
||||
|
||||
return str;
|
||||
},
|
||||
|
||||
// Safely get/set chained properties on an object
|
||||
@@ -410,23 +415,23 @@
|
||||
// get example: utils.props(A, 'a.b.c.foo.bar') // returns undefined without throwing a TypeError
|
||||
// credits to github.com/gkindel
|
||||
props: function (obj, props, value) {
|
||||
if(obj === undefined) {
|
||||
if (obj === undefined) {
|
||||
obj = window;
|
||||
}
|
||||
if(props == null) {
|
||||
if (props == null) {
|
||||
return undefined;
|
||||
}
|
||||
var i = props.indexOf('.');
|
||||
if( i == -1 ) {
|
||||
if(value !== undefined) {
|
||||
if (i === -1) {
|
||||
if (value !== undefined) {
|
||||
obj[props] = value;
|
||||
}
|
||||
return obj[props];
|
||||
}
|
||||
var prop = props.slice(0, i),
|
||||
newProps = props.slice(i + 1);
|
||||
var prop = props.slice(0, i);
|
||||
var newProps = props.slice(i + 1);
|
||||
|
||||
if(props !== undefined && !(obj[prop] instanceof Object) ) {
|
||||
if (props !== undefined && !(obj[prop] instanceof Object)) {
|
||||
obj[prop] = {};
|
||||
}
|
||||
|
||||
@@ -439,47 +444,43 @@
|
||||
targetLocation.host === referenceLocation.host && targetLocation.protocol === referenceLocation.protocol && // Otherwise need to check if protocol and host match
|
||||
(relative_path.length > 0 ? targetLocation.pathname.indexOf(relative_path) === 0 : true) // Subfolder installs need this additional check
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if (typeof String.prototype.startsWith != 'function') {
|
||||
module.exports = utils;
|
||||
if (typeof window !== 'undefined') {
|
||||
window.utils = module.exports;
|
||||
}
|
||||
|
||||
/* eslint "no-extend-native": "off" */
|
||||
if (typeof String.prototype.startsWith !== 'function') {
|
||||
String.prototype.startsWith = function (prefix) {
|
||||
if (this.length < prefix.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = prefix.length - 1; (i >= 0) && (this[i] === prefix[i]); --i) {
|
||||
continue;
|
||||
}
|
||||
return i < 0;
|
||||
return this.slice(0, prefix.length) === prefix;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.endsWith != 'function') {
|
||||
if (typeof String.prototype.endsWith !== 'function') {
|
||||
String.prototype.endsWith = function (suffix) {
|
||||
if (this.length < suffix.length) {
|
||||
return false;
|
||||
}
|
||||
var len = this.length;
|
||||
var suffixLen = suffix.length;
|
||||
for (var i = 1; (i <= suffixLen && this[len - i] === suffix[suffixLen - i]); ++i) {
|
||||
continue;
|
||||
if (suffix.length === 0) {
|
||||
return true;
|
||||
}
|
||||
return i > suffixLen;
|
||||
return this.slice(-suffix.length) === suffix;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.rtrim != 'function') {
|
||||
if (typeof String.prototype.rtrim !== 'function') {
|
||||
String.prototype.rtrim = function () {
|
||||
return this.replace(/\s+$/g, '');
|
||||
};
|
||||
}
|
||||
|
||||
if ('undefined' !== typeof window) {
|
||||
window.utils = module.exports;
|
||||
}
|
||||
|
||||
}('undefined' === typeof module ? {
|
||||
}(typeof module === 'undefined' ? {
|
||||
module: {
|
||||
exports: {}
|
||||
}
|
||||
exports: {},
|
||||
},
|
||||
} : module));
|
||||
|
||||
Reference in New Issue
Block a user