Remove string.js dependency

v1.18.x
Peter Jaszkowiak 7 years ago
parent f9a1951ec5
commit 46fafb20b9

@ -90,7 +90,6 @@
"socket.io-redis": "5.2.0",
"socketio-wildcard": "2.0.0",
"spdx-license-list": "^3.0.1",
"string": "^3.3.3",
"toobusy-js": "^0.5.1",
"uglify-js": "^3.1.3",
"validator": "9.0.0",

@ -3,13 +3,13 @@
(function (factory) {
if (typeof module === 'object' && module.exports) {
var relative_path = require('nconf').get('relative_path');
module.exports = factory(require('../utils'), require('benchpressjs'), require('string'), relative_path);
module.exports = factory(require('../utils'), require('benchpressjs'), relative_path);
} else if (typeof define === 'function' && define.amd) {
define('helpers', ['benchpress', 'string'], function (Benchpress, string) {
return factory(utils, Benchpress, string, config.relative_path);
define('helpers', ['benchpress'], function (Benchpress) {
return factory(utils, Benchpress, config.relative_path);
});
}
}(function (utils, Benchpress, S, relative_path) {
}(function (utils, Benchpress, relative_path) {
var helpers = {
displayMenuItem: displayMenuItem,
buildMetaTag: buildMetaTag,
@ -92,7 +92,7 @@
}
function stripTags(str) {
return S(String(str)).stripTags().s;
return utils.stripHTMLTags(str);
}
function generateCategoryBackground(category) {

File diff suppressed because one or more lines are too long

@ -10,8 +10,8 @@
}
if (typeof define === 'function' && define.amd) {
// AMD. Register as a named module
define('translator', ['string'], function (string) {
return factory(string, loadClient, warn);
define('translator', [], function () {
return factory(utils, loadClient, warn);
});
} else if (typeof module === 'object' && module.exports) {
// Node
@ -37,15 +37,23 @@
});
}
module.exports = factory(require('string'), loadServer, warn);
module.exports = factory(require('../utils'), loadServer, warn);
}());
} else {
window.translator = factory(window.string, loadClient, warn);
}
}(function (string, load, warn) {
}(function (utils, load, warn) {
var assign = Object.assign || jQuery.extend;
function classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function escapeHTML(str) {
return utils.decodeHTMLEntities(
String(str)
.replace(/[\s\xa0]+/g, ' ')
.replace(/^\s+|\s+$/g, '')
).replace(/[<>]/g, function (c) {
return c === '<' ? '&lt;' : '&gt;';
});
}
var Translator = (function () {
/**
* Construct a new Translator object
@ -284,9 +292,7 @@
}
var argsToTranslate = args.map(function (arg) {
return string(arg).collapseWhitespace().decodeHTMLEntities().escapeHTML().s.replace(/&amp;/g, '&');
}).map(function (arg) {
return self.translate(arg);
return self.translate(escapeHTML(arg));
});
return Promise.all(argsToTranslate).then(function (translatedArgs) {
@ -539,12 +545,13 @@
return cb('');
}
Translator.create(lang).translate(text).catch(function (err) {
return Translator.create(lang).translate(text).then(function (output) {
if (cb) {
setTimeout(cb, 0, output);
}
return output;
}, function (err) {
warn('Translation failed: ' + err.stack);
}).then(function (output) {
cb(output);
}).catch(function (err) {
console.error(err);
});
},

@ -25,6 +25,279 @@
window.utils = factory(window.XRegExp);
}
}(function (XRegExp) {
var freeze = Object.freeze || function (obj) { return obj; };
// add default escape function for escaping HTML entities
var escapeCharMap = freeze({
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#x27;',
'`': '&#x60;',
'=': '&#x3D;',
});
function replaceChar(c) {
return escapeCharMap[c];
}
var escapeChars = /[&<>"'`=]/g;
var HTMLEntities = freeze({
amp: '&',
gt: '>',
lt: '<',
quot: '"',
apos: "'",
AElig: 198,
Aacute: 193,
Acirc: 194,
Agrave: 192,
Aring: 197,
Atilde: 195,
Auml: 196,
Ccedil: 199,
ETH: 208,
Eacute: 201,
Ecirc: 202,
Egrave: 200,
Euml: 203,
Iacute: 205,
Icirc: 206,
Igrave: 204,
Iuml: 207,
Ntilde: 209,
Oacute: 211,
Ocirc: 212,
Ograve: 210,
Oslash: 216,
Otilde: 213,
Ouml: 214,
THORN: 222,
Uacute: 218,
Ucirc: 219,
Ugrave: 217,
Uuml: 220,
Yacute: 221,
aacute: 225,
acirc: 226,
aelig: 230,
agrave: 224,
aring: 229,
atilde: 227,
auml: 228,
ccedil: 231,
eacute: 233,
ecirc: 234,
egrave: 232,
eth: 240,
euml: 235,
iacute: 237,
icirc: 238,
igrave: 236,
iuml: 239,
ntilde: 241,
oacute: 243,
ocirc: 244,
ograve: 242,
oslash: 248,
otilde: 245,
ouml: 246,
szlig: 223,
thorn: 254,
uacute: 250,
ucirc: 251,
ugrave: 249,
uuml: 252,
yacute: 253,
yuml: 255,
copy: 169,
reg: 174,
nbsp: 160,
iexcl: 161,
cent: 162,
pound: 163,
curren: 164,
yen: 165,
brvbar: 166,
sect: 167,
uml: 168,
ordf: 170,
laquo: 171,
not: 172,
shy: 173,
macr: 175,
deg: 176,
plusmn: 177,
sup1: 185,
sup2: 178,
sup3: 179,
acute: 180,
micro: 181,
para: 182,
middot: 183,
cedil: 184,
ordm: 186,
raquo: 187,
frac14: 188,
frac12: 189,
frac34: 190,
iquest: 191,
times: 215,
divide: 247,
'OElig;': 338,
'oelig;': 339,
'Scaron;': 352,
'scaron;': 353,
'Yuml;': 376,
'fnof;': 402,
'circ;': 710,
'tilde;': 732,
'Alpha;': 913,
'Beta;': 914,
'Gamma;': 915,
'Delta;': 916,
'Epsilon;': 917,
'Zeta;': 918,
'Eta;': 919,
'Theta;': 920,
'Iota;': 921,
'Kappa;': 922,
'Lambda;': 923,
'Mu;': 924,
'Nu;': 925,
'Xi;': 926,
'Omicron;': 927,
'Pi;': 928,
'Rho;': 929,
'Sigma;': 931,
'Tau;': 932,
'Upsilon;': 933,
'Phi;': 934,
'Chi;': 935,
'Psi;': 936,
'Omega;': 937,
'alpha;': 945,
'beta;': 946,
'gamma;': 947,
'delta;': 948,
'epsilon;': 949,
'zeta;': 950,
'eta;': 951,
'theta;': 952,
'iota;': 953,
'kappa;': 954,
'lambda;': 955,
'mu;': 956,
'nu;': 957,
'xi;': 958,
'omicron;': 959,
'pi;': 960,
'rho;': 961,
'sigmaf;': 962,
'sigma;': 963,
'tau;': 964,
'upsilon;': 965,
'phi;': 966,
'chi;': 967,
'psi;': 968,
'omega;': 969,
'thetasym;': 977,
'upsih;': 978,
'piv;': 982,
'ensp;': 8194,
'emsp;': 8195,
'thinsp;': 8201,
'zwnj;': 8204,
'zwj;': 8205,
'lrm;': 8206,
'rlm;': 8207,
'ndash;': 8211,
'mdash;': 8212,
'lsquo;': 8216,
'rsquo;': 8217,
'sbquo;': 8218,
'ldquo;': 8220,
'rdquo;': 8221,
'bdquo;': 8222,
'dagger;': 8224,
'Dagger;': 8225,
'bull;': 8226,
'hellip;': 8230,
'permil;': 8240,
'prime;': 8242,
'Prime;': 8243,
'lsaquo;': 8249,
'rsaquo;': 8250,
'oline;': 8254,
'frasl;': 8260,
'euro;': 8364,
'image;': 8465,
'weierp;': 8472,
'real;': 8476,
'trade;': 8482,
'alefsym;': 8501,
'larr;': 8592,
'uarr;': 8593,
'rarr;': 8594,
'darr;': 8595,
'harr;': 8596,
'crarr;': 8629,
'lArr;': 8656,
'uArr;': 8657,
'rArr;': 8658,
'dArr;': 8659,
'hArr;': 8660,
'forall;': 8704,
'part;': 8706,
'exist;': 8707,
'empty;': 8709,
'nabla;': 8711,
'isin;': 8712,
'notin;': 8713,
'ni;': 8715,
'prod;': 8719,
'sum;': 8721,
'minus;': 8722,
'lowast;': 8727,
'radic;': 8730,
'prop;': 8733,
'infin;': 8734,
'ang;': 8736,
'and;': 8743,
'or;': 8744,
'cap;': 8745,
'cup;': 8746,
'int;': 8747,
'there4;': 8756,
'sim;': 8764,
'cong;': 8773,
'asymp;': 8776,
'ne;': 8800,
'equiv;': 8801,
'le;': 8804,
'ge;': 8805,
'sub;': 8834,
'sup;': 8835,
'nsub;': 8836,
'sube;': 8838,
'supe;': 8839,
'oplus;': 8853,
'otimes;': 8855,
'perp;': 8869,
'sdot;': 8901,
'lceil;': 8968,
'rceil;': 8969,
'lfloor;': 8970,
'rfloor;': 8971,
'lang;': 9001,
'rang;': 9002,
'loz;': 9674,
'spades;': 9824,
'clubs;': 9827,
'hearts;': 9829,
'diams;': 9830,
});
var utils = {
generateUUID: function () {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
@ -33,6 +306,35 @@
return v.toString(16);
});
},
// https://github.com/substack/node-ent/blob/master/index.js
decodeHTMLEntities: function (html) {
return String(html)
.replace(/&#(\d+);?/g, function (_, code) {
return String.fromCharCode(code);
})
.replace(/&#[xX]([A-Fa-f0-9]+);?/g, function (_, hex) {
return String.fromCharCode(parseInt(hex, 16));
})
.replace(/&([^;\W]+;?)/g, function (m, e) {
var ee = e.replace(/;$/, '');
var target = HTMLEntities[e] || (e.match(/;$/) && HTMLEntities[ee]);
if (typeof target === 'number') {
return String.fromCharCode(target);
} else if (typeof target === 'string') {
return target;
}
return m;
});
},
// https://github.com/jprichardson/string.js/blob/master/lib/string.js
stripHTMLTags: function (str, tags) {
var pattern = (tags || ['']).map(function (tag) {
return utils.escapeRegexChars(tag);
}).join('|');
return String(str).replace(new RegExp('</?(?:' + pattern + ')[^<>]*>', 'gi'), '');
},
invalidUnicodeChars: XRegExp('[^\\p{L}\\s\\d\\-_]', 'g'),
invalidLatinChars: /[^\w\s\d\-_]/g,
@ -232,8 +534,15 @@
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
},
escapeHTML: function (raw) {
return raw.replace(/&/gm, '&amp;').replace(/</gm, '&lt;').replace(/>/gm, '&gt;');
escapeHTML: function (str) {
if (str == null) {
return '';
}
if (!str) {
return String(str);
}
return str.toString().replace(escapeChars, replaceChar);
},
isAndroidBrowser: function () {

@ -2,7 +2,6 @@
var nconf = require('nconf');
var async = require('async');
var S = require('string');
var user = require('../../user');
var posts = require('../../posts');
@ -13,6 +12,7 @@ var helpers = require('../helpers');
var pagination = require('../../pagination');
var messaging = require('../../messaging');
var translator = require('../../translator');
var utils = require('../../utils');
var profileController = module.exports;
@ -87,7 +87,7 @@ profileController.get = function (req, res, callback) {
userData.profileviews = 1;
}
var plainAboutMe = userData.aboutme ? S(userData.aboutme).decodeHTMLEntities().stripTags().s : '';
var plainAboutMe = userData.aboutme ? utils.stripHTMLTags(utils.decodeHTMLEntities(userData.aboutme)) : '';
res.locals.metaTags = [
{

@ -2,7 +2,6 @@
var async = require('async');
var S = require('string');
var nconf = require('nconf');
var user = require('../user');
@ -217,7 +216,7 @@ function addTags(topicData, req, res) {
var postAtIndex = findPost(Math.max(0, req.params.post_index - 1));
if (postAtIndex && postAtIndex.content) {
description = S(postAtIndex.content).decodeHTMLEntities().stripTags().s;
description = utils.stripHTMLTags(utils.decodeHTMLEntities(postAtIndex.content));
}
if (description.length > 255) {

@ -2,7 +2,6 @@
var async = require('async');
var _ = require('lodash');
var S = require('string');
var winston = require('winston');
var validator = require('validator');
@ -660,7 +659,7 @@ Flags.notify = function (flagObj, uid, callback) {
return callback(err);
}
var title = S(results.title).decodeHTMLEntities().s;
var title = utils.decodeHTMLEntities(results.title);
var titleEscaped = title.replace(/%/g, '&#37;').replace(/,/g, '&#44;');
notifications.create({

@ -2,7 +2,6 @@
var async = require('async');
var S = require('string');
var validator = require('validator');
var db = require('./database');
@ -215,7 +214,7 @@ Messaging.getTeaser = function (uid, roomId, callback) {
return callback();
}
if (teaser.content) {
teaser.content = S(teaser.content).stripTags().decodeHTMLEntities().s;
teaser.content = utils.stripHTMLTags(utils.decodeHTMLEntities(teaser.content));
teaser.content = validator.escape(String(teaser.content));
}

@ -1,7 +1,6 @@
'use strict';
var async = require('async');
var S = require('string');
var db = require('../database');
var user = require('../user');
@ -73,7 +72,7 @@ module.exports = function (Messaging) {
return next(err);
}
message.content = result;
message.cleanedContent = S(result).stripTags().decodeHTMLEntities().s;
message.cleanedContent = utils.stripHTMLTags(utils.decodeHTMLEntities(result));
next(null, message);
});
}, next);

@ -72,7 +72,6 @@ JS.scripts = {
'public/src/modules/alerts.js',
'public/src/modules/taskbar.js',
'public/src/modules/helpers.js',
'public/src/modules/string.js',
'public/src/modules/flags.js',
'public/src/modules/storage.js',
],

@ -4,7 +4,6 @@ var async = require('async');
var winston = require('winston');
var cron = require('cron').CronJob;
var nconf = require('nconf');
var S = require('string');
var _ = require('lodash');
var db = require('./database');
@ -56,7 +55,7 @@ Notifications.getMultiple = function (nids, callback) {
notification.datetimeISO = utils.toISOString(notification.datetime);
if (notification.bodyLong) {
notification.bodyLong = S(notification.bodyLong).escapeHTML().s;
notification.bodyLong = utils.escapeHTML(notification.bodyLong);
}
notification.user = usersData[index];
@ -470,7 +469,7 @@ Notifications.merge = function (notifications, callback) {
});
var numUsers = usernames.length;
var title = S(notifications[modifyIndex].topicTitle || '').decodeHTMLEntities().s;
var title = utils.decodeHTMLEntities(notifications[modifyIndex].topicTitle || '');
var titleEscaped = title.replace(/%/g, '&#37;').replace(/,/g, '&#44;');
titleEscaped = titleEscaped ? (', ' + titleEscaped) : '';

@ -4,12 +4,12 @@ var async = require('async');
var nconf = require('nconf');
var url = require('url');
var winston = require('winston');
var S = require('string');
var meta = require('../meta');
var cache = require('./cache');
var plugins = require('../plugins');
var translator = require('../translator');
var utils = require('../utils');
module.exports = function (Posts) {
Posts.urlRegex = {
@ -82,7 +82,6 @@ module.exports = function (Posts) {
function sanitizeSignature(signature) {
signature = translator.escape(signature);
var string = S(signature);
var tagsToStrip = [];
if (parseInt(meta.config['signatures:disableLinks'], 10) === 1) {
@ -93,6 +92,6 @@ module.exports = function (Posts) {
tagsToStrip.push('img');
}
return tagsToStrip.length ? string.stripTags.apply(string, tagsToStrip).s : signature;
return utils.stripHTMLTags(signature, tagsToStrip);
}
};

@ -3,7 +3,6 @@
var async = require('async');
var validator = require('validator');
var S = require('string');
var _ = require('lodash');
var topics = require('../topics');
@ -144,8 +143,7 @@ module.exports = function (Posts) {
function stripTags(content) {
if (content) {
var s = S(content);
return s.stripTags.apply(s, utils.stripTags).s;
return utils.stripHTMLTags(content, utils.stripTags);
}
return content;
}

@ -2,7 +2,6 @@
var async = require('async');
var winston = require('winston');
var S = require('string');
var db = require('../database');
var websockets = require('./index');
@ -12,6 +11,7 @@ var topics = require('../topics');
var privileges = require('../privileges');
var notifications = require('../notifications');
var plugins = require('../plugins');
var utils = require('../utils');
var SocketHelpers = {};
@ -105,7 +105,7 @@ SocketHelpers.sendNotificationToPostOwner = function (pid, fromuid, command, not
}, next);
},
function (results, next) {
var title = S(results.topicTitle).decodeHTMLEntities().s;
var title = utils.decodeHTMLEntities(results.topicTitle);
var titleEscaped = title.replace(/%/g, '&#37;').replace(/,/g, '&#44;');
notifications.create({
@ -151,7 +151,7 @@ SocketHelpers.sendNotificationToTopicOwner = function (tid, fromuid, command, no
return;
}
ownerUid = results.topicData.uid;
var title = S(results.topicData.title).decodeHTMLEntities().s;
var title = utils.decodeHTMLEntities(results.topicData.title);
var titleEscaped = title.replace(/%/g, '&#37;').replace(/,/g, '&#44;');
notifications.create({

@ -3,12 +3,12 @@
var async = require('async');
var validator = require('validator');
var _ = require('lodash');
var S = require('string');
var posts = require('../../posts');
var groups = require('../../groups');
var events = require('../../events');
var meta = require('../../meta');
var utils = require('../../utils');
var websockets = require('../index');
module.exports = function (SocketPosts) {
@ -20,7 +20,7 @@ module.exports = function (SocketPosts) {
}
// Trim and remove HTML (latter for composers that send in HTML, like redactor)
var contentLen = S(data.content).stripTags().s.trim().length;
var contentLen = utils.stripHTMLTags(data.content).trim().length;
if (data.title && data.title.length < parseInt(meta.config.minimumTitleLength, 10)) {
return callback(new Error('[[error:title-too-short, ' + meta.config.minimumTitleLength + ']]'));

@ -4,7 +4,7 @@
var async = require('async');
var _ = require('lodash');
var validator = require('validator');
var S = require('string');
var db = require('../database');
var utils = require('../utils');
var plugins = require('../plugins');
@ -343,7 +343,7 @@ module.exports = function (Topics) {
function check(item, min, max, minError, maxError, callback) {
// Trim and remove HTML (latter for composers that send in HTML, like redactor)
if (typeof item === 'string') {
item = S(item).stripTags().s.trim();
item = utils.stripHTMLTags(item).trim();
}
if (item === null || item === undefined || item.length < parseInt(min, 10)) {

@ -2,7 +2,6 @@
'use strict';
var async = require('async');
var S = require('string');
var winston = require('winston');
var db = require('../database');
@ -13,6 +12,7 @@ var privileges = require('../privileges');
var meta = require('../meta');
var emailer = require('../emailer');
var plugins = require('../plugins');
var utils = require('../utils');
module.exports = function (Topics) {
Topics.toggleFollow = function (tid, uid, callback) {
@ -214,7 +214,7 @@ module.exports = function (Topics) {
title = postData.topic.title;
if (title) {
title = S(title).decodeHTMLEntities().s;
title = utils.decodeHTMLEntities(title);
titleEscaped = title.replace(/%/g, '&#37;').replace(/,/g, '&#44;');
}

@ -3,7 +3,6 @@
var async = require('async');
var _ = require('lodash');
var S = require('string');
var winston = require('winston');
var meta = require('../meta');
@ -91,8 +90,7 @@ module.exports = function (Topics) {
if (tidToPost[topic.tid]) {
tidToPost[topic.tid].index = meta.config.teaserPost === 'first' ? 1 : counts[index];
if (tidToPost[topic.tid].content) {
var s = S(tidToPost[topic.tid].content);
tidToPost[topic.tid].content = s.stripTags.apply(s, utils.stripTags).s;
tidToPost[topic.tid].content = utils.stripHTMLTags(tidToPost[topic.tid].content, utils.stripTags);
}
}
return tidToPost[topic.tid];

@ -3,12 +3,12 @@
var async = require('async');
var winston = require('winston');
var S = require('string');
var db = require('../database');
var meta = require('../meta');
var notifications = require('../notifications');
var privileges = require('../privileges');
var utils = require('../utils');
var UserNotifications = module.exports;
@ -281,7 +281,7 @@ UserNotifications.sendTopicNotificationToFollowers = function (uid, topicData, p
var title = topicData.title;
if (title) {
title = S(title).decodeHTMLEntities().s;
title = utils.decodeHTMLEntities(title);
}
notifications.create({

@ -2,7 +2,6 @@
'use strict';
var async = require('async');
var S = require('string');
var utils = require('../utils');
var meta = require('../meta');
@ -61,7 +60,7 @@ module.exports = function (User) {
} else if (field === 'fullname') {
return updateFullname(updateUid, data.fullname, next);
} else if (field === 'signature') {
data[field] = S(data[field]).stripTags().s;
data[field] = utils.stripHTMLTags(data[field]);
}
User.setUserField(updateUid, field, data[field], next);

@ -1,6 +1,5 @@
'use strict';
var string = require('string');
var path = require('path');
var fs = require('fs');
var assert = require('assert');

@ -16,6 +16,28 @@ describe('Utility Methods', function () {
var $ = global.$;
global.window = window;
// https://github.com/jprichardson/string.js/blob/master/test/string.test.js
it('should decode HTML entities', function (done) {
assert.strictEqual(
utils.decodeHTMLEntities('Ken Thompson &amp; Dennis Ritchie'),
'Ken Thompson & Dennis Ritchie'
);
assert.strictEqual(
utils.decodeHTMLEntities('3 &lt; 4'),
'3 < 4'
);
assert.strictEqual(
utils.decodeHTMLEntities('http:&#47;&#47;'),
'http://'
);
done();
});
it('should strip HTML tags', function (done) {
assert.strictEqual(utils.stripHTMLTags('<p>just <b>some</b> text</p>'), 'just some text');
assert.strictEqual(utils.stripHTMLTags('<p>just <b>some</b> text</p>', ['p']), 'just <b>some</b> text');
done();
});
it('should preserve case if requested', function (done) {
var slug = utils.slugify('UPPER CASE', true);
assert.equal(slug, 'UPPER-CASE');

Loading…
Cancel
Save