chore(deps): upgrade dependencies, remove some unnecessary ones
This commit upgrades dependencies that are more or less trivial to update, e.g. because they didn't have major version bumps or simply didn't break anything. There are some dependencies which have not been upgraded since this would have required larger refactorings. This includes especially the markdown-it ecosystem and the webpack ecosystem. The largest refactorings in this commit come from the bump of socket.io v2 to v4 which changed the handling of the connected socket list for instance. This commit further removes some outdated and/or unnecessary dependencies. This includes the String.js library which is unmaintained for 9 years and has some CVEs. We mainly used this library for their escapeHTML and unescapeHTML methods. This can be done using native DOM APIs nowadays, which is also considered more safe since it is the same logic that the browser itself uses. Since we target Node 18 and above, we can also rely on the built-in fetch function instead of the node-fetch package. The current version of Chance.js includes a method for generating a random color now too, so we don't need the package randomcolor anymore. Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
committed by
Philip Molares
parent
637c451486
commit
9a45d1e2a9
20
app.js
20
app.js
@@ -12,6 +12,7 @@ const session = require('express-session')
|
|||||||
const SequelizeStore = require('connect-session-sequelize')(session.Store)
|
const SequelizeStore = require('connect-session-sequelize')(session.Store)
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const { Server } = require('socket.io')
|
||||||
|
|
||||||
const morgan = require('morgan')
|
const morgan = require('morgan')
|
||||||
const passportSocketIo = require('passport.socketio')
|
const passportSocketIo = require('passport.socketio')
|
||||||
@@ -81,7 +82,16 @@ if (config.enableStatsApi) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// socket io
|
// socket io
|
||||||
const io = require('socket.io')(server, { cookie: false })
|
const io = new Server(server, {
|
||||||
|
pingInterval: config.heartbeatInterval,
|
||||||
|
pingTimeout: config.heartbeatTimeout,
|
||||||
|
cookie: false,
|
||||||
|
cors: {
|
||||||
|
origin: config.serverURL,
|
||||||
|
methods: ['GET', 'POST'],
|
||||||
|
credentials: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// others
|
// others
|
||||||
const realtime = require('./lib/realtime.js')
|
const realtime = require('./lib/realtime.js')
|
||||||
@@ -272,9 +282,6 @@ io.use(passportSocketIo.authorize({
|
|||||||
success: realtime.onAuthorizeSuccess,
|
success: realtime.onAuthorizeSuccess,
|
||||||
fail: realtime.onAuthorizeFail
|
fail: realtime.onAuthorizeFail
|
||||||
}))
|
}))
|
||||||
// socket.io heartbeat
|
|
||||||
io.set('heartbeat interval', config.heartbeatInterval)
|
|
||||||
io.set('heartbeat timeout', config.heartbeatTimeout)
|
|
||||||
// socket.io connection
|
// socket.io connection
|
||||||
io.sockets.on('connection', realtime.connection)
|
io.sockets.on('connection', realtime.connection)
|
||||||
|
|
||||||
@@ -349,8 +356,9 @@ function handleTermSignals () {
|
|||||||
alreadyHandlingTermSignals = true
|
alreadyHandlingTermSignals = true
|
||||||
realtime.maintenance = true
|
realtime.maintenance = true
|
||||||
// disconnect all socket.io clients
|
// disconnect all socket.io clients
|
||||||
Object.keys(io.sockets.sockets).forEach(function (key) {
|
io.sockets.sockets.keys().forEach(function (key) {
|
||||||
const socket = io.sockets.sockets[key]
|
const socket = io.sockets.sockets.get(key)
|
||||||
|
if (!socket) return
|
||||||
// notify client server going into maintenance status
|
// notify client server going into maintenance status
|
||||||
socket.emit('maintenance')
|
socket.emit('maintenance')
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
// external modules
|
// external modules
|
||||||
const crypto = require('crypto')
|
const crypto = require('crypto')
|
||||||
const randomcolor = require('randomcolor')
|
const Chance = require('chance')
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
|
|
||||||
// core
|
// core
|
||||||
exports.generateAvatar = function (name) {
|
exports.generateAvatar = function (name) {
|
||||||
const color = randomcolor({
|
// use darker colors for better contrast
|
||||||
seed: name,
|
const color = new Chance(name).color({
|
||||||
luminosity: 'dark'
|
max_red: 150,
|
||||||
|
max_green: 150,
|
||||||
|
max_blue: 150
|
||||||
})
|
})
|
||||||
const letter = name.substring(0, 1).toUpperCase()
|
const letter = name.substring(0, 1).toUpperCase()
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const async = require('async')
|
|||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
const DiffMatchPatch = require('diff-match-patch')
|
const DiffMatchPatch = require('diff-match-patch')
|
||||||
const dmp = new DiffMatchPatch()
|
const dmp = new DiffMatchPatch()
|
||||||
const S = require('string')
|
|
||||||
|
|
||||||
// core
|
// core
|
||||||
const config = require('../config')
|
const config = require('../config')
|
||||||
@@ -348,7 +347,9 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
title = meta.title
|
title = meta.title
|
||||||
} else {
|
} else {
|
||||||
const h1s = $('h1')
|
const h1s = $('h1')
|
||||||
if (h1s.length > 0 && h1s.first().text().split('\n').length === 1) { title = S(h1s.first().text()).stripTags().s }
|
if (h1s.length > 0 && h1s.first().text().split('\n').length === 1) {
|
||||||
|
title = h1s.first().text().trim()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!title) title = 'Untitled'
|
if (!title) title = 'Untitled'
|
||||||
return title
|
return title
|
||||||
@@ -378,7 +379,7 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
if (/^tags/gmi.test($(value).text())) {
|
if (/^tags/gmi.test($(value).text())) {
|
||||||
const codes = $(value).find('code')
|
const codes = $(value).find('code')
|
||||||
for (let i = 0; i < codes.length; i++) {
|
for (let i = 0; i < codes.length; i++) {
|
||||||
const text = S($(codes[i]).text().trim()).stripTags().s
|
const text = $(codes[i]).text().trim()
|
||||||
if (text) rawtags.push(text)
|
if (text) rawtags.push(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
const cookie = require('cookie')
|
const cookie = require('cookie')
|
||||||
const cookieParser = require('cookie-parser')
|
const cookieParser = require('cookie-parser')
|
||||||
const async = require('async')
|
const async = require('async')
|
||||||
const randomcolor = require('randomcolor')
|
|
||||||
const Chance = require('chance')
|
const Chance = require('chance')
|
||||||
const chance = new Chance()
|
const chance = new Chance()
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
@@ -178,9 +177,9 @@ function finishUpdateNote (note, _note, callback) {
|
|||||||
// clean when user not in any rooms or user not in connected list
|
// clean when user not in any rooms or user not in connected list
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
async.each(Object.keys(users), function (key, callback) {
|
async.each(Object.keys(users), function (key, callback) {
|
||||||
let socket = realtime.io.sockets.connected[key]
|
let socket = realtime.io.sockets.sockets.get(key)
|
||||||
if ((!socket && users[key]) ||
|
if ((!socket && users[key]) ||
|
||||||
(socket && (!socket.rooms || socket.rooms.length <= 0))) {
|
(socket && (!socket.rooms || socket.rooms.size <= 0))) {
|
||||||
logger.debug(`cleaner found redundant user: ${key}`)
|
logger.debug(`cleaner found redundant user: ${key}`)
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
socket = {
|
socket = {
|
||||||
@@ -711,7 +710,7 @@ function connection (socket) {
|
|||||||
|
|
||||||
// initialize user data
|
// initialize user data
|
||||||
// random color
|
// random color
|
||||||
let color = randomcolor()
|
let color = chance.color()
|
||||||
// make sure color not duplicated or reach max random count
|
// make sure color not duplicated or reach max random count
|
||||||
if (notes[noteId]) {
|
if (notes[noteId]) {
|
||||||
let randomcount = 0
|
let randomcount = 0
|
||||||
@@ -724,7 +723,7 @@ function connection (socket) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (found) {
|
if (found) {
|
||||||
color = randomcolor()
|
color = chance.color()
|
||||||
randomcount++
|
randomcount++
|
||||||
}
|
}
|
||||||
} while (found && randomcount < maxrandomcount)
|
} while (found && randomcount < maxrandomcount)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
// external modules
|
// external modules
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const fetch = require('node-fetch')
|
|
||||||
// core
|
// core
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
const config = require('../../config')
|
const config = require('../../config')
|
||||||
const logger = require('../../logger')
|
const logger = require('../../logger')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const fetch = require('node-fetch')
|
|
||||||
|
|
||||||
exports.uploadImage = function (imagePath, callback) {
|
exports.uploadImage = function (imagePath, callback) {
|
||||||
if (!callback || typeof callback !== 'function') {
|
if (!callback || typeof callback !== 'function') {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const { rateLimit } = require('express-rate-limit')
|
const { rateLimit, ipKeyGenerator } = require('express-rate-limit')
|
||||||
const errors = require('../../errors')
|
const errors = require('../../errors')
|
||||||
const config = require('../../config')
|
const config = require('../../config')
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ const determineKey = (req) => {
|
|||||||
if (req.user) {
|
if (req.user) {
|
||||||
return req.user.id
|
return req.user.id
|
||||||
}
|
}
|
||||||
return req.header('cf-connecting-ip') || req.ip
|
return ipKeyGenerator(req.header('cf-connecting-ip') || req.ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
// limits requests to user endpoints (login, signup) to 10 requests per 5 minutes
|
// limits requests to user endpoints (login, signup) to 10 requests per 5 minutes
|
||||||
|
|||||||
72
package.json
72
package.json
@@ -18,40 +18,40 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hedgedoc/meta-marked": "14.1.0",
|
"@hedgedoc/meta-marked": "14.1.0",
|
||||||
"@node-saml/passport-saml": "5.0.1",
|
"@node-saml/passport-saml": "5.1.0",
|
||||||
"@passport-next/passport-openid": "1.0.0",
|
"@passport-next/passport-openid": "1.0.0",
|
||||||
"Idle.Js": "git+https://github.com/shawnmclean/Idle.js#commit=2b57cc6e49d177b7ddce0cca00ef5cbe07453541",
|
"Idle.Js": "git+https://github.com/shawnmclean/Idle.js#commit=2b57cc6e49d177b7ddce0cca00ef5cbe07453541",
|
||||||
"archiver": "6.0.2",
|
"archiver": "7.0.1",
|
||||||
"async": "3.2.6",
|
"async": "3.2.6",
|
||||||
"aws-sdk": "2.1692.0",
|
"aws-sdk": "2.1692.0",
|
||||||
"azure-storage": "2.10.7",
|
"azure-storage": "2.10.7",
|
||||||
"base64url": "3.0.1",
|
"base64url": "3.0.1",
|
||||||
"body-parser": "2.2.0",
|
"body-parser": "2.2.0",
|
||||||
"chance": "1.1.12",
|
"chance": "1.1.13",
|
||||||
"cheerio": "0.22.0",
|
"cheerio": "1.1.2",
|
||||||
"clean-webpack-plugin": "4.0.0",
|
"clean-webpack-plugin": "4.0.0",
|
||||||
"compression": "1.8.0",
|
"compression": "1.8.1",
|
||||||
"connect-flash": "0.1.1",
|
"connect-flash": "0.1.1",
|
||||||
"connect-session-sequelize": "7.1.7",
|
"connect-session-sequelize": "8.0.2",
|
||||||
"cookie": "1.0.2",
|
"cookie": "1.0.2",
|
||||||
"cookie-parser": "1.4.7",
|
"cookie-parser": "1.4.7",
|
||||||
"deep-freeze": "0.0.1",
|
"deep-freeze": "0.0.1",
|
||||||
"diff-match-patch": "git+https://github.com/hackmdio/diff-match-patch.git#commit=59a9395ad9fe143e601e7ae5765ed943bdd2b11e",
|
"diff-match-patch": "git+https://github.com/hackmdio/diff-match-patch.git#commit=59a9395ad9fe143e601e7ae5765ed943bdd2b11e",
|
||||||
"ejs": "3.1.10",
|
"ejs": "3.1.10",
|
||||||
"express": "4.21.2",
|
"express": "4.21.2",
|
||||||
"express-rate-limit": "7.5.0",
|
"express-rate-limit": "8.2.1",
|
||||||
"express-session": "1.18.1",
|
"express-session": "1.18.2",
|
||||||
"file-type": "20.4.1",
|
"file-type": "21.1.1",
|
||||||
"formidable": "2.1.3",
|
"formidable": "3.5.4",
|
||||||
"graceful-fs": "4.2.11",
|
"graceful-fs": "4.2.11",
|
||||||
"helmet": "8.1.0",
|
"helmet": "8.1.0",
|
||||||
"i18n": "0.15.1",
|
"i18n": "0.15.3",
|
||||||
"is-svg": "4.4.0",
|
"is-svg": "6.1.0",
|
||||||
"jsdom-nogyp": "0.8.3",
|
"jsdom-nogyp": "0.8.3",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"lutim": "1.0.3",
|
"lutim": "1.0.3",
|
||||||
"lz-string": "git+https://github.com/hackmdio/lz-string.git#commit=6edfccb79cd8c210f03fd3bf18e41ca144fbeefb",
|
"lz-string": "git+https://github.com/hackmdio/lz-string.git#commit=6edfccb79cd8c210f03fd3bf18e41ca144fbeefb",
|
||||||
"mariadb": "3.4.1",
|
"mariadb": "3.4.5",
|
||||||
"markdown-it": "13.0.2",
|
"markdown-it": "13.0.2",
|
||||||
"markdown-it-abbr": "1.0.4",
|
"markdown-it-abbr": "1.0.4",
|
||||||
"markdown-it-container": "3.0.0",
|
"markdown-it-container": "3.0.0",
|
||||||
@@ -68,12 +68,11 @@
|
|||||||
"mattermost": "3.4.0",
|
"mattermost": "3.4.0",
|
||||||
"method-override": "3.0.0",
|
"method-override": "3.0.0",
|
||||||
"minimist": "1.2.8",
|
"minimist": "1.2.8",
|
||||||
"minio": "7.1.3",
|
"minio": "8.0.6",
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
"morgan": "1.10.0",
|
"morgan": "1.10.0",
|
||||||
"mysql2": "3.14.0",
|
"mysql2": "3.15.3",
|
||||||
"nanoid": "3.3.11",
|
"nanoid": "5.1.6",
|
||||||
"node-fetch": "2.7.0",
|
|
||||||
"passport": "patch:passport@npm%3A0.7.0#~/.yarn/patches/passport-npm-0.7.0-df02531736.patch",
|
"passport": "patch:passport@npm%3A0.7.0#~/.yarn/patches/passport-npm-0.7.0-df02531736.patch",
|
||||||
"passport-dropbox-oauth2": "1.1.0",
|
"passport-dropbox-oauth2": "1.1.0",
|
||||||
"passport-facebook": "3.0.0",
|
"passport-facebook": "3.0.0",
|
||||||
@@ -86,25 +85,23 @@
|
|||||||
"passport-twitter": "1.0.4",
|
"passport-twitter": "1.0.4",
|
||||||
"passport.socketio": "3.7.0",
|
"passport.socketio": "3.7.0",
|
||||||
"pdfobject": "2.3.1",
|
"pdfobject": "2.3.1",
|
||||||
"pg": "8.14.1",
|
"pg": "8.16.3",
|
||||||
"pg-hstore": "2.3.4",
|
"pg-hstore": "2.3.4",
|
||||||
"prom-client": "15.1.3",
|
"prom-client": "15.1.3",
|
||||||
"prometheus-api-metrics": "4.0.0",
|
"prometheus-api-metrics": "4.0.0",
|
||||||
"randomcolor": "0.6.2",
|
|
||||||
"readline-sync": "1.4.10",
|
"readline-sync": "1.4.10",
|
||||||
"rimraf": "5.0.10",
|
"rimraf": "6.1.2",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"scrypt-kdf": "2.0.1",
|
"scrypt-kdf": "3.0.0",
|
||||||
"sequelize": "5.22.5",
|
"sequelize": "5.22.5",
|
||||||
"socket.io": "2.5.1",
|
"socket.io": "4.8.1",
|
||||||
"sqlite3": "5.1.7",
|
"sqlite3": "5.1.7",
|
||||||
"store": "2.0.12",
|
"store": "2.0.12",
|
||||||
"string": "3.3.3",
|
|
||||||
"toobusy-js": "0.5.1",
|
"toobusy-js": "0.5.1",
|
||||||
"umzug": "2.3.0",
|
"umzug": "2.3.0",
|
||||||
"uuid": "11.1.0",
|
"uuid": "13.0.0",
|
||||||
"validator": "13.15.0",
|
"validator": "13.15.23",
|
||||||
"winston": "3.17.0",
|
"winston": "3.18.3",
|
||||||
"xss": "1.0.15"
|
"xss": "1.0.15"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -138,9 +135,9 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "3.3.1",
|
"@eslint/eslintrc": "3.3.1",
|
||||||
"@eslint/js": "9.24.0",
|
"@eslint/js": "9.39.1",
|
||||||
"@hedgedoc/codemirror-5": "5.65.12",
|
"@hedgedoc/codemirror-5": "5.65.12",
|
||||||
"abcjs": "6.4.4",
|
"abcjs": "6.5.2",
|
||||||
"babel-cli": "6.26.0",
|
"babel-cli": "6.26.0",
|
||||||
"babel-core": "6.26.3",
|
"babel-core": "6.26.3",
|
||||||
"babel-loader": "7.1.5",
|
"babel-loader": "7.1.5",
|
||||||
@@ -153,12 +150,11 @@
|
|||||||
"copy-webpack-plugin": "6.4.1",
|
"copy-webpack-plugin": "6.4.1",
|
||||||
"css-loader": "5.2.7",
|
"css-loader": "5.2.7",
|
||||||
"emojify.js": "1.1.0",
|
"emojify.js": "1.1.0",
|
||||||
"esbuild-loader": "4.3.0",
|
"esbuild-loader": "4.4.0",
|
||||||
"escape-html": "1.0.3",
|
"eslint": "9.39.1",
|
||||||
"eslint": "9.24.0",
|
|
||||||
"eslint-config-standard": "17.1.0",
|
"eslint-config-standard": "17.1.0",
|
||||||
"eslint-plugin-import": "2.31.0",
|
"eslint-plugin-import": "2.32.0",
|
||||||
"eslint-plugin-n": "17.17.0",
|
"eslint-plugin-n": "17.23.1",
|
||||||
"eslint-plugin-promise": "7.2.1",
|
"eslint-plugin-promise": "7.2.1",
|
||||||
"eslint-plugin-standard": "5.0.0",
|
"eslint-plugin-standard": "5.0.0",
|
||||||
"exports-loader": "1.1.1",
|
"exports-loader": "1.1.1",
|
||||||
@@ -167,7 +163,7 @@
|
|||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
"flowchart.js": "1.18.0",
|
"flowchart.js": "1.18.0",
|
||||||
"fork-awesome": "1.2.0",
|
"fork-awesome": "1.2.0",
|
||||||
"globals": "16.0.0",
|
"globals": "16.5.0",
|
||||||
"highlight.js": "10.7.3",
|
"highlight.js": "10.7.3",
|
||||||
"html-webpack-plugin": "4.5.2",
|
"html-webpack-plugin": "4.5.2",
|
||||||
"imports-loader": "1.2.0",
|
"imports-loader": "1.2.0",
|
||||||
@@ -180,13 +176,13 @@
|
|||||||
"js-yaml": "3.14.1",
|
"js-yaml": "3.14.1",
|
||||||
"jsonlint": "1.6.3",
|
"jsonlint": "1.6.3",
|
||||||
"keymaster": "1.6.2",
|
"keymaster": "1.6.2",
|
||||||
"less": "4.3.0",
|
"less": "4.4.2",
|
||||||
"less-loader": "7.3.0",
|
"less-loader": "7.3.0",
|
||||||
"list.js": "2.3.1",
|
"list.js": "2.3.1",
|
||||||
"mathjax": "2.7.9",
|
"mathjax": "2.7.9",
|
||||||
"mermaid": "9.1.7",
|
"mermaid": "9.1.7",
|
||||||
"mini-css-extract-plugin": "1.6.2",
|
"mini-css-extract-plugin": "1.6.2",
|
||||||
"mocha": "11.1.0",
|
"mocha": "11.7.5",
|
||||||
"mock-require": "3.0.3",
|
"mock-require": "3.0.3",
|
||||||
"optimize-css-assets-webpack-plugin": "6.0.1",
|
"optimize-css-assets-webpack-plugin": "6.0.1",
|
||||||
"prismjs": "1.30.0",
|
"prismjs": "1.30.0",
|
||||||
@@ -195,10 +191,10 @@
|
|||||||
"remark-preset-lint-markdown-style-guide": "5.1.3",
|
"remark-preset-lint-markdown-style-guide": "5.1.3",
|
||||||
"reveal.js": "3.9.2",
|
"reveal.js": "3.9.2",
|
||||||
"select2": "3.5.2-browserify",
|
"select2": "3.5.2-browserify",
|
||||||
"socket.io-client": "2.5.0",
|
"socket.io-client": "4.8.1",
|
||||||
"spin.js": "4.1.2",
|
"spin.js": "4.1.2",
|
||||||
"string-loader": "0.0.1",
|
"string-loader": "0.0.1",
|
||||||
"turndown": "7.2.0",
|
"turndown": "7.2.2",
|
||||||
"url-loader": "4.1.1",
|
"url-loader": "4.1.1",
|
||||||
"velocity-animate": "1.5.2",
|
"velocity-animate": "1.5.2",
|
||||||
"visibilityjs": "2.0.2",
|
"visibilityjs": "2.0.2",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
|
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
import List from 'list.js'
|
import List from 'list.js'
|
||||||
import S from 'string'
|
import { unescapeHtml } from './utils'
|
||||||
|
|
||||||
require('./locale')
|
require('./locale')
|
||||||
|
|
||||||
@@ -398,7 +398,7 @@ function buildTagsFilter (tags) {
|
|||||||
for (let i = 0; i < tags.length; i++) {
|
for (let i = 0; i < tags.length; i++) {
|
||||||
tags[i] = {
|
tags[i] = {
|
||||||
id: i,
|
id: i,
|
||||||
text: S(tags[i]).unescapeHTML().s
|
text: unescapeHtml(tags[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filtertags = tags
|
filtertags = tags
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
import Prism from 'prismjs'
|
import Prism from 'prismjs'
|
||||||
import PDFObject from 'pdfobject'
|
import PDFObject from 'pdfobject'
|
||||||
import S from 'string'
|
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
import escapeHTML from 'escape-html'
|
import filterXSS from 'xss'
|
||||||
|
|
||||||
import getUIElements from './lib/editor/ui-elements'
|
import getUIElements from './lib/editor/ui-elements'
|
||||||
|
import { escapeHtml, unescapeHtml } from './utils'
|
||||||
|
|
||||||
import markdownit from 'markdown-it'
|
import markdownit from 'markdown-it'
|
||||||
import markdownitContainer from 'markdown-it-container'
|
import markdownitContainer from 'markdown-it-container'
|
||||||
@@ -166,7 +166,11 @@ export function renderTags (view) {
|
|||||||
|
|
||||||
function slugifyWithUTF8 (text) {
|
function slugifyWithUTF8 (text) {
|
||||||
// remove HTML tags and trim spaces
|
// remove HTML tags and trim spaces
|
||||||
let newText = S(text).trim().stripTags().s
|
let newText = filterXSS(text.trim(), {
|
||||||
|
whiteList: {},
|
||||||
|
stripIgnoreTag: true,
|
||||||
|
stripIgnoreTagBody: ['script', 'style']
|
||||||
|
})
|
||||||
// replace space between words with dashes
|
// replace space between words with dashes
|
||||||
newText = newText.replace(/\s+/g, '-')
|
newText = newText.replace(/\s+/g, '-')
|
||||||
// slugify string to make it valid as an attribute
|
// slugify string to make it valid as an attribute
|
||||||
@@ -318,7 +322,7 @@ export function finishView (view) {
|
|||||||
svg[0].setAttribute('preserveAspectRatio', 'xMidYMid meet')
|
svg[0].setAttribute('preserveAspectRatio', 'xMidYMid meet')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$value.unwrap()
|
$value.unwrap()
|
||||||
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(err)}</div>`)
|
$value.parent().append(`<div class="alert alert-warning">${escapeHtml(err)}</div>`)
|
||||||
console.warn(err)
|
console.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -343,7 +347,7 @@ export function finishView (view) {
|
|||||||
$value.children().unwrap().unwrap()
|
$value.children().unwrap().unwrap()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$value.unwrap()
|
$value.unwrap()
|
||||||
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(err)}</div>`)
|
$value.parent().append(`<div class="alert alert-warning">${escapeHtml(err)}</div>`)
|
||||||
console.warn(err)
|
console.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -365,7 +369,7 @@ export function finishView (view) {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$value.unwrap()
|
$value.unwrap()
|
||||||
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(err)}</div>`)
|
$value.parent().append(`<div class="alert alert-warning">${escapeHtml(err)}</div>`)
|
||||||
console.warn(err)
|
console.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -388,7 +392,7 @@ export function finishView (view) {
|
|||||||
errormessage = err.str
|
errormessage = err.str
|
||||||
}
|
}
|
||||||
$value.unwrap()
|
$value.unwrap()
|
||||||
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(errormessage)}</div>`)
|
$value.parent().append(`<div class="alert alert-warning">${escapeHtml(errormessage)}</div>`)
|
||||||
console.warn(errormessage)
|
console.warn(errormessage)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -411,7 +415,7 @@ export function finishView (view) {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$value.unwrap()
|
$value.unwrap()
|
||||||
$value.parent().append(`<div class="alert alert-warning">${escapeHTML(err)}</div>`)
|
$value.parent().append(`<div class="alert alert-warning">${escapeHtml(err)}</div>`)
|
||||||
console.warn(err)
|
console.warn(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -486,24 +490,24 @@ export function finishView (view) {
|
|||||||
value: code
|
value: code
|
||||||
}
|
}
|
||||||
} else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {
|
} else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {
|
||||||
code = S(code).unescapeHTML().s
|
code = unescapeHtml(code)
|
||||||
result = {
|
result = {
|
||||||
value: Prism.highlight(code, Prism.languages[reallang])
|
value: Prism.highlight(code, Prism.languages[reallang])
|
||||||
}
|
}
|
||||||
} else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {
|
} else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {
|
||||||
code = S(code).unescapeHTML().s
|
code = unescapeHtml(code)
|
||||||
result = {
|
result = {
|
||||||
value: Prism.highlight(code, Prism.languages.wiki)
|
value: Prism.highlight(code, Prism.languages.wiki)
|
||||||
}
|
}
|
||||||
} else if (reallang === 'cmake') {
|
} else if (reallang === 'cmake') {
|
||||||
code = S(code).unescapeHTML().s
|
code = unescapeHtml(code)
|
||||||
result = {
|
result = {
|
||||||
value: Prism.highlight(code, Prism.languages.makefile)
|
value: Prism.highlight(code, Prism.languages.makefile)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
require.ensure([], function (require) {
|
require.ensure([], function (require) {
|
||||||
const hljs = require('highlight.js')
|
const hljs = require('highlight.js')
|
||||||
code = S(code).unescapeHTML().s
|
code = unescapeHtml(code)
|
||||||
const languages = hljs.listLanguages()
|
const languages = hljs.listLanguages()
|
||||||
if (!languages.includes(reallang)) {
|
if (!languages.includes(reallang)) {
|
||||||
result = hljs.highlightAuto(code)
|
result = hljs.highlightAuto(code)
|
||||||
@@ -576,7 +580,7 @@ export function postProcess (code) {
|
|||||||
if (warning && warning.length > 0) {
|
if (warning && warning.length > 0) {
|
||||||
warning.text(md.metaError)
|
warning.text(md.metaError)
|
||||||
} else {
|
} else {
|
||||||
warning = $(`<div id="meta-error" class="alert alert-warning">${escapeHTML(md.metaError)}</div>`)
|
warning = $(`<div id="meta-error" class="alert alert-warning">${escapeHtml(md.metaError)}</div>`)
|
||||||
result.prepend(warning)
|
result.prepend(warning)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -963,7 +967,7 @@ export function scrollToHash () {
|
|||||||
|
|
||||||
function highlightRender (code, lang) {
|
function highlightRender (code, lang) {
|
||||||
if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }
|
if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }
|
||||||
code = S(code).escapeHTML().s
|
code = escapeHtml(code)
|
||||||
if (lang === 'sequence') {
|
if (lang === 'sequence') {
|
||||||
return `<div class="sequence-diagram raw">${code}</div>`
|
return `<div class="sequence-diagram raw">${code}</div>`
|
||||||
} else if (lang === 'flow') {
|
} else if (lang === 'flow') {
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
/* global serverurl, moment */
|
/* global serverurl, moment */
|
||||||
|
|
||||||
import store from 'store'
|
import store from 'store'
|
||||||
import S from 'string'
|
|
||||||
import LZString from 'lz-string'
|
import LZString from 'lz-string'
|
||||||
import url from 'wurl'
|
import url from 'wurl'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkNoteIdValid,
|
checkNoteIdValid,
|
||||||
encodeNoteId
|
encodeNoteId,
|
||||||
|
escapeHtml
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -275,8 +275,8 @@ function parseToHistory (list, notehistory, callback) {
|
|||||||
notehistory[i].fromNow = timestamp.fromNow()
|
notehistory[i].fromNow = timestamp.fromNow()
|
||||||
notehistory[i].time = timestamp.format('llll')
|
notehistory[i].time = timestamp.format('llll')
|
||||||
// prevent XSS
|
// prevent XSS
|
||||||
notehistory[i].text = S(notehistory[i].text).escapeHTML().s
|
notehistory[i].text = escapeHtml(notehistory[i].text)
|
||||||
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? S(notehistory[i].tags).escapeHTML().s.split(',') : []
|
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? escapeHtml(notehistory[i].tags).split(',') : []
|
||||||
// add to list
|
// add to list
|
||||||
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
|
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { ot } from '../vendor/ot/ot.min.js'
|
|||||||
import hex2rgb from '../vendor/ot/hex2rgb'
|
import hex2rgb from '../vendor/ot/hex2rgb'
|
||||||
|
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
import randomColor from 'randomcolor'
|
import chance from 'chance'
|
||||||
import store from 'store'
|
import store from 'store'
|
||||||
import url from 'wurl'
|
import url from 'wurl'
|
||||||
import { Spinner } from 'spin.js'
|
import { Spinner } from 'spin.js'
|
||||||
@@ -427,7 +427,7 @@ const supportExtraTags = [
|
|||||||
text: '[random color tag]',
|
text: '[random color tag]',
|
||||||
search: '[]',
|
search: '[]',
|
||||||
command: function () {
|
command: function () {
|
||||||
const color = randomColor()
|
const color = chance().color()
|
||||||
return '[color=' + color + ']'
|
return '[color=' + color + ']'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,3 +30,21 @@ export function decodeNoteId (encodedId) {
|
|||||||
idParts.push(id.substr(20, 12))
|
idParts.push(id.substr(20, 12))
|
||||||
return idParts.join('-')
|
return idParts.join('-')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use browser's DOM APIs for escaping and unescaping HTML
|
||||||
|
export function escapeHtml (unsafe) {
|
||||||
|
if (!unsafe) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const tempDiv = document.createElement('div')
|
||||||
|
tempDiv.appendChild(document.createTextNode(String(unsafe)))
|
||||||
|
return tempDiv.innerHTML
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unescapeHtml (escapedHtml) {
|
||||||
|
if (!escapedHtml) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const doc = new DOMParser().parseFromString(escapedHtml, 'text/html')
|
||||||
|
return doc.documentElement.textContent || ''
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user