mirror of https://github.com/status-im/codimd.git
Merge branch 'develop' into feature/support-vega-lite
# Conflicts: # package.json # public/views/slide.ejs
This commit is contained in:
commit
71ea581796
6
app.js
6
app.js
|
@ -28,8 +28,8 @@ var csp = require('./lib/csp')
|
||||||
function createHttpServer () {
|
function createHttpServer () {
|
||||||
if (config.useSSL) {
|
if (config.useSSL) {
|
||||||
const ca = (function () {
|
const ca = (function () {
|
||||||
let i, len, results
|
let i, len
|
||||||
results = []
|
const results = []
|
||||||
for (i = 0, len = config.sslCAPath.length; i < len; i++) {
|
for (i = 0, len = config.sslCAPath.length; i < len; i++) {
|
||||||
results.push(fs.readFileSync(config.sslCAPath[i], 'utf8'))
|
results.push(fs.readFileSync(config.sslCAPath[i], 'utf8'))
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ var server = createHttpServer()
|
||||||
|
|
||||||
// logger
|
// logger
|
||||||
app.use(morgan('combined', {
|
app.use(morgan('combined', {
|
||||||
'stream': logger.stream
|
stream: logger.stream
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// socket io
|
// socket io
|
||||||
|
|
|
@ -53,14 +53,14 @@ if (['debug', 'verbose', 'info', 'warn', 'error'].includes(config.loglevel)) {
|
||||||
|
|
||||||
// load LDAP CA
|
// load LDAP CA
|
||||||
if (config.ldap.tlsca) {
|
if (config.ldap.tlsca) {
|
||||||
let ca = config.ldap.tlsca.split(',')
|
const certificateAuthorities = config.ldap.tlsca.split(',')
|
||||||
let caContent = []
|
const caContent = []
|
||||||
for (let i of ca) {
|
for (const ca of certificateAuthorities) {
|
||||||
if (fs.existsSync(i)) {
|
if (fs.existsSync(ca)) {
|
||||||
caContent.push(fs.readFileSync(i, 'utf8'))
|
caContent.push(fs.readFileSync(ca, 'utf8'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let tlsOptions = {
|
const tlsOptions = {
|
||||||
ca: caContent
|
ca: caContent
|
||||||
}
|
}
|
||||||
config.ldap.tlsOptions = config.ldap.tlsOptions ? Object.assign(config.ldap.tlsOptions, tlsOptions) : tlsOptions
|
config.ldap.tlsOptions = config.ldap.tlsOptions ? Object.assign(config.ldap.tlsOptions, tlsOptions) : tlsOptions
|
||||||
|
@ -134,10 +134,10 @@ config.isGitlabSnippetsEnable = (!config.gitlab.scope || config.gitlab.scope ===
|
||||||
config.updateI18nFiles = (env === Environment.development)
|
config.updateI18nFiles = (env === Environment.development)
|
||||||
|
|
||||||
// merge legacy values
|
// merge legacy values
|
||||||
let keys = Object.keys(config)
|
const keys = Object.keys(config)
|
||||||
const uppercase = /[A-Z]/
|
const uppercase = /[A-Z]/
|
||||||
for (let i = keys.length; i--;) {
|
for (let i = keys.length; i--;) {
|
||||||
let lowercaseKey = keys[i].toLowerCase()
|
const lowercaseKey = keys[i].toLowerCase()
|
||||||
// if the config contains uppercase letters
|
// if the config contains uppercase letters
|
||||||
// and a lowercase version of this setting exists
|
// and a lowercase version of this setting exists
|
||||||
// and the config with uppercase is not set
|
// and the config with uppercase is not set
|
||||||
|
|
|
@ -9,14 +9,6 @@ var logger = require('./logger')
|
||||||
var response = require('./response')
|
var response = require('./response')
|
||||||
var models = require('./models')
|
var models = require('./models')
|
||||||
|
|
||||||
// public
|
|
||||||
var History = {
|
|
||||||
historyGet: historyGet,
|
|
||||||
historyPost: historyPost,
|
|
||||||
historyDelete: historyDelete,
|
|
||||||
updateHistory: updateHistory
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHistory (userid, callback) {
|
function getHistory (userid, callback) {
|
||||||
models.User.findOne({
|
models.User.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
@ -41,7 +33,7 @@ function getHistory (userid, callback) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let id = LZString.decompressFromBase64(history[i].id)
|
const id = LZString.decompressFromBase64(history[i].id)
|
||||||
if (id && models.Note.checkNoteIdValid(id)) {
|
if (id && models.Note.checkNoteIdValid(id)) {
|
||||||
history[i].id = models.Note.encodeNoteId(id)
|
history[i].id = models.Note.encodeNoteId(id)
|
||||||
}
|
}
|
||||||
|
@ -200,4 +192,8 @@ function historyDelete (req, res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = History
|
// public
|
||||||
|
exports.historyGet = historyGet
|
||||||
|
exports.historyPost = historyPost
|
||||||
|
exports.historyDelete = historyDelete
|
||||||
|
exports.updateHistory = updateHistory
|
||||||
|
|
|
@ -32,9 +32,9 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
|
||||||
}
|
}
|
||||||
name = encodeURIComponent(name)
|
name = encodeURIComponent(name)
|
||||||
|
|
||||||
let hash = crypto.createHash('md5')
|
const hash = crypto.createHash('md5')
|
||||||
hash.update(email.toLowerCase())
|
hash.update(email.toLowerCase())
|
||||||
let hexDigest = hash.digest('hex')
|
const hexDigest = hash.digest('hex')
|
||||||
|
|
||||||
if (email !== '' && config.allowGravatar) {
|
if (email !== '' && config.allowGravatar) {
|
||||||
photo = 'https://www.gravatar.com/avatar/' + hexDigest
|
photo = 'https://www.gravatar.com/avatar/' + hexDigest
|
||||||
|
|
|
@ -165,15 +165,15 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
}
|
}
|
||||||
Note.encodeNoteId = function (id) {
|
Note.encodeNoteId = function (id) {
|
||||||
// remove dashes in UUID and encode in url-safe base64
|
// remove dashes in UUID and encode in url-safe base64
|
||||||
let str = id.replace(/-/g, '')
|
const str = id.replace(/-/g, '')
|
||||||
let hexStr = Buffer.from(str, 'hex')
|
const hexStr = Buffer.from(str, 'hex')
|
||||||
return base64url.encode(hexStr)
|
return base64url.encode(hexStr)
|
||||||
}
|
}
|
||||||
Note.decodeNoteId = function (encodedId) {
|
Note.decodeNoteId = function (encodedId) {
|
||||||
// decode from url-safe base64
|
// decode from url-safe base64
|
||||||
let id = base64url.toBuffer(encodedId).toString('hex')
|
const id = base64url.toBuffer(encodedId).toString('hex')
|
||||||
// add dashes between the UUID string parts
|
// add dashes between the UUID string parts
|
||||||
let idParts = []
|
const idParts = []
|
||||||
idParts.push(id.substr(0, 8))
|
idParts.push(id.substr(0, 8))
|
||||||
idParts.push(id.substr(8, 4))
|
idParts.push(id.substr(8, 4))
|
||||||
idParts.push(id.substr(12, 4))
|
idParts.push(id.substr(12, 4))
|
||||||
|
@ -196,7 +196,7 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
}
|
}
|
||||||
}).then(function (note) {
|
}).then(function (note) {
|
||||||
if (note) {
|
if (note) {
|
||||||
let filePath = path.join(config.docsPath, noteId + '.md')
|
const filePath = path.join(config.docsPath, noteId + '.md')
|
||||||
if (Note.checkFileExist(filePath)) {
|
if (Note.checkFileExist(filePath)) {
|
||||||
// if doc in filesystem have newer modified time than last change time
|
// if doc in filesystem have newer modified time than last change time
|
||||||
// then will update the doc in db
|
// then will update the doc in db
|
||||||
|
@ -421,20 +421,20 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
if (ot.TextOperation.isRetain(op)) {
|
if (ot.TextOperation.isRetain(op)) {
|
||||||
index += op
|
index += op
|
||||||
} else if (ot.TextOperation.isInsert(op)) {
|
} else if (ot.TextOperation.isInsert(op)) {
|
||||||
let opStart = index
|
const opStart = index
|
||||||
let opEnd = index + op.length
|
const opEnd = index + op.length
|
||||||
var inserted = false
|
let inserted = false
|
||||||
// authorship format: [userId, startPos, endPos, createdAt, updatedAt]
|
// authorship format: [userId, startPos, endPos, createdAt, updatedAt]
|
||||||
if (authorships.length <= 0) authorships.push([userId, opStart, opEnd, timestamp, timestamp])
|
if (authorships.length <= 0) authorships.push([userId, opStart, opEnd, timestamp, timestamp])
|
||||||
else {
|
else {
|
||||||
for (let j = 0; j < authorships.length; j++) {
|
for (let j = 0; j < authorships.length; j++) {
|
||||||
let authorship = authorships[j]
|
const authorship = authorships[j]
|
||||||
if (!inserted) {
|
if (!inserted) {
|
||||||
let nextAuthorship = authorships[j + 1] || -1
|
const nextAuthorship = authorships[j + 1] || -1
|
||||||
if ((nextAuthorship !== -1 && nextAuthorship[1] >= opEnd) || j >= authorships.length - 1) {
|
if ((nextAuthorship !== -1 && nextAuthorship[1] >= opEnd) || j >= authorships.length - 1) {
|
||||||
if (authorship[1] < opStart && authorship[2] > opStart) {
|
if (authorship[1] < opStart && authorship[2] > opStart) {
|
||||||
// divide
|
// divide
|
||||||
let postLength = authorship[2] - opStart
|
const postLength = authorship[2] - opStart
|
||||||
authorship[2] = opStart
|
authorship[2] = opStart
|
||||||
authorship[4] = timestamp
|
authorship[4] = timestamp
|
||||||
authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp])
|
authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp])
|
||||||
|
@ -460,13 +460,13 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
}
|
}
|
||||||
index += op.length
|
index += op.length
|
||||||
} else if (ot.TextOperation.isDelete(op)) {
|
} else if (ot.TextOperation.isDelete(op)) {
|
||||||
let opStart = index
|
const opStart = index
|
||||||
let opEnd = index - op
|
const opEnd = index - op
|
||||||
if (operation.length === 1) {
|
if (operation.length === 1) {
|
||||||
authorships = []
|
authorships = []
|
||||||
} else if (authorships.length > 0) {
|
} else if (authorships.length > 0) {
|
||||||
for (let j = 0; j < authorships.length; j++) {
|
for (let j = 0; j < authorships.length; j++) {
|
||||||
let authorship = authorships[j]
|
const authorship = authorships[j]
|
||||||
if (authorship[1] >= opStart && authorship[1] <= opEnd && authorship[2] >= opStart && authorship[2] <= opEnd) {
|
if (authorship[1] >= opStart && authorship[1] <= opEnd && authorship[2] >= opStart && authorship[2] <= opEnd) {
|
||||||
authorships.splice(j, 1)
|
authorships.splice(j, 1)
|
||||||
j -= 1
|
j -= 1
|
||||||
|
@ -491,12 +491,12 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
}
|
}
|
||||||
// merge
|
// merge
|
||||||
for (let j = 0; j < authorships.length; j++) {
|
for (let j = 0; j < authorships.length; j++) {
|
||||||
let authorship = authorships[j]
|
const authorship = authorships[j]
|
||||||
for (let k = j + 1; k < authorships.length; k++) {
|
for (let k = j + 1; k < authorships.length; k++) {
|
||||||
let nextAuthorship = authorships[k]
|
const nextAuthorship = authorships[k]
|
||||||
if (nextAuthorship && authorship[0] === nextAuthorship[0] && authorship[2] === nextAuthorship[1]) {
|
if (nextAuthorship && authorship[0] === nextAuthorship[0] && authorship[2] === nextAuthorship[1]) {
|
||||||
let minTimestamp = Math.min(authorship[3], nextAuthorship[3])
|
const minTimestamp = Math.min(authorship[3], nextAuthorship[3])
|
||||||
let maxTimestamp = Math.max(authorship[3], nextAuthorship[3])
|
const maxTimestamp = Math.max(authorship[3], nextAuthorship[3])
|
||||||
authorships.splice(j, 1, [authorship[0], authorship[1], nextAuthorship[2], minTimestamp, maxTimestamp])
|
authorships.splice(j, 1, [authorship[0], authorship[1], nextAuthorship[2], minTimestamp, maxTimestamp])
|
||||||
authorships.splice(k, 1)
|
authorships.splice(k, 1)
|
||||||
j -= 1
|
j -= 1
|
||||||
|
@ -506,7 +506,7 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
}
|
}
|
||||||
// clear
|
// clear
|
||||||
for (let j = 0; j < authorships.length; j++) {
|
for (let j = 0; j < authorships.length; j++) {
|
||||||
let authorship = authorships[j]
|
const authorship = authorships[j]
|
||||||
if (!authorship[0]) {
|
if (!authorship[0]) {
|
||||||
authorships.splice(j, 1)
|
authorships.splice(j, 1)
|
||||||
j -= 1
|
j -= 1
|
||||||
|
@ -537,11 +537,11 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
var lengthBias = 0
|
var lengthBias = 0
|
||||||
for (let j = 0; j < patch.length; j++) {
|
for (let j = 0; j < patch.length; j++) {
|
||||||
var operation = []
|
var operation = []
|
||||||
let p = patch[j]
|
const p = patch[j]
|
||||||
var currIndex = p.start1
|
var currIndex = p.start1
|
||||||
var currLength = contentLength - bias
|
var currLength = contentLength - bias
|
||||||
for (let i = 0; i < p.diffs.length; i++) {
|
for (let i = 0; i < p.diffs.length; i++) {
|
||||||
let diff = p.diffs[i]
|
const diff = p.diffs[i]
|
||||||
switch (diff[0]) {
|
switch (diff[0]) {
|
||||||
case 0: // retain
|
case 0: // retain
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
|
|
|
@ -744,8 +744,8 @@ function queueForConnect (socket) {
|
||||||
})
|
})
|
||||||
return socket.disconnect(true)
|
return socket.disconnect(true)
|
||||||
}
|
}
|
||||||
let note = notes[noteId]
|
const note = notes[noteId]
|
||||||
let user = users[socket.id]
|
const user = users[socket.id]
|
||||||
// update user color to author color
|
// update user color to author color
|
||||||
if (note.authors[user.userid]) {
|
if (note.authors[user.userid]) {
|
||||||
user.color = users[socket.id].color = note.authors[user.userid].color
|
user.color = users[socket.id].color = note.authors[user.userid].color
|
||||||
|
@ -766,7 +766,7 @@ function queueForConnect (socket) {
|
||||||
socketClient.registerEventHandler()
|
socketClient.registerEventHandler()
|
||||||
|
|
||||||
if (config.debug) {
|
if (config.debug) {
|
||||||
let noteId = socket.noteId
|
const noteId = socket.noteId
|
||||||
logger.info('SERVER connected a client to [' + noteId + ']:')
|
logger.info('SERVER connected a client to [' + noteId + ']:')
|
||||||
logger.info(JSON.stringify(user))
|
logger.info(JSON.stringify(user))
|
||||||
// logger.info(notes);
|
// logger.info(notes);
|
||||||
|
|
131
lib/response.js
131
lib/response.js
|
@ -1,24 +1,40 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
// response
|
// response
|
||||||
// external modules
|
// external modules
|
||||||
var fs = require('fs')
|
const fs = require('fs')
|
||||||
var path = require('path')
|
const path = require('path')
|
||||||
var markdownpdf = require('markdown-pdf')
|
const markdownpdf = require('markdown-pdf')
|
||||||
var shortId = require('shortid')
|
const shortId = require('shortid')
|
||||||
var querystring = require('querystring')
|
const querystring = require('querystring')
|
||||||
var request = require('request')
|
const request = require('request')
|
||||||
var moment = require('moment')
|
const moment = require('moment')
|
||||||
|
|
||||||
// core
|
// core
|
||||||
var config = require('./config')
|
const config = require('./config')
|
||||||
var logger = require('./logger')
|
const logger = require('./logger')
|
||||||
var models = require('./models')
|
const models = require('./models')
|
||||||
var utils = require('./utils')
|
const utils = require('./utils')
|
||||||
var history = require('./history')
|
const history = require('./history')
|
||||||
|
|
||||||
// public
|
// public
|
||||||
var response = {
|
exports.errorForbidden = errorForbidden
|
||||||
errorForbidden: function (res) {
|
exports.errorNotFound = errorNotFound
|
||||||
|
exports.errorBadRequest = errorBadRequest
|
||||||
|
exports.errorTooLong = errorTooLong
|
||||||
|
exports.errorInternalError = errorInternalError
|
||||||
|
exports.errorServiceUnavailable = errorServiceUnavailable
|
||||||
|
exports.newNote = newNote
|
||||||
|
exports.showNote = showNote
|
||||||
|
exports.showPublishNote = showPublishNote
|
||||||
|
exports.showPublishSlide = showPublishSlide
|
||||||
|
exports.showIndex = showIndex
|
||||||
|
exports.noteActions = noteActions
|
||||||
|
exports.publishNoteActions = publishNoteActions
|
||||||
|
exports.publishSlideActions = publishSlideActions
|
||||||
|
exports.githubActions = githubActions
|
||||||
|
exports.gitlabActions = gitlabActions
|
||||||
|
|
||||||
|
function errorForbidden (res) {
|
||||||
const { req } = res
|
const { req } = res
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
responseError(res, '403', 'Forbidden', 'oh no.')
|
responseError(res, '403', 'Forbidden', 'oh no.')
|
||||||
|
@ -26,32 +42,21 @@ var response = {
|
||||||
req.flash('error', 'You are not allowed to access this page. Maybe try logging in?')
|
req.flash('error', 'You are not allowed to access this page. Maybe try logging in?')
|
||||||
res.redirect(config.serverURL + '/')
|
res.redirect(config.serverURL + '/')
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
errorNotFound: function (res) {
|
function errorNotFound (res) {
|
||||||
responseError(res, '404', 'Not Found', 'oops.')
|
responseError(res, '404', 'Not Found', 'oops.')
|
||||||
},
|
}
|
||||||
errorBadRequest: function (res) {
|
function errorBadRequest (res) {
|
||||||
responseError(res, '400', 'Bad Request', 'something not right.')
|
responseError(res, '400', 'Bad Request', 'something not right.')
|
||||||
},
|
}
|
||||||
errorTooLong: function (res) {
|
function errorTooLong (res) {
|
||||||
responseError(res, '413', 'Payload Too Large', 'Shorten your note!')
|
responseError(res, '413', 'Payload Too Large', 'Shorten your note!')
|
||||||
},
|
}
|
||||||
errorInternalError: function (res) {
|
function errorInternalError (res) {
|
||||||
responseError(res, '500', 'Internal Error', 'wtf.')
|
responseError(res, '500', 'Internal Error', 'wtf.')
|
||||||
},
|
}
|
||||||
errorServiceUnavailable: function (res) {
|
function errorServiceUnavailable (res) {
|
||||||
res.status(503).send("I'm busy right now, try again later.")
|
res.status(503).send("I'm busy right now, try again later.")
|
||||||
},
|
|
||||||
newNote: newNote,
|
|
||||||
showNote: showNote,
|
|
||||||
showPublishNote: showPublishNote,
|
|
||||||
showPublishSlide: showPublishSlide,
|
|
||||||
showIndex: showIndex,
|
|
||||||
noteActions: noteActions,
|
|
||||||
publishNoteActions: publishNoteActions,
|
|
||||||
publishSlideActions: publishSlideActions,
|
|
||||||
githubActions: githubActions,
|
|
||||||
gitlabActions: gitlabActions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function responseError (res, code, detail, msg) {
|
function responseError (res, code, detail, msg) {
|
||||||
|
@ -117,7 +122,7 @@ function newNote (req, res, next) {
|
||||||
var owner = null
|
var owner = null
|
||||||
var body = ''
|
var body = ''
|
||||||
if (req.body && req.body.length > config.documentMaxLength) {
|
if (req.body && req.body.length > config.documentMaxLength) {
|
||||||
return response.errorTooLong(res)
|
return errorTooLong(res)
|
||||||
} else if (req.body) {
|
} else if (req.body) {
|
||||||
body = req.body
|
body = req.body
|
||||||
}
|
}
|
||||||
|
@ -125,7 +130,7 @@ function newNote (req, res, next) {
|
||||||
if (req.isAuthenticated()) {
|
if (req.isAuthenticated()) {
|
||||||
owner = req.user.id
|
owner = req.user.id
|
||||||
} else if (!config.allowAnonymous) {
|
} else if (!config.allowAnonymous) {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
}
|
}
|
||||||
models.Note.create({
|
models.Note.create({
|
||||||
ownerId: owner,
|
ownerId: owner,
|
||||||
|
@ -139,7 +144,7 @@ function newNote (req, res, next) {
|
||||||
return res.redirect(config.serverURL + '/' + models.Note.encodeNoteId(note.id))
|
return res.redirect(config.serverURL + '/' + models.Note.encodeNoteId(note.id))
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +164,7 @@ function findNote (req, res, callback, include) {
|
||||||
models.Note.parseNoteId(id, function (err, _id) {
|
models.Note.parseNoteId(id, function (err, _id) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
}
|
}
|
||||||
models.Note.findOne({
|
models.Note.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
@ -172,17 +177,17 @@ function findNote (req, res, callback, include) {
|
||||||
req.alias = noteId
|
req.alias = noteId
|
||||||
return newNote(req, res)
|
return newNote(req, res)
|
||||||
} else {
|
} else {
|
||||||
return response.errorNotFound(res)
|
return errorNotFound(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!checkViewPermission(req, note)) {
|
if (!checkViewPermission(req, note)) {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
} else {
|
} else {
|
||||||
return callback(note)
|
return callback(note)
|
||||||
}
|
}
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -213,7 +218,7 @@ function showPublishNote (req, res, next) {
|
||||||
}
|
}
|
||||||
note.increment('viewcount').then(function (note) {
|
note.increment('viewcount').then(function (note) {
|
||||||
if (!note) {
|
if (!note) {
|
||||||
return response.errorNotFound(res)
|
return errorNotFound(res)
|
||||||
}
|
}
|
||||||
var body = note.content
|
var body = note.content
|
||||||
var extracted = models.Note.extractMeta(body)
|
var extracted = models.Note.extractMeta(body)
|
||||||
|
@ -242,7 +247,7 @@ function showPublishNote (req, res, next) {
|
||||||
return renderPublish(data, res)
|
return renderPublish(data, res)
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
})
|
})
|
||||||
}, include)
|
}, include)
|
||||||
}
|
}
|
||||||
|
@ -319,7 +324,7 @@ function actionPDF (req, res, note) {
|
||||||
markdownpdf().from.string(content).to(path, function () {
|
markdownpdf().from.string(content).to(path, function () {
|
||||||
if (!fs.existsSync(path)) {
|
if (!fs.existsSync(path)) {
|
||||||
logger.error('PDF seems to not be generated as expected. File doesn\'t exist: ' + path)
|
logger.error('PDF seems to not be generated as expected. File doesn\'t exist: ' + path)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
}
|
}
|
||||||
var stream = fs.createReadStream(path)
|
var stream = fs.createReadStream(path)
|
||||||
var filename = title
|
var filename = title
|
||||||
|
@ -354,10 +359,10 @@ function actionRevision (req, res, note) {
|
||||||
models.Revision.getPatchedNoteRevisionByTime(note, time, function (err, content) {
|
models.Revision.getPatchedNoteRevisionByTime(note, time, function (err, content) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
}
|
}
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return response.errorNotFound(res)
|
return errorNotFound(res)
|
||||||
}
|
}
|
||||||
res.set({
|
res.set({
|
||||||
'Access-Control-Allow-Origin': '*', // allow CORS as API
|
'Access-Control-Allow-Origin': '*', // allow CORS as API
|
||||||
|
@ -369,13 +374,13 @@ function actionRevision (req, res, note) {
|
||||||
res.send(content)
|
res.send(content)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return response.errorNotFound(res)
|
return errorNotFound(res)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
models.Revision.getNoteRevisions(note, function (err, data) {
|
models.Revision.getNoteRevisions(note, function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
}
|
}
|
||||||
var out = {
|
var out = {
|
||||||
revision: data
|
revision: data
|
||||||
|
@ -415,7 +420,7 @@ function noteActions (req, res, next) {
|
||||||
actionPDF(req, res, note)
|
actionPDF(req, res, note)
|
||||||
} else {
|
} else {
|
||||||
logger.error('PDF export failed: Disabled by config. Set "allowPDFExport: true" to enable. Check the documentation for details')
|
logger.error('PDF export failed: Disabled by config. Set "allowPDFExport: true" to enable. Check the documentation for details')
|
||||||
response.errorForbidden(res)
|
errorForbidden(res)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'gist':
|
case 'gist':
|
||||||
|
@ -480,7 +485,7 @@ function githubActionGist (req, res, note) {
|
||||||
var code = req.query.code
|
var code = req.query.code
|
||||||
var state = req.query.state
|
var state = req.query.state
|
||||||
if (!code || !state) {
|
if (!code || !state) {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
} else {
|
} else {
|
||||||
var data = {
|
var data = {
|
||||||
client_id: config.github.clientID,
|
client_id: config.github.clientID,
|
||||||
|
@ -501,17 +506,17 @@ function githubActionGist (req, res, note) {
|
||||||
var title = models.Note.decodeTitle(note.title)
|
var title = models.Note.decodeTitle(note.title)
|
||||||
var filename = title.replace('/', ' ') + '.md'
|
var filename = title.replace('/', ' ') + '.md'
|
||||||
var gist = {
|
var gist = {
|
||||||
'files': {}
|
files: {}
|
||||||
}
|
}
|
||||||
gist.files[filename] = {
|
gist.files[filename] = {
|
||||||
'content': content
|
content: content
|
||||||
}
|
}
|
||||||
var gistUrl = 'https://api.github.com/gists'
|
var gistUrl = 'https://api.github.com/gists'
|
||||||
request({
|
request({
|
||||||
url: gistUrl,
|
url: gistUrl,
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'CodiMD',
|
'User-Agent': 'CodiMD',
|
||||||
'Authorization': 'token ' + accessToken
|
Authorization: 'token ' + accessToken
|
||||||
},
|
},
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
json: gist
|
json: gist
|
||||||
|
@ -520,14 +525,14 @@ function githubActionGist (req, res, note) {
|
||||||
res.setHeader('referer', '')
|
res.setHeader('referer', '')
|
||||||
res.redirect(body.html_url)
|
res.redirect(body.html_url)
|
||||||
} else {
|
} else {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -555,7 +560,7 @@ function gitlabActionProjects (req, res, note) {
|
||||||
id: req.user.id
|
id: req.user.id
|
||||||
}
|
}
|
||||||
}).then(function (user) {
|
}).then(function (user) {
|
||||||
if (!user) { return response.errorNotFound(res) }
|
if (!user) { return errorNotFound(res) }
|
||||||
var ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
|
var ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
|
||||||
ret.accesstoken = user.accessToken
|
ret.accesstoken = user.accessToken
|
||||||
ret.profileid = user.profileid
|
ret.profileid = user.profileid
|
||||||
|
@ -572,10 +577,10 @@ function gitlabActionProjects (req, res, note) {
|
||||||
)
|
)
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
logger.error('gitlab action projects failed: ' + err)
|
logger.error('gitlab action projects failed: ' + err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return response.errorForbidden(res)
|
return errorForbidden(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,7 +598,7 @@ function showPublishSlide (req, res, next) {
|
||||||
if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) { return res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid)) }
|
if ((note.alias && shortid !== note.alias) || (!note.alias && shortid !== note.shortid)) { return res.redirect(config.serverURL + '/p/' + (note.alias || note.shortid)) }
|
||||||
note.increment('viewcount').then(function (note) {
|
note.increment('viewcount').then(function (note) {
|
||||||
if (!note) {
|
if (!note) {
|
||||||
return response.errorNotFound(res)
|
return errorNotFound(res)
|
||||||
}
|
}
|
||||||
var body = note.content
|
var body = note.content
|
||||||
var extracted = models.Note.extractMeta(body)
|
var extracted = models.Note.extractMeta(body)
|
||||||
|
@ -624,7 +629,7 @@ function showPublishSlide (req, res, next) {
|
||||||
return renderPublishSlide(data, res)
|
return renderPublishSlide(data, res)
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
logger.error(err)
|
logger.error(err)
|
||||||
return response.errorInternalError(res)
|
return errorInternalError(res)
|
||||||
})
|
})
|
||||||
}, include)
|
}, include)
|
||||||
}
|
}
|
||||||
|
@ -635,5 +640,3 @@ function renderPublishSlide (data, res) {
|
||||||
})
|
})
|
||||||
res.render('slide.ejs', data)
|
res.render('slide.ejs', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = response
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ exports.isSQLite = function isSQLite (sequelize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getImageMimeType = function getImageMimeType (imagePath) {
|
exports.getImageMimeType = function getImageMimeType (imagePath) {
|
||||||
var fileExtension = /[^.]+$/.exec(imagePath)
|
const fileExtension = /[^.]+$/.exec(imagePath)
|
||||||
|
|
||||||
switch (fileExtension[0]) {
|
switch (fileExtension[0]) {
|
||||||
case 'bmp':
|
case 'bmp':
|
||||||
|
|
|
@ -6,7 +6,7 @@ const DropboxStrategy = require('passport-dropbox-oauth2').Strategy
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let dropboxAuth = module.exports = Router()
|
const dropboxAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new DropboxStrategy({
|
passport.use(new DropboxStrategy({
|
||||||
apiVersion: '2',
|
apiVersion: '2',
|
||||||
|
|
|
@ -11,7 +11,7 @@ const { setReturnToFromReferer } = require('../utils')
|
||||||
const { urlencodedParser } = require('../../utils')
|
const { urlencodedParser } = require('../../utils')
|
||||||
const response = require('../../../response')
|
const response = require('../../../response')
|
||||||
|
|
||||||
let emailAuth = module.exports = Router()
|
const emailAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new LocalStrategy({
|
passport.use(new LocalStrategy({
|
||||||
usernameField: 'email'
|
usernameField: 'email'
|
||||||
|
|
|
@ -7,7 +7,7 @@ const FacebookStrategy = require('passport-facebook').Strategy
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let facebookAuth = module.exports = Router()
|
const facebookAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new FacebookStrategy({
|
passport.use(new FacebookStrategy({
|
||||||
clientID: config.facebook.clientID,
|
clientID: config.facebook.clientID,
|
||||||
|
|
|
@ -7,7 +7,7 @@ const config = require('../../../config')
|
||||||
const response = require('../../../response')
|
const response = require('../../../response')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let githubAuth = module.exports = Router()
|
const githubAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new GithubStrategy({
|
passport.use(new GithubStrategy({
|
||||||
clientID: config.github.clientID,
|
clientID: config.github.clientID,
|
||||||
|
|
|
@ -7,7 +7,7 @@ const config = require('../../../config')
|
||||||
const response = require('../../../response')
|
const response = require('../../../response')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let gitlabAuth = module.exports = Router()
|
const gitlabAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new GitlabStrategy({
|
passport.use(new GitlabStrategy({
|
||||||
baseURL: config.gitlab.baseURL,
|
baseURL: config.gitlab.baseURL,
|
||||||
|
|
|
@ -6,7 +6,7 @@ var GoogleStrategy = require('passport-google-oauth20').Strategy
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let googleAuth = module.exports = Router()
|
const googleAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new GoogleStrategy({
|
passport.use(new GoogleStrategy({
|
||||||
clientID: config.google.clientID,
|
clientID: config.google.clientID,
|
||||||
|
|
|
@ -10,7 +10,7 @@ const { setReturnToFromReferer } = require('../utils')
|
||||||
const { urlencodedParser } = require('../../utils')
|
const { urlencodedParser } = require('../../utils')
|
||||||
const response = require('../../../response')
|
const response = require('../../../response')
|
||||||
|
|
||||||
let ldapAuth = module.exports = Router()
|
const ldapAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new LDAPStrategy({
|
passport.use(new LDAPStrategy({
|
||||||
server: {
|
server: {
|
||||||
|
|
|
@ -8,11 +8,11 @@ const OAuthStrategy = require('passport-oauth2').Strategy
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let mattermostAuth = module.exports = Router()
|
const mattermostAuth = module.exports = Router()
|
||||||
|
|
||||||
const mattermostClient = new MattermostClient()
|
const mattermostClient = new MattermostClient()
|
||||||
|
|
||||||
let mattermostStrategy = new OAuthStrategy({
|
const mattermostStrategy = new OAuthStrategy({
|
||||||
authorizationURL: config.mattermost.baseURL + '/oauth/authorize',
|
authorizationURL: config.mattermost.baseURL + '/oauth/authorize',
|
||||||
tokenURL: config.mattermost.baseURL + '/oauth/access_token',
|
tokenURL: config.mattermost.baseURL + '/oauth/access_token',
|
||||||
clientID: config.mattermost.clientID,
|
clientID: config.mattermost.clientID,
|
||||||
|
|
|
@ -6,7 +6,7 @@ const { Strategy, InternalOAuthError } = require('passport-oauth2')
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let oauth2Auth = module.exports = Router()
|
const oauth2Auth = module.exports = Router()
|
||||||
|
|
||||||
class OAuth2CustomStrategy extends Strategy {
|
class OAuth2CustomStrategy extends Strategy {
|
||||||
constructor (options, verify) {
|
constructor (options, verify) {
|
||||||
|
@ -31,7 +31,7 @@ class OAuth2CustomStrategy extends Strategy {
|
||||||
return done(new Error('Failed to parse user profile'))
|
return done(new Error('Failed to parse user profile'))
|
||||||
}
|
}
|
||||||
|
|
||||||
let profile = parseProfile(json)
|
const profile = parseProfile(json)
|
||||||
profile.provider = 'oauth2'
|
profile.provider = 'oauth2'
|
||||||
|
|
||||||
done(null, profile)
|
done(null, profile)
|
||||||
|
@ -76,7 +76,7 @@ OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
|
||||||
return done(new Error('Failed to parse user profile'))
|
return done(new Error('Failed to parse user profile'))
|
||||||
}
|
}
|
||||||
|
|
||||||
let profile = parseProfile(json)
|
const profile = parseProfile(json)
|
||||||
profile.provider = 'oauth2'
|
profile.provider = 'oauth2'
|
||||||
|
|
||||||
done(null, profile)
|
done(null, profile)
|
||||||
|
|
|
@ -9,7 +9,7 @@ const logger = require('../../../logger')
|
||||||
const { urlencodedParser } = require('../../utils')
|
const { urlencodedParser } = require('../../utils')
|
||||||
const { setReturnToFromReferer } = require('../utils')
|
const { setReturnToFromReferer } = require('../utils')
|
||||||
|
|
||||||
let openIDAuth = module.exports = Router()
|
const openIDAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new OpenIDStrategy({
|
passport.use(new OpenIDStrategy({
|
||||||
returnURL: config.serverURL + '/auth/openid/callback',
|
returnURL: config.serverURL + '/auth/openid/callback',
|
||||||
|
|
|
@ -10,7 +10,7 @@ const { urlencodedParser } = require('../../utils')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) }
|
const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) }
|
||||||
|
|
||||||
let samlAuth = module.exports = Router()
|
const samlAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new SamlStrategy({
|
passport.use(new SamlStrategy({
|
||||||
callbackUrl: config.serverURL + '/auth/saml/callback',
|
callbackUrl: config.serverURL + '/auth/saml/callback',
|
||||||
|
|
|
@ -7,7 +7,7 @@ const TwitterStrategy = require('passport-twitter').Strategy
|
||||||
const config = require('../../../config')
|
const config = require('../../../config')
|
||||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||||
|
|
||||||
let twitterAuth = module.exports = Router()
|
const twitterAuth = module.exports = Router()
|
||||||
|
|
||||||
passport.use(new TwitterStrategy({
|
passport.use(new TwitterStrategy({
|
||||||
consumerKey: config.twitter.consumerKey,
|
consumerKey: config.twitter.consumerKey,
|
||||||
|
|
|
@ -32,16 +32,16 @@ exports.uploadImage = function (imagePath, callback) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = path.join('uploads', path.basename(imagePath))
|
const key = path.join('uploads', path.basename(imagePath))
|
||||||
let protocol = config.minio.secure ? 'https' : 'http'
|
const protocol = config.minio.secure ? 'https' : 'http'
|
||||||
|
|
||||||
minioClient.putObject(config.s3bucket, key, buffer, buffer.size, getImageMimeType(imagePath), function (err, data) {
|
minioClient.putObject(config.s3bucket, key, buffer, buffer.size, getImageMimeType(imagePath), function (err, data) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(new Error(err), null)
|
callback(new Error(err), null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let hidePort = [80, 443].includes(config.minio.port)
|
const hidePort = [80, 443].includes(config.minio.port)
|
||||||
let urlPort = hidePort ? '' : `:${config.minio.port}`
|
const urlPort = hidePort ? '' : `:${config.minio.port}`
|
||||||
callback(null, `${protocol}://${config.minio.endPoint}${urlPort}/${config.s3bucket}/${key}`)
|
callback(null, `${protocol}://${config.minio.endPoint}${urlPort}/${config.s3bucket}/${key}`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -26,7 +26,7 @@ exports.uploadImage = function (imagePath, callback) {
|
||||||
callback(new Error(err), null)
|
callback(new Error(err), null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let params = {
|
const params = {
|
||||||
Bucket: config.s3bucket,
|
Bucket: config.s3bucket,
|
||||||
Key: path.join('uploads', path.basename(imagePath)),
|
Key: path.join('uploads', path.basename(imagePath)),
|
||||||
Body: buffer
|
Body: buffer
|
||||||
|
|
|
@ -69,8 +69,7 @@ UserRouter.get('/me/delete/:token?', function (req, res) {
|
||||||
// export the data of the authenticated user
|
// export the data of the authenticated user
|
||||||
UserRouter.get('/me/export', function (req, res) {
|
UserRouter.get('/me/export', function (req, res) {
|
||||||
if (req.isAuthenticated()) {
|
if (req.isAuthenticated()) {
|
||||||
// let output = fs.createWriteStream(__dirname + '/example.zip');
|
const archive = archiver('zip', {
|
||||||
let archive = archiver('zip', {
|
|
||||||
zlib: { level: 3 } // Sets the compression level.
|
zlib: { level: 3 } // Sets the compression level.
|
||||||
})
|
})
|
||||||
res.setHeader('Content-Type', 'application/zip')
|
res.setHeader('Content-Type', 'application/zip')
|
||||||
|
@ -90,14 +89,14 @@ UserRouter.get('/me/export', function (req, res) {
|
||||||
ownerId: user.id
|
ownerId: user.id
|
||||||
}
|
}
|
||||||
}).then(function (notes) {
|
}).then(function (notes) {
|
||||||
let filenames = {}
|
const filenames = {}
|
||||||
async.each(notes, function (note, callback) {
|
async.each(notes, function (note, callback) {
|
||||||
let basename = note.title.replace(/\//g, '-') // Prevent subdirectories
|
const basename = note.title.replace(/\//g, '-') // Prevent subdirectories
|
||||||
let filename
|
let filename
|
||||||
let suffix = ''
|
let suffix = 0
|
||||||
do {
|
do {
|
||||||
let seperator = typeof suffix === 'number' ? '-' : ''
|
const separator = suffix === 0 ? '' : '-'
|
||||||
filename = basename + seperator + suffix + '.md'
|
filename = basename + separator + suffix + '.md'
|
||||||
suffix++
|
suffix++
|
||||||
} while (filenames[filename])
|
} while (filenames[filename])
|
||||||
filenames[filename] = true
|
filenames[filename] = true
|
||||||
|
|
|
@ -13,7 +13,7 @@ process.on('message', function (data) {
|
||||||
}
|
}
|
||||||
switch (data.msg) {
|
switch (data.msg) {
|
||||||
case 'create patch':
|
case 'create patch':
|
||||||
if (!data.hasOwnProperty('lastDoc') || !data.hasOwnProperty('currDoc')) {
|
if (!Object.hasOwnProperty.call(data, 'lastDoc') || !Object.hasOwnProperty.call(data, 'currDoc')) {
|
||||||
return logger.error('dmp worker error: not enough data on create patch')
|
return logger.error('dmp worker error: not enough data on create patch')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -33,7 +33,7 @@ process.on('message', function (data) {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case 'get revision':
|
case 'get revision':
|
||||||
if (!data.hasOwnProperty('revisions') || !data.hasOwnProperty('count')) {
|
if (!Object.hasOwnProperty.call(data, 'revisions') || !Object.hasOwnProperty.call(data, 'count')) {
|
||||||
return logger.error('dmp worker error: not enough data on get revision')
|
return logger.error('dmp worker error: not enough data on get revision')
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -77,12 +77,12 @@ function getRevision (revisions, count) {
|
||||||
if (count <= Math.round(revisions.length / 2)) {
|
if (count <= Math.round(revisions.length / 2)) {
|
||||||
// start from top to target
|
// start from top to target
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
let revision = revisions[i]
|
const revision = revisions[i]
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
startContent = revision.content || revision.lastContent
|
startContent = revision.content || revision.lastContent
|
||||||
}
|
}
|
||||||
if (i !== count - 1) {
|
if (i !== count - 1) {
|
||||||
let patch = dmp.patch_fromText(revision.patch)
|
const patch = dmp.patch_fromText(revision.patch)
|
||||||
applyPatches = applyPatches.concat(patch)
|
applyPatches = applyPatches.concat(patch)
|
||||||
}
|
}
|
||||||
lastPatch = revision.patch
|
lastPatch = revision.patch
|
||||||
|
@ -99,13 +99,13 @@ function getRevision (revisions, count) {
|
||||||
// start from bottom to target
|
// start from bottom to target
|
||||||
var l = revisions.length - 1
|
var l = revisions.length - 1
|
||||||
for (var i = l; i >= count - 1; i--) {
|
for (var i = l; i >= count - 1; i--) {
|
||||||
let revision = revisions[i]
|
const revision = revisions[i]
|
||||||
if (i === l) {
|
if (i === l) {
|
||||||
startContent = revision.lastContent
|
startContent = revision.lastContent
|
||||||
authorship = revision.authorship
|
authorship = revision.authorship
|
||||||
}
|
}
|
||||||
if (revision.patch) {
|
if (revision.patch) {
|
||||||
let patch = dmp.patch_fromText(revision.patch)
|
const patch = dmp.patch_fromText(revision.patch)
|
||||||
applyPatches = applyPatches.concat(patch)
|
applyPatches = applyPatches.concat(patch)
|
||||||
}
|
}
|
||||||
lastPatch = revision.patch
|
lastPatch = revision.patch
|
||||||
|
|
114
package.json
114
package.json
|
@ -30,62 +30,61 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hackmd/codemirror": "~5.46.2",
|
"@hackmd/codemirror": "~5.46.2",
|
||||||
"@hackmd/diff-match-patch": "~1.1.1",
|
"@hackmd/diff-match-patch": "~1.1.3",
|
||||||
"@hackmd/idle-js": "~1.0.1",
|
"@hackmd/idle-js": "~1.0.1",
|
||||||
"@hackmd/imgur": "~0.4.1",
|
"@hackmd/imgur": "~0.4.1",
|
||||||
"@hackmd/js-sequence-diagrams": "~0.0.1-alpha.3",
|
"@hackmd/js-sequence-diagrams": "~0.0.1-alpha.3",
|
||||||
"@hackmd/lz-string": "~1.4.4",
|
"@hackmd/lz-string": "~1.4.4",
|
||||||
"@hackmd/meta-marked": "~0.4.4",
|
"@hackmd/meta-marked": "~0.4.4",
|
||||||
"@passport-next/passport-openid": "~1.0.0",
|
"@passport-next/passport-openid": "~1.0.0",
|
||||||
"archiver": "~2.1.1",
|
"archiver": "~3.1.1",
|
||||||
"async": "~2.1.4",
|
"async": "~3.1.0",
|
||||||
"aws-sdk": "~2.345.0",
|
"aws-sdk": "~2.503.0",
|
||||||
"azure-storage": "~2.10.2",
|
"azure-storage": "~2.10.3",
|
||||||
"babel-polyfill": "~6.26.0",
|
"babel-polyfill": "~6.26.0",
|
||||||
"base64url": "~3.0.0",
|
"base64url": "~3.0.1",
|
||||||
"body-parser": "~1.18.3",
|
"body-parser": "~1.19.0",
|
||||||
"bootstrap": "~3.4.0",
|
"bootstrap": "~3.4.0",
|
||||||
"bootstrap-validator": "~0.11.8",
|
"bootstrap-validator": "~0.11.8",
|
||||||
"chance": "~1.0.4",
|
"chance": "~1.0.18",
|
||||||
"cheerio": "~0.22.0",
|
"cheerio": "~0.22.0",
|
||||||
"compression": "~1.7.4",
|
|
||||||
"connect-flash": "~0.1.1",
|
"connect-flash": "~0.1.1",
|
||||||
"connect-session-sequelize": "~6.0.0",
|
"connect-session-sequelize": "~6.0.0",
|
||||||
"cookie": "~0.3.1",
|
"cookie": "~0.4.0",
|
||||||
"cookie-parser": "~1.4.3",
|
"cookie-parser": "~1.4.4",
|
||||||
"deep-freeze": "~0.0.1",
|
"deep-freeze": "~0.0.1",
|
||||||
"ejs": "~2.5.5",
|
"ejs": "~2.6.2",
|
||||||
"emojify.js": "~1.1.0",
|
"emojify.js": "~1.1.0",
|
||||||
"express": "~4.16.4",
|
"express": "~4.17.1",
|
||||||
"express-session": "~1.16.1",
|
"express-session": "~1.16.2",
|
||||||
"file-saver": "~1.3.3",
|
"file-saver": "~2.0.2",
|
||||||
"flowchart.js": "~1.12.0",
|
"flowchart.js": "~1.12.2",
|
||||||
"fork-awesome": "~1.1.3",
|
"fork-awesome": "~1.1.7",
|
||||||
"formidable": "~1.2.1",
|
"formidable": "~1.2.1",
|
||||||
"gist-embed": "~2.6.0",
|
"gist-embed": "~2.6.0",
|
||||||
"graceful-fs": "~4.1.11",
|
"graceful-fs": "~4.2.1",
|
||||||
"handlebars": "~4.0.13",
|
"handlebars": "~4.1.2",
|
||||||
"helmet": "~3.13.0",
|
"helmet": "~3.20.0",
|
||||||
"highlight.js": "~9.12.0",
|
"highlight.js": "~9.15.9",
|
||||||
"i18n": "~0.8.3",
|
"i18n": "~0.8.3",
|
||||||
"ionicons": "~2.0.1",
|
"ionicons": "~2.0.1",
|
||||||
"isomorphic-fetch": "~2.2.1",
|
"isomorphic-fetch": "~2.2.1",
|
||||||
"jquery": "~3.1.1",
|
"jquery": "~3.4.1",
|
||||||
"jquery-mousewheel": "~3.1.13",
|
"jquery-mousewheel": "~3.1.13",
|
||||||
"jquery-ui": "~1.12.1",
|
"jquery-ui": "~1.12.1",
|
||||||
"js-cookie": "~2.1.3",
|
"js-cookie": "~2.2.0",
|
||||||
"js-yaml": "~3.13.1",
|
"js-yaml": "~3.13.1",
|
||||||
"jsdom-nogyp": "~0.8.3",
|
"jsdom-nogyp": "~0.8.3",
|
||||||
"keymaster": "~1.6.2",
|
"keymaster": "~1.6.2",
|
||||||
"list.js": "~1.5.0",
|
"list.js": "~1.5.0",
|
||||||
"lodash": "~4.17.11",
|
"lodash": "~4.17.15",
|
||||||
"lutim": "~1.0.2",
|
"lutim": "~1.0.2",
|
||||||
"markdown-it": "~8.2.2",
|
"markdown-it": "~9.0.1",
|
||||||
"markdown-it-abbr": "~1.0.4",
|
"markdown-it-abbr": "~1.0.4",
|
||||||
"markdown-it-container": "~2.0.0",
|
"markdown-it-container": "~2.0.0",
|
||||||
"markdown-it-deflist": "~2.0.1",
|
"markdown-it-deflist": "~2.0.3",
|
||||||
"markdown-it-emoji": "~1.3.0",
|
"markdown-it-emoji": "~1.4.0",
|
||||||
"markdown-it-footnote": "~3.0.1",
|
"markdown-it-footnote": "~3.0.2",
|
||||||
"markdown-it-imsize": "~2.0.1",
|
"markdown-it-imsize": "~2.0.1",
|
||||||
"markdown-it-ins": "~2.0.0",
|
"markdown-it-ins": "~2.0.0",
|
||||||
"markdown-it-mark": "~2.0.0",
|
"markdown-it-mark": "~2.0.0",
|
||||||
|
@ -94,15 +93,15 @@
|
||||||
"markdown-it-sub": "~1.0.0",
|
"markdown-it-sub": "~1.0.0",
|
||||||
"markdown-it-sup": "~1.0.0",
|
"markdown-it-sup": "~1.0.0",
|
||||||
"markdown-pdf": "~9.0.0",
|
"markdown-pdf": "~9.0.0",
|
||||||
"mathjax": "~2.7.0",
|
"mathjax": "~2.7.5",
|
||||||
"mattermost-redux": "~5.9.0",
|
"mattermost-redux": "~5.13.0",
|
||||||
"mermaid": "~8.2.3",
|
"mermaid": "~8.2.3",
|
||||||
"method-override": "~2.3.7",
|
"method-override": "~3.0.0",
|
||||||
"minimist": "~1.2.0",
|
"minimist": "~1.2.0",
|
||||||
"minio": "~6.0.0",
|
"minio": "~7.0.10",
|
||||||
"moment": "~2.24.0",
|
"moment": "~2.24.0",
|
||||||
"morgan": "~1.9.1",
|
"morgan": "~1.9.1",
|
||||||
"mysql": "~2.16.0",
|
"mysql": "~2.17.1",
|
||||||
"passport": "~0.4.0",
|
"passport": "~0.4.0",
|
||||||
"passport-dropbox-oauth2": "~1.1.0",
|
"passport-dropbox-oauth2": "~1.1.0",
|
||||||
"passport-facebook": "~2.1.1",
|
"passport-facebook": "~2.1.1",
|
||||||
|
@ -115,12 +114,12 @@
|
||||||
"passport-saml": "~1.0.0",
|
"passport-saml": "~1.0.0",
|
||||||
"passport-twitter": "~1.0.4",
|
"passport-twitter": "~1.0.4",
|
||||||
"passport.socketio": "~3.7.0",
|
"passport.socketio": "~3.7.0",
|
||||||
"pdfobject": "~2.0.201604172",
|
"pdfobject": "~2.1.1",
|
||||||
"pg": "~6.1.2",
|
"pg": "~6.1.2",
|
||||||
"pg-hstore": "~2.3.2",
|
"pg-hstore": "~2.3.2",
|
||||||
"plantuml-encoder": "^1.2.5",
|
"plantuml-encoder": "^1.2.5",
|
||||||
"prismjs": "~1.6.0",
|
"prismjs": "~1.17.1",
|
||||||
"randomcolor": "~0.5.3",
|
"randomcolor": "~0.5.4",
|
||||||
"raphael": "~2.2.8",
|
"raphael": "~2.2.8",
|
||||||
"readline-sync": "~1.4.7",
|
"readline-sync": "~1.4.7",
|
||||||
"request": "~2.88.0",
|
"request": "~2.88.0",
|
||||||
|
@ -128,27 +127,27 @@
|
||||||
"scrypt": "~6.0.3",
|
"scrypt": "~6.0.3",
|
||||||
"select2": "~3.5.2-browserify",
|
"select2": "~3.5.2-browserify",
|
||||||
"sequelize": "5.3.5",
|
"sequelize": "5.3.5",
|
||||||
"shortid": "~2.2.8",
|
"shortid": "~2.2.14",
|
||||||
"socket.io": "~2.1.1",
|
"socket.io": "~2.2.0",
|
||||||
"socket.io-client": "~2.1.1",
|
"socket.io-client": "~2.2.0",
|
||||||
"spin.js": "~2.3.2",
|
"spin.js": "~4.0.0",
|
||||||
"sqlite3": "~4.0.1",
|
"sqlite3": "~4.0.9",
|
||||||
"store": "~2.0.12",
|
"store": "~2.0.12",
|
||||||
"tedious": "~6.1.0",
|
"tedious": "~6.2.0",
|
||||||
"toobusy-js": "~0.5.1",
|
"toobusy-js": "~0.5.1",
|
||||||
"turndown": "~5.0.1",
|
"turndown": "~5.0.3",
|
||||||
"uuid": "~3.1.0",
|
"uuid": "~3.3.2",
|
||||||
"validator": "~10.4.0",
|
"validator": "~11.1.0",
|
||||||
"vega": "~5.4.0",
|
"vega": "~5.4.0",
|
||||||
"vega-embed": "~4.2.2",
|
"vega-embed": "~4.2.2",
|
||||||
"vega-lite": "~3.4.0",
|
"vega-lite": "~3.4.0",
|
||||||
"velocity-animate": "~1.4.0",
|
"velocity-animate": "~1.5.2",
|
||||||
"visibilityjs": "~1.2.4",
|
"visibilityjs": "~2.0.2",
|
||||||
"viz.js": "~1.7.0",
|
"viz.js": "~2.1.2",
|
||||||
"winston": "~3.1.0",
|
"winston": "~3.2.1",
|
||||||
"ws": "~6.0.0",
|
"ws": "~7.1.1",
|
||||||
"wurl": "~2.5.3",
|
"wurl": "~2.5.3",
|
||||||
"xss": "~1.0.3"
|
"xss": "~1.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~6.1.1",
|
"acorn": "~6.1.1",
|
||||||
|
@ -179,14 +178,14 @@
|
||||||
"script-loader": "~0.7.2",
|
"script-loader": "~0.7.2",
|
||||||
"sequelize-cli": "~5.4.0",
|
"sequelize-cli": "~5.4.0",
|
||||||
"sinon": "~7.3.2",
|
"sinon": "~7.3.2",
|
||||||
"standard": "~12.0.1",
|
"standard": "~13.1.0",
|
||||||
"string-loader": "~0.0.1",
|
"string-loader": "~0.0.1",
|
||||||
"style-loader": "~0.21.0",
|
"style-loader": "~0.23.1",
|
||||||
"uglifyjs-webpack-plugin": "~1.2.7",
|
"uglifyjs-webpack-plugin": "~1.2.7",
|
||||||
"url-loader": "~1.0.1",
|
"url-loader": "~1.0.1",
|
||||||
"webpack": "~4.30.0",
|
"webpack": "~4.39.0",
|
||||||
"webpack-cli": "~3.3.0",
|
"webpack-cli": "~3.3.6",
|
||||||
"webpack-merge": "~4.1.4",
|
"webpack-merge": "~4.2.1",
|
||||||
"webpack-parallel-uglify-plugin": "~1.1.0"
|
"webpack-parallel-uglify-plugin": "~1.1.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
|
@ -210,7 +209,8 @@
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"/public/build",
|
"/public/build",
|
||||||
"/public/vendor",
|
"/public/vendor",
|
||||||
"/lib/ot"
|
"/lib/ot",
|
||||||
|
"webpack.*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nyc": {
|
"nyc": {
|
||||||
|
|
|
@ -10,7 +10,6 @@ module.exports = {
|
||||||
"moment": false,
|
"moment": false,
|
||||||
"editor": false,
|
"editor": false,
|
||||||
"ui": false,
|
"ui": false,
|
||||||
"Spinner": false,
|
|
||||||
"modeType": false,
|
"modeType": false,
|
||||||
"serverurl": false,
|
"serverurl": false,
|
||||||
"key": false,
|
"key": false,
|
||||||
|
|
|
@ -350,7 +350,7 @@ export function finishView (view) {
|
||||||
$value.html('')
|
$value.html('')
|
||||||
chart.drawSVG(value, {
|
chart.drawSVG(value, {
|
||||||
'line-width': 2,
|
'line-width': 2,
|
||||||
'fill': 'none',
|
fill: 'none',
|
||||||
'font-size': '16px',
|
'font-size': '16px',
|
||||||
'font-family': "'Andale Mono', monospace"
|
'font-family': "'Andale Mono', monospace"
|
||||||
})
|
})
|
||||||
|
@ -773,12 +773,12 @@ export function generateToc (id) {
|
||||||
target.html('')
|
target.html('')
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
var toc = new window.Toc('doc', {
|
var toc = new window.Toc('doc', {
|
||||||
'level': 3,
|
level: 3,
|
||||||
'top': -1,
|
top: -1,
|
||||||
'class': 'toc',
|
class: 'toc',
|
||||||
'ulClass': 'nav',
|
ulClass: 'nav',
|
||||||
'targetId': id,
|
targetId: id,
|
||||||
'process': getHeaderContent
|
process: getHeaderContent
|
||||||
})
|
})
|
||||||
/* eslint-enable no-unused-vars */
|
/* eslint-enable no-unused-vars */
|
||||||
if (target.text() === 'undefined') { target.html('') }
|
if (target.text() === 'undefined') { target.html('') }
|
||||||
|
@ -861,7 +861,7 @@ const linkifyAnchors = (level, containingElement) => {
|
||||||
const headers = containingElement.getElementsByTagName(`h${level}`)
|
const headers = containingElement.getElementsByTagName(`h${level}`)
|
||||||
|
|
||||||
for (let i = 0, l = headers.length; i < l; i++) {
|
for (let i = 0, l = headers.length; i < l; i++) {
|
||||||
let header = headers[i]
|
const header = headers[i]
|
||||||
if (header.getElementsByClassName('anchor').length === 0) {
|
if (header.getElementsByClassName('anchor').length === 0) {
|
||||||
if (typeof header.id === 'undefined' || header.id === '') {
|
if (typeof header.id === 'undefined' || header.id === '') {
|
||||||
// to escape characters not allow in css and humanize
|
// to escape characters not allow in css and humanize
|
||||||
|
@ -920,12 +920,12 @@ export function renderTOC (view) {
|
||||||
const target = $(`#${id}`)
|
const target = $(`#${id}`)
|
||||||
target.html('')
|
target.html('')
|
||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
let TOC = new window.Toc('doc', {
|
const TOC = new window.Toc('doc', {
|
||||||
'level': 3,
|
level: 3,
|
||||||
'top': -1,
|
top: -1,
|
||||||
'class': 'toc',
|
class: 'toc',
|
||||||
'targetId': id,
|
targetId: id,
|
||||||
'process': getHeaderContent
|
process: getHeaderContent
|
||||||
})
|
})
|
||||||
/* eslint-enable no-unused-vars */
|
/* eslint-enable no-unused-vars */
|
||||||
if (target.text() === 'undefined') { target.html('') }
|
if (target.text() === 'undefined') { target.html('') }
|
||||||
|
@ -975,7 +975,7 @@ function highlightRender (code, lang) {
|
||||||
return result.value
|
return result.value
|
||||||
}
|
}
|
||||||
|
|
||||||
export let md = markdownit('default', {
|
export const md = markdownit('default', {
|
||||||
html: true,
|
html: true,
|
||||||
breaks: true,
|
breaks: true,
|
||||||
langPrefix: '',
|
langPrefix: '',
|
||||||
|
@ -1044,7 +1044,7 @@ md.use(markdownitContainer, 'spoiler', {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let defaultImageRender = md.renderer.rules.image
|
const defaultImageRender = md.renderer.rules.image
|
||||||
md.renderer.rules.image = function (tokens, idx, options, env, self) {
|
md.renderer.rules.image = function (tokens, idx, options, env, self) {
|
||||||
tokens[idx].attrJoin('class', 'raw')
|
tokens[idx].attrJoin('class', 'raw')
|
||||||
return defaultImageRender(...arguments)
|
return defaultImageRender(...arguments)
|
||||||
|
@ -1089,26 +1089,26 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const makePlantumlURL = (umlCode) => {
|
const makePlantumlURL = (umlCode) => {
|
||||||
let format = 'svg'
|
const format = 'svg'
|
||||||
let code = plantumlEncoder.encode(umlCode)
|
const code = plantumlEncoder.encode(umlCode)
|
||||||
return `${plantumlServer}/${format}/${code}`
|
return `${plantumlServer}/${format}/${code}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml
|
// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml
|
||||||
md.renderer.rules.plantuml = (tokens, idx) => {
|
md.renderer.rules.plantuml = (tokens, idx) => {
|
||||||
let token = tokens[idx]
|
const token = tokens[idx]
|
||||||
if (token.type !== 'plantuml') {
|
if (token.type !== 'plantuml') {
|
||||||
return tokens[idx].content
|
return tokens[idx].content
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = makePlantumlURL(token.content)
|
const url = makePlantumlURL(token.content)
|
||||||
return `<img src="${url}" />`
|
return `<img src="${url}" />`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml
|
// https://github.com/qjebbs/vscode-plantuml/tree/master/src/markdown-it-plantuml
|
||||||
md.core.ruler.push('plantuml', (state) => {
|
md.core.ruler.push('plantuml', (state) => {
|
||||||
let blockTokens = state.tokens
|
const blockTokens = state.tokens
|
||||||
for (let blockToken of blockTokens) {
|
for (const blockToken of blockTokens) {
|
||||||
if (blockToken.type === 'fence' && blockToken.info === 'plantuml') {
|
if (blockToken.type === 'fence' && blockToken.info === 'plantuml') {
|
||||||
blockToken.type = 'plantuml'
|
blockToken.type = 'plantuml'
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ export function writeHistory (title, tags) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeHistoryToStorage (title, tags) {
|
function writeHistoryToStorage (title, tags) {
|
||||||
let data = store.get('notehistory')
|
const data = store.get('notehistory')
|
||||||
let notehistory
|
let notehistory
|
||||||
if (data && typeof data === 'string') {
|
if (data && typeof data === 'string') {
|
||||||
notehistory = JSON.parse(data)
|
notehistory = JSON.parse(data)
|
||||||
|
@ -260,7 +260,7 @@ function parseToHistory (list, notehistory, callback) {
|
||||||
for (let i = 0; i < notehistory.length; i++) {
|
for (let i = 0; i < notehistory.length; i++) {
|
||||||
// migrate LZString encoded id to base64url encoded id
|
// migrate LZString encoded id to base64url encoded id
|
||||||
try {
|
try {
|
||||||
let id = LZString.decompressFromBase64(notehistory[i].id)
|
const id = LZString.decompressFromBase64(notehistory[i].id)
|
||||||
if (id && checkNoteIdValid(id)) {
|
if (id && checkNoteIdValid(id)) {
|
||||||
notehistory[i].id = encodeNoteId(id)
|
notehistory[i].id = encodeNoteId(id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-env browser, jquery */
|
/* eslint-env browser, jquery */
|
||||||
/* global CodeMirror, Cookies, moment, Spinner, serverurl,
|
/* global CodeMirror, Cookies, moment, serverurl,
|
||||||
key, Dropbox, ot, hex2rgb, Visibility, inlineAttachment */
|
key, Dropbox, ot, hex2rgb, Visibility, inlineAttachment */
|
||||||
|
|
||||||
import TurndownService from 'turndown'
|
import TurndownService from 'turndown'
|
||||||
|
@ -17,6 +17,8 @@ import List from 'list.js'
|
||||||
|
|
||||||
import Idle from '@hackmd/idle-js'
|
import Idle from '@hackmd/idle-js'
|
||||||
|
|
||||||
|
import { Spinner } from 'spin.js'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkLoginStateChanged,
|
checkLoginStateChanged,
|
||||||
setloginStateChangeEvent
|
setloginStateChangeEvent
|
||||||
|
@ -83,6 +85,7 @@ require('../css/index.css')
|
||||||
require('../css/extra.css')
|
require('../css/extra.css')
|
||||||
require('../css/slide-preview.css')
|
require('../css/slide-preview.css')
|
||||||
require('../css/site.css')
|
require('../css/site.css')
|
||||||
|
require('spin.js/spin.css')
|
||||||
|
|
||||||
require('highlight.js/styles/github-gist.css')
|
require('highlight.js/styles/github-gist.css')
|
||||||
|
|
||||||
|
@ -260,7 +263,7 @@ let visibleMD = false
|
||||||
let visibleLG = false
|
let visibleLG = false
|
||||||
const isTouchDevice = 'ontouchstart' in document.documentElement
|
const isTouchDevice = 'ontouchstart' in document.documentElement
|
||||||
let currentStatus = statusType.offline
|
let currentStatus = statusType.offline
|
||||||
let lastInfo = {
|
const lastInfo = {
|
||||||
needRestore: false,
|
needRestore: false,
|
||||||
cursor: null,
|
cursor: null,
|
||||||
scroll: null,
|
scroll: null,
|
||||||
|
@ -286,14 +289,14 @@ let lastInfo = {
|
||||||
let personalInfo = {}
|
let personalInfo = {}
|
||||||
let onlineUsers = []
|
let onlineUsers = []
|
||||||
const fileTypes = {
|
const fileTypes = {
|
||||||
'pl': 'perl',
|
pl: 'perl',
|
||||||
'cgi': 'perl',
|
cgi: 'perl',
|
||||||
'js': 'javascript',
|
js: 'javascript',
|
||||||
'php': 'php',
|
php: 'php',
|
||||||
'sh': 'bash',
|
sh: 'bash',
|
||||||
'rb': 'ruby',
|
rb: 'ruby',
|
||||||
'html': 'html',
|
html: 'html',
|
||||||
'py': 'python'
|
py: 'python'
|
||||||
}
|
}
|
||||||
|
|
||||||
// editor settings
|
// editor settings
|
||||||
|
@ -334,9 +337,7 @@ var opts = {
|
||||||
left: '50%' // Left position relative to parent
|
left: '50%' // Left position relative to parent
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable no-unused-vars */
|
new Spinner(opts).spin(ui.spinner[0])
|
||||||
var spinner = new Spinner(opts).spin(ui.spinner[0])
|
|
||||||
/* eslint-enable no-unused-vars */
|
|
||||||
|
|
||||||
// idle
|
// idle
|
||||||
var idle = new Idle({
|
var idle = new Idle({
|
||||||
|
@ -955,8 +956,8 @@ ui.toolbar.export.dropbox.click(function () {
|
||||||
var options = {
|
var options = {
|
||||||
files: [
|
files: [
|
||||||
{
|
{
|
||||||
'url': noteurl + '/download',
|
url: noteurl + '/download',
|
||||||
'filename': filename
|
filename: filename
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
error: function (errorMessage) {
|
error: function (errorMessage) {
|
||||||
|
@ -1787,29 +1788,29 @@ var authorMarks = {} // temp variable
|
||||||
var addTextMarkers = [] // temp variable
|
var addTextMarkers = [] // temp variable
|
||||||
function updateInfo (data) {
|
function updateInfo (data) {
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
if (data.hasOwnProperty('createtime') && window.createtime !== data.createtime) {
|
if (Object.hasOwnProperty.call(data, 'createtime') && window.createtime !== data.createtime) {
|
||||||
window.createtime = data.createtime
|
window.createtime = data.createtime
|
||||||
updateLastChange()
|
updateLastChange()
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('updatetime') && window.lastchangetime !== data.updatetime) {
|
if (Object.hasOwnProperty.call(data, 'updatetime') && window.lastchangetime !== data.updatetime) {
|
||||||
window.lastchangetime = data.updatetime
|
window.lastchangetime = data.updatetime
|
||||||
updateLastChange()
|
updateLastChange()
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('owner') && window.owner !== data.owner) {
|
if (Object.hasOwnProperty.call(data, 'owner') && window.owner !== data.owner) {
|
||||||
window.owner = data.owner
|
window.owner = data.owner
|
||||||
window.ownerprofile = data.ownerprofile
|
window.ownerprofile = data.ownerprofile
|
||||||
updateOwner()
|
updateOwner()
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('lastchangeuser') && window.lastchangeuser !== data.lastchangeuser) {
|
if (Object.hasOwnProperty.call(data, 'lastchangeuser') && window.lastchangeuser !== data.lastchangeuser) {
|
||||||
window.lastchangeuser = data.lastchangeuser
|
window.lastchangeuser = data.lastchangeuser
|
||||||
window.lastchangeuserprofile = data.lastchangeuserprofile
|
window.lastchangeuserprofile = data.lastchangeuserprofile
|
||||||
updateLastChangeUser()
|
updateLastChangeUser()
|
||||||
updateOwner()
|
updateOwner()
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('authors') && authors !== data.authors) {
|
if (Object.hasOwnProperty.call(data, 'authors') && authors !== data.authors) {
|
||||||
authors = data.authors
|
authors = data.authors
|
||||||
}
|
}
|
||||||
if (data.hasOwnProperty('authorship') && authorship !== data.authorship) {
|
if (Object.hasOwnProperty.call(data, 'authorship') && authorship !== data.authorship) {
|
||||||
authorship = data.authorship
|
authorship = data.authorship
|
||||||
updateAuthorship()
|
updateAuthorship()
|
||||||
}
|
}
|
||||||
|
@ -1854,7 +1855,7 @@ function updateAuthorshipInner () {
|
||||||
authorMarks = {}
|
authorMarks = {}
|
||||||
for (let i = 0; i < authorship.length; i++) {
|
for (let i = 0; i < authorship.length; i++) {
|
||||||
var atom = authorship[i]
|
var atom = authorship[i]
|
||||||
let author = authors[atom[0]]
|
const author = authors[atom[0]]
|
||||||
if (author) {
|
if (author) {
|
||||||
var prePos = editor.posFromIndex(atom[1])
|
var prePos = editor.posFromIndex(atom[1])
|
||||||
var preLine = editor.getLine(prePos.line)
|
var preLine = editor.getLine(prePos.line)
|
||||||
|
@ -1872,7 +1873,7 @@ function updateAuthorshipInner () {
|
||||||
if (prePos.ch === preLine.length) {
|
if (prePos.ch === preLine.length) {
|
||||||
startLine++
|
startLine++
|
||||||
} else if (prePos.ch !== 0) {
|
} else if (prePos.ch !== 0) {
|
||||||
let mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
|
const mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
|
||||||
var _postPos = {
|
var _postPos = {
|
||||||
line: prePos.line,
|
line: prePos.line,
|
||||||
ch: preLine.length
|
ch: preLine.length
|
||||||
|
@ -1889,7 +1890,7 @@ function updateAuthorshipInner () {
|
||||||
if (postPos.ch === 0) {
|
if (postPos.ch === 0) {
|
||||||
endLine--
|
endLine--
|
||||||
} else if (postPos.ch !== postLine.length) {
|
} else if (postPos.ch !== postLine.length) {
|
||||||
let mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3])
|
const mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3])
|
||||||
var _prePos = {
|
var _prePos = {
|
||||||
line: postPos.line,
|
line: postPos.line,
|
||||||
ch: 0
|
ch: 0
|
||||||
|
@ -1909,7 +1910,7 @@ function updateAuthorshipInner () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
|
const mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
|
||||||
if (JSON.stringify(prePos) !== JSON.stringify(postPos)) {
|
if (JSON.stringify(prePos) !== JSON.stringify(postPos)) {
|
||||||
mark.textmarkers.push({
|
mark.textmarkers.push({
|
||||||
userid: author.userid,
|
userid: author.userid,
|
||||||
|
@ -1922,15 +1923,15 @@ function updateAuthorshipInner () {
|
||||||
}
|
}
|
||||||
addTextMarkers = []
|
addTextMarkers = []
|
||||||
editor.eachLine(iterateLine)
|
editor.eachLine(iterateLine)
|
||||||
var allTextMarks = editor.getAllMarks()
|
const allTextMarks = editor.getAllMarks()
|
||||||
for (let i = 0; i < allTextMarks.length; i++) {
|
for (let i = 0; i < allTextMarks.length; i++) {
|
||||||
let _textMarker = allTextMarks[i]
|
const _textMarker = allTextMarks[i]
|
||||||
var pos = _textMarker.find()
|
const pos = _textMarker.find()
|
||||||
var found = false
|
let found = false
|
||||||
for (let j = 0; j < addTextMarkers.length; j++) {
|
for (let j = 0; j < addTextMarkers.length; j++) {
|
||||||
let textMarker = addTextMarkers[j]
|
const textMarker = addTextMarkers[j]
|
||||||
let author = authors[textMarker.userid]
|
const author = authors[textMarker.userid]
|
||||||
let className = 'authorship-inline-' + author.color.substr(1)
|
const className = 'authorship-inline-' + author.color.substr(1)
|
||||||
var obj = {
|
var obj = {
|
||||||
from: textMarker.pos[0],
|
from: textMarker.pos[0],
|
||||||
to: textMarker.pos[1]
|
to: textMarker.pos[1]
|
||||||
|
@ -1948,12 +1949,12 @@ function updateAuthorshipInner () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i = 0; i < addTextMarkers.length; i++) {
|
for (let i = 0; i < addTextMarkers.length; i++) {
|
||||||
let textMarker = addTextMarkers[i]
|
const textMarker = addTextMarkers[i]
|
||||||
let author = authors[textMarker.userid]
|
const author = authors[textMarker.userid]
|
||||||
const rgbcolor = hex2rgb(author.color)
|
const rgbcolor = hex2rgb(author.color)
|
||||||
const colorString = `rgba(${rgbcolor.red},${rgbcolor.green},${rgbcolor.blue},0.7)`
|
const colorString = `rgba(${rgbcolor.red},${rgbcolor.green},${rgbcolor.blue},0.7)`
|
||||||
const styleString = `background-image: linear-gradient(to top, ${colorString} 1px, transparent 1px);`
|
const styleString = `background-image: linear-gradient(to top, ${colorString} 1px, transparent 1px);`
|
||||||
let className = `authorship-inline-${author.color.substr(1)}`
|
const className = `authorship-inline-${author.color.substr(1)}`
|
||||||
const rule = `.${className} { ${styleString} }`
|
const rule = `.${className} { ${styleString} }`
|
||||||
addStyleRule(rule)
|
addStyleRule(rule)
|
||||||
editor.markText(textMarker.pos[0], textMarker.pos[1], {
|
editor.markText(textMarker.pos[0], textMarker.pos[1], {
|
||||||
|
@ -1963,11 +1964,11 @@ function updateAuthorshipInner () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function iterateLine (line) {
|
function iterateLine (line) {
|
||||||
var lineNumber = line.lineNo()
|
const lineNumber = line.lineNo()
|
||||||
var currMark = authorMarks[lineNumber]
|
const currMark = authorMarks[lineNumber]
|
||||||
var author = currMark ? authors[currMark.gutter.userid] : null
|
const author = currMark ? authors[currMark.gutter.userid] : null
|
||||||
if (currMark && author) {
|
if (currMark && author) {
|
||||||
let className = 'authorship-gutter-' + author.color.substr(1)
|
const className = 'authorship-gutter-' + author.color.substr(1)
|
||||||
const gutters = line.gutterMarkers
|
const gutters = line.gutterMarkers
|
||||||
if (!gutters || !gutters['authorship-gutters'] ||
|
if (!gutters || !gutters['authorship-gutters'] ||
|
||||||
!gutters['authorship-gutters'].className ||
|
!gutters['authorship-gutters'].className ||
|
||||||
|
@ -1975,7 +1976,7 @@ function iterateLine (line) {
|
||||||
const styleString = `border-left: 3px solid ${author.color}; height: ${defaultTextHeight}px; margin-left: 3px;`
|
const styleString = `border-left: 3px solid ${author.color}; height: ${defaultTextHeight}px; margin-left: 3px;`
|
||||||
const rule = `.${className} { ${styleString} }`
|
const rule = `.${className} { ${styleString} }`
|
||||||
addStyleRule(rule)
|
addStyleRule(rule)
|
||||||
var gutter = $('<div>', {
|
const gutter = $('<div>', {
|
||||||
class: 'authorship-gutter ' + className,
|
class: 'authorship-gutter ' + className,
|
||||||
title: author.name
|
title: author.name
|
||||||
})
|
})
|
||||||
|
@ -1985,8 +1986,8 @@ function iterateLine (line) {
|
||||||
editor.setGutterMarker(line, 'authorship-gutters', null)
|
editor.setGutterMarker(line, 'authorship-gutters', null)
|
||||||
}
|
}
|
||||||
if (currMark && currMark.textmarkers.length > 0) {
|
if (currMark && currMark.textmarkers.length > 0) {
|
||||||
for (var i = 0; i < currMark.textmarkers.length; i++) {
|
for (let i = 0; i < currMark.textmarkers.length; i++) {
|
||||||
let textMarker = currMark.textmarkers[i]
|
const textMarker = currMark.textmarkers[i]
|
||||||
if (textMarker.userid !== currMark.gutter.userid) {
|
if (textMarker.userid !== currMark.gutter.userid) {
|
||||||
addTextMarkers.push(textMarker)
|
addTextMarkers.push(textMarker)
|
||||||
}
|
}
|
||||||
|
@ -1997,12 +1998,12 @@ editorInstance.on('update', function () {
|
||||||
$('.authorship-gutter:not([data-original-title])').tooltip({
|
$('.authorship-gutter:not([data-original-title])').tooltip({
|
||||||
container: '.CodeMirror-lines',
|
container: '.CodeMirror-lines',
|
||||||
placement: 'right',
|
placement: 'right',
|
||||||
delay: { 'show': 500, 'hide': 100 }
|
delay: { show: 500, hide: 100 }
|
||||||
})
|
})
|
||||||
$('.authorship-inline:not([data-original-title])').tooltip({
|
$('.authorship-inline:not([data-original-title])').tooltip({
|
||||||
container: '.CodeMirror-lines',
|
container: '.CodeMirror-lines',
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
delay: { 'show': 500, 'hide': 100 }
|
delay: { show: 500, hide: 100 }
|
||||||
})
|
})
|
||||||
// clear tooltip which described element has been removed
|
// clear tooltip which described element has been removed
|
||||||
$('[id^="tooltip"]').each(function (index, element) {
|
$('[id^="tooltip"]').each(function (index, element) {
|
||||||
|
@ -2063,7 +2064,7 @@ var cmClient = null
|
||||||
var synchronized_ = null
|
var synchronized_ = null
|
||||||
|
|
||||||
function havePendingOperation () {
|
function havePendingOperation () {
|
||||||
return !!((cmClient && cmClient.state && cmClient.state.hasOwnProperty('outstanding')))
|
return !!((cmClient && cmClient.state && Object.hasOwnProperty.call(cmClient.state, 'outstanding')))
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.on('doc', function (obj) {
|
socket.on('doc', function (obj) {
|
||||||
|
@ -2223,7 +2224,7 @@ function updateOnlineStatus () {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let id = items[i].values().id
|
const id = items[i].values().id
|
||||||
if (found) {
|
if (found) {
|
||||||
onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
|
onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
|
||||||
shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
|
shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
|
||||||
|
@ -2417,19 +2418,19 @@ function buildCursor (user) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if ($('div[data-clientid="' + user.id + '"]').length <= 0) {
|
if ($('div[data-clientid="' + user.id + '"]').length <= 0) {
|
||||||
let cursor = $('<div data-clientid="' + user.id + '" class="CodeMirror-other-cursor" style="display:none;"></div>')
|
const cursor = $('<div data-clientid="' + user.id + '" class="CodeMirror-other-cursor" style="display:none;"></div>')
|
||||||
cursor.attr('data-line', user.cursor.line)
|
cursor.attr('data-line', user.cursor.line)
|
||||||
cursor.attr('data-ch', user.cursor.ch)
|
cursor.attr('data-ch', user.cursor.ch)
|
||||||
cursor.attr('data-offset-left', 0)
|
cursor.attr('data-offset-left', 0)
|
||||||
cursor.attr('data-offset-top', 0)
|
cursor.attr('data-offset-top', 0)
|
||||||
|
|
||||||
let cursorbar = $('<div class="cursorbar"> </div>')
|
const cursorbar = $('<div class="cursorbar"> </div>')
|
||||||
cursorbar[0].style.height = defaultTextHeight + 'px'
|
cursorbar[0].style.height = defaultTextHeight + 'px'
|
||||||
cursorbar[0].style.borderLeft = '2px solid ' + user.color
|
cursorbar[0].style.borderLeft = '2px solid ' + user.color
|
||||||
|
|
||||||
var icon = '<i class="fa ' + iconClass + '"></i>'
|
var icon = '<i class="fa ' + iconClass + '"></i>'
|
||||||
|
|
||||||
let cursortag = $('<div class="cursortag">' + icon + ' <span class="name">' + user.name + '</span></div>')
|
const cursortag = $('<div class="cursortag">' + icon + ' <span class="name">' + user.name + '</span></div>')
|
||||||
// cursortag[0].style.background = color;
|
// cursortag[0].style.background = color;
|
||||||
cursortag[0].style.color = user.color
|
cursortag[0].style.color = user.color
|
||||||
|
|
||||||
|
@ -2485,15 +2486,15 @@ function buildCursor (user) {
|
||||||
|
|
||||||
checkCursorTag(coord, cursortag)
|
checkCursorTag(coord, cursortag)
|
||||||
} else {
|
} else {
|
||||||
let cursor = $('div[data-clientid="' + user.id + '"]')
|
const cursor = $('div[data-clientid="' + user.id + '"]')
|
||||||
cursor.attr('data-line', user.cursor.line)
|
cursor.attr('data-line', user.cursor.line)
|
||||||
cursor.attr('data-ch', user.cursor.ch)
|
cursor.attr('data-ch', user.cursor.ch)
|
||||||
|
|
||||||
let cursorbar = cursor.find('.cursorbar')
|
const cursorbar = cursor.find('.cursorbar')
|
||||||
cursorbar[0].style.height = defaultTextHeight + 'px'
|
cursorbar[0].style.height = defaultTextHeight + 'px'
|
||||||
cursorbar[0].style.borderLeft = '2px solid ' + user.color
|
cursorbar[0].style.borderLeft = '2px solid ' + user.color
|
||||||
|
|
||||||
let cursortag = cursor.find('.cursortag')
|
const cursortag = cursor.find('.cursortag')
|
||||||
cursortag.find('i').removeClass().addClass('fa').addClass(iconClass)
|
cursortag.find('i').removeClass().addClass('fa').addClass(iconClass)
|
||||||
cursortag.find('.name').text(user.name)
|
cursortag.find('.name').text(user.name)
|
||||||
|
|
||||||
|
@ -2502,8 +2503,8 @@ function buildCursor (user) {
|
||||||
cursor[0].style.top = coord.top + 'px'
|
cursor[0].style.top = coord.top + 'px'
|
||||||
} else {
|
} else {
|
||||||
cursor.animate({
|
cursor.animate({
|
||||||
'left': coord.left,
|
left: coord.left,
|
||||||
'top': coord.top
|
top: coord.top
|
||||||
}, {
|
}, {
|
||||||
duration: cursorAnimatePeriod,
|
duration: cursorAnimatePeriod,
|
||||||
queue: false
|
queue: false
|
||||||
|
@ -2712,8 +2713,8 @@ function restoreInfo () {
|
||||||
$(window).scrollLeft(lastInfo.edit.scroll.left)
|
$(window).scrollLeft(lastInfo.edit.scroll.left)
|
||||||
$(window).scrollTop(lastInfo.edit.scroll.top)
|
$(window).scrollTop(lastInfo.edit.scroll.top)
|
||||||
} else {
|
} else {
|
||||||
let left = lastInfo.edit.scroll.left
|
const left = lastInfo.edit.scroll.left
|
||||||
let top = lastInfo.edit.scroll.top
|
const top = lastInfo.edit.scroll.top
|
||||||
editor.scrollIntoView()
|
editor.scrollIntoView()
|
||||||
editor.scrollTo(left, top)
|
editor.scrollTo(left, top)
|
||||||
}
|
}
|
||||||
|
@ -2723,8 +2724,8 @@ function restoreInfo () {
|
||||||
$(window).scrollTop(lastInfo.view.scroll.top)
|
$(window).scrollTop(lastInfo.view.scroll.top)
|
||||||
break
|
break
|
||||||
case modeType.both:
|
case modeType.both:
|
||||||
let left = lastInfo.edit.scroll.left
|
const left = lastInfo.edit.scroll.left
|
||||||
let top = lastInfo.edit.scroll.top
|
const top = lastInfo.edit.scroll.top
|
||||||
editor.scrollIntoView()
|
editor.scrollIntoView()
|
||||||
editor.scrollTo(left, top)
|
editor.scrollTo(left, top)
|
||||||
ui.area.view.scrollLeft(lastInfo.view.scroll.left)
|
ui.area.view.scrollLeft(lastInfo.view.scroll.left)
|
||||||
|
@ -2846,8 +2847,8 @@ function partialUpdate (src, tar, des) {
|
||||||
for (let i = 0; i < tar.length; i++) {
|
for (let i = 0; i < tar.length; i++) {
|
||||||
// copyAttribute(src[i], des[i], 'data-startline');
|
// copyAttribute(src[i], des[i], 'data-startline');
|
||||||
// copyAttribute(src[i], des[i], 'data-endline');
|
// copyAttribute(src[i], des[i], 'data-endline');
|
||||||
let rawSrc = cloneAndRemoveDataAttr(src[i])
|
const rawSrc = cloneAndRemoveDataAttr(src[i])
|
||||||
let rawTar = cloneAndRemoveDataAttr(tar[i])
|
const rawTar = cloneAndRemoveDataAttr(tar[i])
|
||||||
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
||||||
start = i
|
start = i
|
||||||
break
|
break
|
||||||
|
@ -2859,8 +2860,8 @@ function partialUpdate (src, tar, des) {
|
||||||
for (let i = 0; i < src.length; i++) {
|
for (let i = 0; i < src.length; i++) {
|
||||||
// copyAttribute(src[i], des[i], 'data-startline');
|
// copyAttribute(src[i], des[i], 'data-startline');
|
||||||
// copyAttribute(src[i], des[i], 'data-endline');
|
// copyAttribute(src[i], des[i], 'data-endline');
|
||||||
let rawSrc = cloneAndRemoveDataAttr(src[i])
|
const rawSrc = cloneAndRemoveDataAttr(src[i])
|
||||||
let rawTar = cloneAndRemoveDataAttr(tar[i])
|
const rawTar = cloneAndRemoveDataAttr(tar[i])
|
||||||
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
||||||
start = i
|
start = i
|
||||||
break
|
break
|
||||||
|
@ -2868,12 +2869,12 @@ function partialUpdate (src, tar, des) {
|
||||||
}
|
}
|
||||||
// tar end
|
// tar end
|
||||||
for (let i = 1; i <= tar.length + 1; i++) {
|
for (let i = 1; i <= tar.length + 1; i++) {
|
||||||
let srcLength = src.length
|
const srcLength = src.length
|
||||||
let tarLength = tar.length
|
const tarLength = tar.length
|
||||||
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
|
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
|
||||||
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
|
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
|
||||||
let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
|
const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
|
||||||
let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
|
const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
|
||||||
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
||||||
tarEnd = tar.length - i
|
tarEnd = tar.length - i
|
||||||
break
|
break
|
||||||
|
@ -2881,12 +2882,12 @@ function partialUpdate (src, tar, des) {
|
||||||
}
|
}
|
||||||
// src end
|
// src end
|
||||||
for (let i = 1; i <= src.length + 1; i++) {
|
for (let i = 1; i <= src.length + 1; i++) {
|
||||||
let srcLength = src.length
|
const srcLength = src.length
|
||||||
let tarLength = tar.length
|
const tarLength = tar.length
|
||||||
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
|
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
|
||||||
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
|
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
|
||||||
let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
|
const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
|
||||||
let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
|
const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
|
||||||
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
|
||||||
srcEnd = src.length - i
|
srcEnd = src.length - i
|
||||||
break
|
break
|
||||||
|
@ -3317,22 +3318,22 @@ $(editor.getInputField())
|
||||||
'textComplete:show': function (e) {
|
'textComplete:show': function (e) {
|
||||||
$(this).data('autocompleting', true)
|
$(this).data('autocompleting', true)
|
||||||
editor.setOption('extraKeys', {
|
editor.setOption('extraKeys', {
|
||||||
'Up': function () {
|
Up: function () {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
'Right': function () {
|
Right: function () {
|
||||||
editor.doc.cm.execCommand('goCharRight')
|
editor.doc.cm.execCommand('goCharRight')
|
||||||
},
|
},
|
||||||
'Down': function () {
|
Down: function () {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
'Left': function () {
|
Left: function () {
|
||||||
editor.doc.cm.execCommand('goCharLeft')
|
editor.doc.cm.execCommand('goCharLeft')
|
||||||
},
|
},
|
||||||
'Enter': function () {
|
Enter: function () {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
'Backspace': function () {
|
Backspace: function () {
|
||||||
editor.doc.cm.execCommand('delCharBefore')
|
editor.doc.cm.execCommand('delCharBefore')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import modeType from './modeType'
|
import modeType from './modeType'
|
||||||
|
|
||||||
let state = {
|
const state = {
|
||||||
syncscroll: true,
|
syncscroll: true,
|
||||||
currentMode: modeType.view,
|
currentMode: modeType.view,
|
||||||
nightMode: false
|
nightMode: false
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
let config = {
|
const config = {
|
||||||
docmaxlength: null
|
docmaxlength: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,8 @@ export default class Editor {
|
||||||
},
|
},
|
||||||
'Cmd-Left': 'goLineLeftSmart',
|
'Cmd-Left': 'goLineLeftSmart',
|
||||||
'Cmd-Right': 'goLineRight',
|
'Cmd-Right': 'goLineRight',
|
||||||
'Home': 'goLineLeftSmart',
|
Home: 'goLineLeftSmart',
|
||||||
'End': 'goLineRight',
|
End: 'goLineRight',
|
||||||
'Ctrl-C': function (cm) {
|
'Ctrl-C': function (cm) {
|
||||||
if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {
|
if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {
|
||||||
document.execCommand('copy')
|
document.execCommand('copy')
|
||||||
|
@ -513,6 +513,7 @@ export default class Editor {
|
||||||
this.jumpToAddressBarKeymapValue = null
|
this.jumpToAddressBarKeymapValue = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setOverrideBrowserKeymap () {
|
setOverrideBrowserKeymap () {
|
||||||
var overrideBrowserKeymap = $(
|
var overrideBrowserKeymap = $(
|
||||||
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
|
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
|
||||||
|
|
|
@ -4,17 +4,17 @@ export function wrapTextWith (editor, cm, symbol) {
|
||||||
if (!cm.getSelection()) {
|
if (!cm.getSelection()) {
|
||||||
return CodeMirror.Pass
|
return CodeMirror.Pass
|
||||||
} else {
|
} else {
|
||||||
let ranges = cm.listSelections()
|
const ranges = cm.listSelections()
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
let range = ranges[i]
|
const range = ranges[i]
|
||||||
if (!range.empty()) {
|
if (!range.empty()) {
|
||||||
const from = range.from()
|
const from = range.from()
|
||||||
const to = range.to()
|
const to = range.to()
|
||||||
|
|
||||||
if (symbol !== 'Backspace') {
|
if (symbol !== 'Backspace') {
|
||||||
let selection = cm.getRange(from, to)
|
const selection = cm.getRange(from, to)
|
||||||
let anchorIndex = editor.indexFromPos(ranges[i].anchor)
|
const anchorIndex = editor.indexFromPos(ranges[i].anchor)
|
||||||
let headIndex = editor.indexFromPos(ranges[i].head)
|
const headIndex = editor.indexFromPos(ranges[i].head)
|
||||||
cm.replaceRange(symbol + selection + symbol, from, to, '+input')
|
cm.replaceRange(symbol + selection + symbol, from, to, '+input')
|
||||||
if (anchorIndex > headIndex) {
|
if (anchorIndex > headIndex) {
|
||||||
ranges[i].anchor.ch += symbol.length
|
ranges[i].anchor.ch += symbol.length
|
||||||
|
@ -25,18 +25,18 @@ export function wrapTextWith (editor, cm, symbol) {
|
||||||
}
|
}
|
||||||
cm.setSelections(ranges)
|
cm.setSelections(ranges)
|
||||||
} else {
|
} else {
|
||||||
let preEndPos = {
|
const preEndPos = {
|
||||||
line: to.line,
|
line: to.line,
|
||||||
ch: to.ch + symbol.length
|
ch: to.ch + symbol.length
|
||||||
}
|
}
|
||||||
let preText = cm.getRange(to, preEndPos)
|
const preText = cm.getRange(to, preEndPos)
|
||||||
let preIndex = wrapSymbols.indexOf(preText)
|
const preIndex = wrapSymbols.indexOf(preText)
|
||||||
let postEndPos = {
|
const postEndPos = {
|
||||||
line: from.line,
|
line: from.line,
|
||||||
ch: from.ch - symbol.length
|
ch: from.ch - symbol.length
|
||||||
}
|
}
|
||||||
let postText = cm.getRange(postEndPos, from)
|
const postText = cm.getRange(postEndPos, from)
|
||||||
let postIndex = wrapSymbols.indexOf(postText)
|
const postIndex = wrapSymbols.indexOf(postText)
|
||||||
// check if surround symbol are list in array and matched
|
// check if surround symbol are list in array and matched
|
||||||
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
|
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
|
||||||
cm.replaceRange('', to, preEndPos, '+delete')
|
cm.replaceRange('', to, preEndPos, '+delete')
|
||||||
|
@ -49,25 +49,25 @@ export function wrapTextWith (editor, cm, symbol) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertText (cm, text, cursorEnd = 0) {
|
export function insertText (cm, text, cursorEnd = 0) {
|
||||||
let cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
cm.replaceSelection(text, cursor, cursor)
|
cm.replaceSelection(text, cursor, cursor)
|
||||||
cm.focus()
|
cm.focus()
|
||||||
cm.setCursor({ line: cursor.line, ch: cursor.ch + cursorEnd })
|
cm.setCursor({ line: cursor.line, ch: cursor.ch + cursorEnd })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertLink (cm, isImage) {
|
export function insertLink (cm, isImage) {
|
||||||
let cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
let ranges = cm.listSelections()
|
const ranges = cm.listSelections()
|
||||||
const linkEnd = '](https://)'
|
const linkEnd = '](https://)'
|
||||||
const symbol = (isImage) ? '![' : '['
|
const symbol = (isImage) ? '![' : '['
|
||||||
|
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
let range = ranges[i]
|
const range = ranges[i]
|
||||||
if (!range.empty()) {
|
if (!range.empty()) {
|
||||||
const from = range.from()
|
const from = range.from()
|
||||||
const to = range.to()
|
const to = range.to()
|
||||||
let anchorIndex = editor.indexFromPos(ranges[i].anchor)
|
const anchorIndex = editor.indexFromPos(ranges[i].anchor)
|
||||||
let headIndex = editor.indexFromPos(ranges[i].head)
|
const headIndex = editor.indexFromPos(ranges[i].head)
|
||||||
let selection = cm.getRange(from, to)
|
let selection = cm.getRange(from, to)
|
||||||
selection = symbol + selection + linkEnd
|
selection = symbol + selection + linkEnd
|
||||||
cm.replaceRange(selection, from, to)
|
cm.replaceRange(selection, from, to)
|
||||||
|
@ -88,9 +88,9 @@ export function insertLink (cm, isImage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertHeader (cm) {
|
export function insertHeader (cm) {
|
||||||
let cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
let startOfLine = { line: cursor.line, ch: 0 }
|
const startOfLine = { line: cursor.line, ch: 0 }
|
||||||
let startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
|
const startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
|
||||||
// See if it is already a header
|
// See if it is already a header
|
||||||
if (startOfLineText === '#') {
|
if (startOfLineText === '#') {
|
||||||
cm.replaceRange('#', startOfLine, startOfLine)
|
cm.replaceRange('#', startOfLine, startOfLine)
|
||||||
|
@ -101,11 +101,11 @@ export function insertHeader (cm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertOnStartOfLines (cm, symbol) {
|
export function insertOnStartOfLines (cm, symbol) {
|
||||||
let cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
let ranges = cm.listSelections()
|
const ranges = cm.listSelections()
|
||||||
|
|
||||||
for (let i = 0; i < ranges.length; i++) {
|
for (let i = 0; i < ranges.length; i++) {
|
||||||
let range = ranges[i]
|
const range = ranges[i]
|
||||||
if (!range.empty()) {
|
if (!range.empty()) {
|
||||||
const from = range.from()
|
const from = range.from()
|
||||||
const to = range.to()
|
const to = range.to()
|
||||||
|
|
|
@ -174,12 +174,12 @@ const buildMap = _.throttle(buildMapInner, buildMapThrottle)
|
||||||
// Optimizations are required only for big texts.
|
// Optimizations are required only for big texts.
|
||||||
function buildMapInner (callback) {
|
function buildMapInner (callback) {
|
||||||
if (!viewArea || !markdownArea) return
|
if (!viewArea || !markdownArea) return
|
||||||
let i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, acc, _scrollMap
|
let i, pos, a, b, acc
|
||||||
|
|
||||||
offset = viewArea.scrollTop() - viewArea.offset().top
|
const offset = viewArea.scrollTop() - viewArea.offset().top
|
||||||
_scrollMap = []
|
const _scrollMap = []
|
||||||
nonEmptyList = []
|
const nonEmptyList = []
|
||||||
_lineHeightMap = []
|
const _lineHeightMap = []
|
||||||
viewTop = 0
|
viewTop = 0
|
||||||
viewBottom = viewArea[0].scrollHeight - viewArea.height()
|
viewBottom = viewArea[0].scrollHeight - viewArea.height()
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ function buildMapInner (callback) {
|
||||||
acc += Math.round(h / lineHeight)
|
acc += Math.round(h / lineHeight)
|
||||||
}
|
}
|
||||||
_lineHeightMap.push(acc)
|
_lineHeightMap.push(acc)
|
||||||
linesCount = acc
|
const linesCount = acc
|
||||||
|
|
||||||
for (i = 0; i < linesCount; i++) {
|
for (i = 0; i < linesCount; i++) {
|
||||||
_scrollMap.push(-1)
|
_scrollMap.push(-1)
|
||||||
|
@ -350,11 +350,11 @@ export function syncScrollToView (event, preventAnimate) {
|
||||||
}
|
}
|
||||||
if (viewScrolling) return
|
if (viewScrolling) return
|
||||||
|
|
||||||
let lineNo, posTo
|
let posTo
|
||||||
let topDiffPercent, posToNextDiff
|
let topDiffPercent, posToNextDiff
|
||||||
const scrollInfo = editor.getScrollInfo()
|
const scrollInfo = editor.getScrollInfo()
|
||||||
const textHeight = editor.defaultTextHeight()
|
const textHeight = editor.defaultTextHeight()
|
||||||
lineNo = Math.floor(scrollInfo.top / textHeight)
|
const lineNo = Math.floor(scrollInfo.top / textHeight)
|
||||||
// if reach the last line, will start lerp to the bottom
|
// if reach the last line, will start lerp to the bottom
|
||||||
const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
|
const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
|
||||||
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
|
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ function extend () {
|
||||||
|
|
||||||
for (const source of arguments) {
|
for (const source of arguments) {
|
||||||
for (const key in source) {
|
for (const key in source) {
|
||||||
if (source.hasOwnProperty(key)) {
|
if (Object.hasOwnProperty.call(source, key)) {
|
||||||
target[key] = source[key]
|
target[key] = source[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,17 +74,17 @@ const defaultOptions = {
|
||||||
const meta = JSON.parse($('#meta').text())
|
const meta = JSON.parse($('#meta').text())
|
||||||
var options = meta.slideOptions || {}
|
var options = meta.slideOptions || {}
|
||||||
|
|
||||||
if (options.hasOwnProperty('spotlight')) {
|
if (Object.hasOwnProperty.call(options, 'spotlight')) {
|
||||||
defaultOptions.dependencies.push({
|
defaultOptions.dependencies.push({
|
||||||
src: `${serverurl}/build/reveal.js/plugin/spotlight/spotlight.js`
|
src: `${serverurl}/build/reveal.js/plugin/spotlight/spotlight.js`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.hasOwnProperty('allottedTime') || options.hasOwnProperty('allottedMinutes')) {
|
if (Object.hasOwnProperty.call(options, 'allottedTime') || Object.hasOwnProperty.call(options, 'allottedMinutes')) {
|
||||||
defaultOptions.dependencies.push({
|
defaultOptions.dependencies.push({
|
||||||
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
|
src: `${serverurl}/build/reveal.js/plugin/elapsed-time-bar/elapsed-time-bar.js`
|
||||||
})
|
})
|
||||||
if (options.hasOwnProperty('allottedMinutes')) {
|
if (Object.hasOwnProperty.call(options, 'allottedMinutes')) {
|
||||||
options.allottedTime = options.allottedMinutes * 60 * 1000
|
options.allottedTime = options.allottedMinutes * 60 * 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,14 +123,14 @@ window.viewAjaxCallback = () => {
|
||||||
function renderSlide (event) {
|
function renderSlide (event) {
|
||||||
if (window.location.search.match(/print-pdf/gi)) {
|
if (window.location.search.match(/print-pdf/gi)) {
|
||||||
const slides = $('.slides')
|
const slides = $('.slides')
|
||||||
let title = document.title
|
const title = document.title
|
||||||
finishView(slides)
|
finishView(slides)
|
||||||
document.title = title
|
document.title = title
|
||||||
Reveal.layout()
|
Reveal.layout()
|
||||||
} else {
|
} else {
|
||||||
const markdown = $(event.currentSlide)
|
const markdown = $(event.currentSlide)
|
||||||
if (!markdown.attr('data-rendered')) {
|
if (!markdown.attr('data-rendered')) {
|
||||||
let title = document.title
|
const title = document.title
|
||||||
finishView(markdown)
|
finishView(markdown)
|
||||||
markdown.attr('data-rendered', 'true')
|
markdown.attr('data-rendered', 'true')
|
||||||
document.title = title
|
document.title = title
|
||||||
|
|
|
@ -1,28 +1,24 @@
|
||||||
import base64url from 'base64url'
|
import base64url from 'base64url'
|
||||||
|
|
||||||
let uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||||
|
|
||||||
export function checkNoteIdValid (id) {
|
export function checkNoteIdValid (id) {
|
||||||
let result = id.match(uuidRegex)
|
const result = id.match(uuidRegex)
|
||||||
if (result && result.length === 1) {
|
return !!(result && result.length === 1)
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeNoteId (id) {
|
export function encodeNoteId (id) {
|
||||||
// remove dashes in UUID and encode in url-safe base64
|
// remove dashes in UUID and encode in url-safe base64
|
||||||
let str = id.replace(/-/g, '')
|
const str = id.replace(/-/g, '')
|
||||||
let hexStr = Buffer.from(str, 'hex')
|
const hexStr = Buffer.from(str, 'hex')
|
||||||
return base64url.encode(hexStr)
|
return base64url.encode(hexStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeNoteId (encodedId) {
|
export function decodeNoteId (encodedId) {
|
||||||
// decode from url-safe base64
|
// decode from url-safe base64
|
||||||
let id = base64url.toBuffer(encodedId).toString('hex')
|
const id = base64url.toBuffer(encodedId).toString('hex')
|
||||||
// add dashes between the UUID string parts
|
// add dashes between the UUID string parts
|
||||||
let idParts = []
|
const idParts = []
|
||||||
idParts.push(id.substr(0, 8))
|
idParts.push(id.substr(0, 8))
|
||||||
idParts.push(id.substr(8, 4))
|
idParts.push(id.substr(8, 4))
|
||||||
idParts.push(id.substr(12, 4))
|
idParts.push(id.substr(12, 4))
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<% if(useCDN) { %>
|
<% if(useCDN) { %>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.4.0/velocity.min.js" integrity="sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.2/velocity.min.js" integrity="sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js" integrity="sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/js/bootstrap.min.js" integrity="sha256-kJrlY+s09+QoWjpkOrXXwhxeaoDz9FW5SaxF8I0DibQ=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/list.pagination.js/0.1.1/list.pagination.min.js" integrity="sha256-WwTza96H3BgcQTfEfxX7MFaFc/dZA0QrPRKDRLdFHJo=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/list.pagination.js/0.1.1/list.pagination.min.js" integrity="sha256-WwTza96H3BgcQTfEfxX7MFaFc/dZA0QrPRKDRLdFHJo=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.min.js" integrity="sha256-HzzZFiY4t0PIv02Tm8/R3CVvLpcjHhO1z/YAUCp4oQ4=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.min.js" integrity="sha256-HzzZFiY4t0PIv02Tm8/R3CVvLpcjHhO1z/YAUCp4oQ4=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-url/2.3.0/url.min.js" integrity="sha256-HOZJz4x+1mn1Si84WT5XKXPtOlTytmZLnMb6n1v4+5Q=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-url/2.3.0/url.min.js" integrity="sha256-HOZJz4x+1mn1Si84WT5XKXPtOlTytmZLnMb6n1v4+5Q=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.8/validator.min.js" integrity="sha256-LHeY7YoYJ0SSXbCx7sR14Pqna+52moaH3bhv0Mjzd/M=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.8/validator.min.js" integrity="sha256-LHeY7YoYJ0SSXbCx7sR14Pqna+52moaH3bhv0Mjzd/M=" crossorigin="anonymous" defer></script>
|
||||||
<%- include ../build/cover-scripts %>
|
<%- include ../build/cover-scripts %>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" integrity="sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.4.0/css/bootstrap.min.css" integrity="sha256-H0KfTigpUV+0/5tn2HXC0CPwhhDhWgSawJdnFd0CGCo=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css" integrity="sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css" integrity="sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-social/4.9.0/bootstrap-social.min.css" integrity="sha256-02JtFTurpwBjQJ6q13iJe82/NF0RbZlJroDegK5g87Y=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-social/4.9.0/bootstrap-social.min.css" integrity="sha256-02JtFTurpwBjQJ6q13iJe82/NF0RbZlJroDegK5g87Y=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2.min.css" integrity="sha256-ijlUKKj3hJCiiT2HWo1kqkI79NTEYpzOsw5Rs3k42dI=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.min.css" integrity="sha256-ijlUKKj3hJCiiT2HWo1kqkI79NTEYpzOsw5Rs3k42dI=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.4/select2-bootstrap.min.css" integrity="sha256-NAWFcNIZdH+TS1xpWujF/EB/Y8gwBbEOCoaK/eqaer8=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2-bootstrap.min.css" integrity="sha256-NAWFcNIZdH+TS1xpWujF/EB/Y8gwBbEOCoaK/eqaer8=" crossorigin="anonymous" />
|
||||||
<%- include ../build/cover-header %>
|
<%- include ../build/cover-header %>
|
||||||
<%- include ../shared/polyfill %>
|
<%- include ../shared/polyfill %>
|
||||||
<% } else { %>
|
<% } else { %>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<link rel="apple-touch-icon" href="<%- serverURL %>/apple-touch-icon.png">
|
<link rel="apple-touch-icon" href="<%- serverURL %>/apple-touch-icon.png">
|
||||||
|
|
||||||
<% if(useCDN) { %>
|
<% if(useCDN) { %>
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.3/css/fork-awesome.min.css" integrity="sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fork-awesome/1.1.7/css/fork-awesome.min.css" integrity="sha256-ZhApazu+kejqTYhMF+1DzNKjIzP7KXu6AzyXcC1gMus=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/css/reveal.min.css" integrity="sha256-9+Wg2bcNeiOMGXOUNqBdceY2lAH/eCiTDcdzHhHIl48=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/css/reveal.min.css" integrity="sha256-9+Wg2bcNeiOMGXOUNqBdceY2lAH/eCiTDcdzHhHIl48=" crossorigin="anonymous" />
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
|
||||||
|
@ -90,20 +90,20 @@
|
||||||
<% if(useCDN) { %>
|
<% if(useCDN) { %>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/lib/js/head.min.js" integrity="sha256-CTcwyen1cxIrm4hlqdxe0y7Hq6B0rpxAKLiXMD3dJv0=" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/lib/js/head.min.js" integrity="sha256-CTcwyen1cxIrm4hlqdxe0y7Hq6B0rpxAKLiXMD3dJv0=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/js/reveal.min.js" integrity="sha256-Xr6ZH+/kc7hDVReZLO5khBknteLqu5oen/xnSraXrVk=" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.7.0/js/reveal.min.js" integrity="sha256-Xr6ZH+/kc7hDVReZLO5khBknteLqu5oen/xnSraXrVk=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.4.0/velocity.min.js" integrity="sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.2/velocity.min.js" integrity="sha256-bhm0lgEt6ITaZCDzZpkr/VXVrLa5RP4u9v2AYsbzSUk=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js" integrity="sha256-jnOjDTXIPqall8M0MyTSt98JetJuZ7Yu+1Jm7hLTF7U=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js" integrity="sha256-jnOjDTXIPqall8M0MyTSt98JetJuZ7Yu+1Jm7hLTF7U=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.7.0/js-yaml.min.js" integrity="sha256-8PanqYAVOGlOct+i65R+HqibK3KPsXINnrSfxN+Y/J0=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.13.1/js-yaml.min.js" integrity="sha256-8PanqYAVOGlOct+i65R+HqibK3KPsXINnrSfxN+Y/J0=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js" integrity="sha256-yYfngbEKv4RENfGDvNUqJTqGFcKf31NJEe9OTnnMH3Y=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js" integrity="sha256-yYfngbEKv4RENfGDvNUqJTqGFcKf31NJEe9OTnnMH3Y=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js" integrity="sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/TeX-AMS-MML_HTMLorMML.js" integrity="sha256-immzXfCGLhnx3Zfi9F/dUcqxEM8K3o3oTFy9Bh6HCwg=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js" integrity="sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/config/Safe.js" integrity="sha256-0ygBUDksNDXZS4vm5HMNH1a33KUu6QT1cdNTN+ZLF+4=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js" integrity="sha256-vvT7Ok9u6GbfnBPXnbM6FVDEO8E1kTdgHOFZOAXrktA=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.2.3/mermaid.min.js" integrity="sha256-4s3fF5e1iWRLtiV7mRev7n17oALqqDHbWrNqF3/r7jU=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.2.3/mermaid.min.js" integrity="sha256-4s3fF5e1iWRLtiV7mRev7n17oALqqDHbWrNqF3/r7jU=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/js/emojify.min.js" integrity="sha256-VAB5tAlKBvgaxw8oJ1crWMVbdmBVl4mP/2M8MNRl+4E=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/js/emojify.min.js" integrity="sha256-VAB5tAlKBvgaxw8oJ1crWMVbdmBVl4mP/2M8MNRl+4E=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.6/handlebars.min.js" integrity="sha256-1O3BtOwnPyyRzOszK6P+gqaRoXHV6JXj8HkjZmPYhCI=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js" integrity="sha256-1O3BtOwnPyyRzOszK6P+gqaRoXHV6JXj8HkjZmPYhCI=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.9/highlight.min.js" integrity="sha256-/BfiIkHlHoVihZdc6TFuj7MmJ0TWcWsMXkeDFwhi0zw=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/viz.js/1.7.0/viz.js" integrity="sha256-8t+rndrF+TU4JtelmOH1lDHTMe2ovhO2UbzDArp5lY8=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/viz.js/2.1.2/viz.js" integrity="sha256-8t+rndrF+TU4JtelmOH1lDHTMe2ovhO2UbzDArp5lY8=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/abcjs/3.1.1/abcjs_basic-min.js" integrity="sha256-Sq1r2XXWXQoShQKsS0Wrf5r7fRkErd9Fat9vHYeU68s=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/abcjs/3.1.1/abcjs_basic-min.js" integrity="sha256-Sq1r2XXWXQoShQKsS0Wrf5r7fRkErd9Fat9vHYeU68s=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega/5.4.0/vega.min.js" integrity="sha256-PrkRj4B3I5V9yHBLdO3jyyqNUwSKS1CXXIh3VrnFPEU=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega/5.4.0/vega.min.js" integrity="sha256-PrkRj4B3I5V9yHBLdO3jyyqNUwSKS1CXXIh3VrnFPEU=" crossorigin="anonymous" defer></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-lite/3.4.0/vega-lite.min.js" integrity="sha256-ro+FWr16NboXJ5rSwInNli1P16ObUXnWUJMgKc8KnHI=" crossorigin="anonymous" defer></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/vega-lite/3.4.0/vega-lite.min.js" integrity="sha256-ro+FWr16NboXJ5rSwInNli1P16ObUXnWUJMgKc8KnHI=" crossorigin="anonymous" defer></script>
|
||||||
|
|
10
test/csp.js
10
test/csp.js
|
@ -43,7 +43,7 @@ describe('Content security policies', function () {
|
||||||
|
|
||||||
// beginnging Tests
|
// beginnging Tests
|
||||||
it('Disable CDN', function () {
|
it('Disable CDN', function () {
|
||||||
let testconfig = defaultConfig
|
const testconfig = defaultConfig
|
||||||
testconfig.useCDN = false
|
testconfig.useCDN = false
|
||||||
mock('../lib/config', testconfig)
|
mock('../lib/config', testconfig)
|
||||||
csp = mock.reRequire('../lib/csp')
|
csp = mock.reRequire('../lib/csp')
|
||||||
|
@ -57,7 +57,7 @@ describe('Content security policies', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Disable Google Analytics', function () {
|
it('Disable Google Analytics', function () {
|
||||||
let testconfig = defaultConfig
|
const testconfig = defaultConfig
|
||||||
testconfig.csp.addGoogleAnalytics = false
|
testconfig.csp.addGoogleAnalytics = false
|
||||||
mock('../lib/config', testconfig)
|
mock('../lib/config', testconfig)
|
||||||
csp = mock.reRequire('../lib/csp')
|
csp = mock.reRequire('../lib/csp')
|
||||||
|
@ -66,7 +66,7 @@ describe('Content security policies', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Disable Disqus', function () {
|
it('Disable Disqus', function () {
|
||||||
let testconfig = defaultConfig
|
const testconfig = defaultConfig
|
||||||
testconfig.csp.addDisqus = false
|
testconfig.csp.addDisqus = false
|
||||||
mock('../lib/config', testconfig)
|
mock('../lib/config', testconfig)
|
||||||
csp = mock.reRequire('../lib/csp')
|
csp = mock.reRequire('../lib/csp')
|
||||||
|
@ -79,7 +79,7 @@ describe('Content security policies', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Set ReportURI', function () {
|
it('Set ReportURI', function () {
|
||||||
let testconfig = defaultConfig
|
const testconfig = defaultConfig
|
||||||
testconfig.csp.reportURI = 'https://example.com/reportURI'
|
testconfig.csp.reportURI = 'https://example.com/reportURI'
|
||||||
mock('../lib/config', testconfig)
|
mock('../lib/config', testconfig)
|
||||||
csp = mock.reRequire('../lib/csp')
|
csp = mock.reRequire('../lib/csp')
|
||||||
|
@ -88,7 +88,7 @@ describe('Content security policies', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Set own directives', function () {
|
it('Set own directives', function () {
|
||||||
let testconfig = defaultConfig
|
const testconfig = defaultConfig
|
||||||
mock('../lib/config', defaultConfig)
|
mock('../lib/config', defaultConfig)
|
||||||
csp = mock.reRequire('../lib/csp')
|
csp = mock.reRequire('../lib/csp')
|
||||||
const unextendedCSP = csp.computeDirectives()
|
const unextendedCSP = csp.computeDirectives()
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe('generateAvatarURL() gravatar enabled', function () {
|
||||||
let avatars
|
let avatars
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
// Reset config to make sure we don't influence other tests
|
// Reset config to make sure we don't influence other tests
|
||||||
let testconfig = {
|
const testconfig = {
|
||||||
allowGravatar: true,
|
allowGravatar: true,
|
||||||
serverURL: 'http://localhost:3000',
|
serverURL: 'http://localhost:3000',
|
||||||
port: 3000
|
port: 3000
|
||||||
|
@ -32,7 +32,7 @@ describe('generateAvatarURL() gravatar disabled', function () {
|
||||||
let avatars
|
let avatars
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
// Reset config to make sure we don't influence other tests
|
// Reset config to make sure we don't influence other tests
|
||||||
let testconfig = {
|
const testconfig = {
|
||||||
allowGravatar: false,
|
allowGravatar: false,
|
||||||
serverURL: 'http://localhost:3000',
|
serverURL: 'http://localhost:3000',
|
||||||
port: 3000
|
port: 3000
|
||||||
|
|
|
@ -49,8 +49,8 @@ describe('cleanDanglingUser', function () {
|
||||||
connected: {}
|
connected: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let user1Socket = makeMockSocket()
|
const user1Socket = makeMockSocket()
|
||||||
let user2Socket = makeMockSocket()
|
const user2Socket = makeMockSocket()
|
||||||
|
|
||||||
user1Socket.rooms.push('room1')
|
user1Socket.rooms.push('room1')
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ describe('realtime#connection', function () {
|
||||||
const emitRefreshStub = sinon.stub(realtime, 'emitRefresh')
|
const emitRefreshStub = sinon.stub(realtime, 'emitRefresh')
|
||||||
const failConnectionSpy = sinon.spy(realtime, 'failConnection')
|
const failConnectionSpy = sinon.spy(realtime, 'failConnection')
|
||||||
|
|
||||||
let note = {
|
const note = {
|
||||||
id: noteId,
|
id: noteId,
|
||||||
authors: [
|
authors: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,7 +57,7 @@ describe('realtime#update note is dirty timer', function () {
|
||||||
socks: []
|
socks: []
|
||||||
}
|
}
|
||||||
|
|
||||||
let note2 = {
|
const note2 = {
|
||||||
server: {
|
server: {
|
||||||
isDirty: true
|
isDirty: true
|
||||||
},
|
},
|
||||||
|
@ -79,7 +79,7 @@ describe('realtime#update note is dirty timer', function () {
|
||||||
callback(null, note)
|
callback(null, note)
|
||||||
})
|
})
|
||||||
|
|
||||||
let note = {
|
const note = {
|
||||||
server: {
|
server: {
|
||||||
isDirty: true
|
isDirty: true
|
||||||
},
|
},
|
||||||
|
@ -109,7 +109,7 @@ describe('realtime#update note is dirty timer', function () {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let note = {
|
const note = {
|
||||||
server: {
|
server: {
|
||||||
isDirty: true
|
isDirty: true
|
||||||
},
|
},
|
||||||
|
|
|
@ -35,7 +35,7 @@ describe('realtime#extractNoteIdFromSocket', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('return false if query not set and referer not set', function () {
|
it('return false if query not set and referer not set', function () {
|
||||||
let noteId = realtime.extractNoteIdFromSocket(makeMockSocket({
|
const noteId = realtime.extractNoteIdFromSocket(makeMockSocket({
|
||||||
otherHeader: 1
|
otherHeader: 1
|
||||||
}, {
|
}, {
|
||||||
otherQuery: 1
|
otherQuery: 1
|
||||||
|
|
|
@ -274,7 +274,7 @@ describe('realtime#socket event', function () {
|
||||||
onlineUsersFunc()
|
onlineUsersFunc()
|
||||||
assert(clientSocket.emit.called)
|
assert(clientSocket.emit.called)
|
||||||
assert(clientSocket.emit.lastCall.args[0] === 'online users')
|
assert(clientSocket.emit.lastCall.args[0] === 'online users')
|
||||||
let returnUserList = clientSocket.emit.lastCall.args[1].users
|
const returnUserList = clientSocket.emit.lastCall.args[1].users
|
||||||
assert(returnUserList.length === 2)
|
assert(returnUserList.length === 2)
|
||||||
assert(returnUserList[0].id === 10)
|
assert(returnUserList[0].id === 10)
|
||||||
assert(returnUserList[1].id === 20)
|
assert(returnUserList[1].id === 20)
|
||||||
|
@ -444,8 +444,8 @@ describe('realtime#socket event', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('permission', function () {
|
describe('permission', function () {
|
||||||
let ownerId = 'user1_id'
|
const ownerId = 'user1_id'
|
||||||
let otherSignInUserId = 'user2_id'
|
const otherSignInUserId = 'user2_id'
|
||||||
let otherClient
|
let otherClient
|
||||||
let checkViewPermissionSpy
|
let checkViewPermissionSpy
|
||||||
let permissionFunc
|
let permissionFunc
|
||||||
|
|
|
@ -53,7 +53,7 @@ describe('realtime#updateNote', function () {
|
||||||
const callback = sinon.stub()
|
const callback = sinon.stub()
|
||||||
const note = {
|
const note = {
|
||||||
tempUsers: {
|
tempUsers: {
|
||||||
'user1': Date.now()
|
user1: Date.now()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
realtime.updateNote(note, callback)
|
realtime.updateNote(note, callback)
|
||||||
|
|
|
@ -238,7 +238,6 @@ module.exports = {
|
||||||
],
|
],
|
||||||
'index-pack': [
|
'index-pack': [
|
||||||
'babel-polyfill',
|
'babel-polyfill',
|
||||||
'expose-loader?Spinner!spin.js',
|
|
||||||
'script-loader!jquery-ui-resizable',
|
'script-loader!jquery-ui-resizable',
|
||||||
'bootstrap-validator',
|
'bootstrap-validator',
|
||||||
'expose-loader?jsyaml!js-yaml',
|
'expose-loader?jsyaml!js-yaml',
|
||||||
|
|
Loading…
Reference in New Issue