summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Molares2021-02-15 09:42:51 +0100
committerPhilip Molares2021-02-15 12:15:14 +0100
commit136d895d155f28c2e75b3af206549acaa2a354ed (patch)
treead80595f5dd94a7ac63bc1481943ae7b356ddb17
parentb0a45bdf9c531d93a2462c09d58b2e9e703a0a66 (diff)
Linter: Fix all lint errors
Signed-off-by: Philip Molares <philip.molares@udo.edu>
-rw-r--r--app.js76
-rw-r--r--lib/config/index.js16
-rw-r--r--lib/csp.js24
-rw-r--r--lib/history.js52
-rw-r--r--lib/letter-avatars.js4
-rw-r--r--lib/models/author.js4
-rw-r--r--lib/models/index.js26
-rw-r--r--lib/models/note.js166
-rw-r--r--lib/models/revision.js48
-rw-r--r--lib/models/temp.js4
-rw-r--r--lib/models/user.js4
-rw-r--r--lib/realtime.js245
-rw-r--r--lib/response.js56
-rw-r--r--lib/utils.js2
-rw-r--r--lib/web/auth/dropbox/index.js2
-rw-r--r--lib/web/auth/email/index.js2
-rw-r--r--lib/web/auth/facebook/index.js2
-rw-r--r--lib/web/auth/github/index.js2
-rw-r--r--lib/web/auth/gitlab/index.js2
-rw-r--r--lib/web/auth/google/index.js4
-rw-r--r--lib/web/auth/ldap/index.js12
-rw-r--r--lib/web/auth/mattermost/index.js4
-rw-r--r--lib/web/auth/oauth2/index.js10
-rw-r--r--lib/web/auth/openid/index.js6
-rw-r--r--lib/web/auth/saml/index.js28
-rw-r--r--lib/web/auth/twitter/index.js2
-rw-r--r--lib/web/auth/utils.js4
-rw-r--r--lib/web/imageRouter/azure.js2
-rw-r--r--lib/web/imageRouter/index.js40
-rw-r--r--lib/web/imageRouter/minio.js8
-rw-r--r--lib/web/imageRouter/s3.js2
-rw-r--r--lib/web/statusRouter.js10
-rw-r--r--lib/web/userRouter.js10
-rw-r--r--lib/workers/dmpWorker.js86
-rw-r--r--public/.eslintrc.js48
-rw-r--r--public/js/cover.js10
-rw-r--r--public/js/extra.js74
-rw-r--r--public/js/history.js6
-rw-r--r--public/js/index.js2171
-rw-r--r--public/js/lib/appState.js2
-rw-r--r--public/js/lib/common/login.js2
-rw-r--r--public/js/lib/editor/config.js2
-rw-r--r--public/js/lib/editor/index.js123
-rw-r--r--public/js/lib/editor/utils.js46
-rw-r--r--public/js/lib/syncscroll.js22
-rw-r--r--public/js/render.js34
-rw-r--r--public/js/reveal-markdown.js102
-rw-r--r--public/js/slide.js141
-rw-r--r--public/js/utils.js12
-rw-r--r--test/csp.js12
-rw-r--r--test/letter-avatars.js4
51 files changed, 2241 insertions, 1535 deletions
diff --git a/app.js b/app.js
index eb2a8193..ae332d98 100644
--- a/app.js
+++ b/app.js
@@ -1,44 +1,44 @@
'use strict'
// app
// external modules
-var express = require('express')
-
-var ejs = require('ejs')
-var passport = require('passport')
-var methodOverride = require('method-override')
-var cookieParser = require('cookie-parser')
-var compression = require('compression')
-var session = require('express-session')
-var SequelizeStore = require('connect-session-sequelize')(session.Store)
-var fs = require('fs')
-var path = require('path')
-
-var morgan = require('morgan')
-var passportSocketIo = require('passport.socketio')
-var helmet = require('helmet')
-var i18n = require('i18n')
-var flash = require('connect-flash')
+const express = require('express')
+
+const ejs = require('ejs')
+const passport = require('passport')
+const methodOverride = require('method-override')
+const cookieParser = require('cookie-parser')
+const compression = require('compression')
+const session = require('express-session')
+const SequelizeStore = require('connect-session-sequelize')(session.Store)
+const fs = require('fs')
+const path = require('path')
+
+const morgan = require('morgan')
+const passportSocketIo = require('passport.socketio')
+const helmet = require('helmet')
+const i18n = require('i18n')
+const flash = require('connect-flash')
// core
-var config = require('./lib/config')
-var logger = require('./lib/logger')
-var errors = require('./lib/errors')
-var models = require('./lib/models')
-var csp = require('./lib/csp')
+const config = require('./lib/config')
+const logger = require('./lib/logger')
+const errors = require('./lib/errors')
+const models = require('./lib/models')
+const csp = require('./lib/csp')
// server setup
-var app = express()
-var server = null
+const app = express()
+let server = null
if (config.useSSL) {
- var ca = (function () {
- var i, len, results
- results = []
+ const ca = (function () {
+ let i, len
+ const results = []
for (i = 0, len = config.sslCAPath.length; i < len; i++) {
results.push(fs.readFileSync(config.sslCAPath[i], 'utf8'))
}
return results
})()
- var options = {
+ const options = {
key: fs.readFileSync(config.sslKeyPath, 'utf8'),
cert: fs.readFileSync(config.sslCertPath, 'utf8'),
ca: ca,
@@ -60,18 +60,18 @@ if (!config.useSSL && config.protocolUseSSL) {
// logger
app.use(morgan('combined', {
- 'stream': logger.stream
+ stream: logger.stream
}))
// socket io
-var io = require('socket.io')(server, { cookie: false })
+const io = require('socket.io')(server, { cookie: false })
io.engine.ws = new (require('ws').Server)({
noServer: true,
perMessageDeflate: false
})
// others
-var realtime = require('./lib/realtime.js')
+const realtime = require('./lib/realtime.js')
// assign socket io to realtime
realtime.io = io
@@ -80,7 +80,7 @@ realtime.io = io
app.use(methodOverride('_method'))
// session store
-var sessionStore = new SequelizeStore({
+const sessionStore = new SequelizeStore({
db: models.sequelize
})
@@ -154,7 +154,7 @@ app.use(session({
}))
// session resumption
-var tlsSessionStore = {}
+const tlsSessionStore = {}
server.on('newSession', function (id, data, cb) {
tlsSessionStore[id.toString('hex')] = data
cb()
@@ -246,9 +246,9 @@ io.sockets.on('connection', realtime.connection)
// listen
function startListen () {
- var address
- var listenCallback = function () {
- var schema = config.useSSL ? 'HTTPS' : 'HTTP'
+ let address
+ const listenCallback = function () {
+ const schema = config.useSSL ? 'HTTPS' : 'HTTP'
logger.info('%s Server listening at %s', schema, address)
realtime.maintenance = false
}
@@ -290,7 +290,7 @@ function handleTermSignals () {
realtime.maintenance = true
// disconnect all socket.io clients
Object.keys(io.sockets.sockets).forEach(function (key) {
- var socket = io.sockets.sockets[key]
+ const socket = io.sockets.sockets[key]
// notify client server going into maintenance status
socket.emit('maintenance')
setTimeout(function () {
@@ -300,7 +300,7 @@ function handleTermSignals () {
if (config.path) {
fs.unlink(config.path)
}
- var checkCleanTimer = setInterval(function () {
+ const checkCleanTimer = setInterval(function () {
if (realtime.isReady()) {
models.Revision.checkAllNotesRevision(function (err, notes) {
if (err) return logger.error(err)
diff --git a/lib/config/index.js b/lib/config/index.js
index 1657ba7a..17c13f5f 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -58,14 +58,14 @@ if (!['strict', 'lax', 'none'].includes(config.cookiePolicy)) {
// load LDAP CA
if (config.ldap.tlsca) {
- let ca = config.ldap.tlsca.split(',')
- let caContent = []
- for (let i of ca) {
+ const ca = config.ldap.tlsca.split(',')
+ const caContent = []
+ for (const i of ca) {
if (fs.existsSync(i)) {
caContent.push(fs.readFileSync(i, 'utf8'))
}
}
- let tlsOptions = {
+ const tlsOptions = {
ca: caContent
}
config.ldap.tlsOptions = config.ldap.tlsOptions ? Object.assign(config.ldap.tlsOptions, tlsOptions) : tlsOptions
@@ -90,9 +90,9 @@ config.isStandardHTTPPort = (function isStandardHTTPPort () {
// cache serverURL
config.serverURL = (function getserverurl () {
- var url = ''
+ let url = ''
if (config.domain) {
- var protocol = config.protocolUseSSL ? 'https://' : 'http://'
+ const protocol = config.protocolUseSSL ? 'https://' : 'http://'
url = protocol + config.domain
if (config.urlAddPort) {
if (!config.isStandardHTTPPort || !config.isStandardHTTPsPort) {
@@ -138,10 +138,10 @@ config.isGitlabSnippetsEnable = (!config.gitlab.scope || config.gitlab.scope ===
config.updateI18nFiles = (env === Environment.development)
// merge legacy values
-let keys = Object.keys(config)
+const keys = Object.keys(config)
const uppercase = /[A-Z]/
for (let i = keys.length; i--;) {
- let lowercaseKey = keys[i].toLowerCase()
+ const lowercaseKey = keys[i].toLowerCase()
// if the config contains uppercase letters
// and a lowercase version of this setting exists
// and the config with uppercase is not set
diff --git a/lib/csp.js b/lib/csp.js
index 24399436..a5f0a4fc 100644
--- a/lib/csp.js
+++ b/lib/csp.js
@@ -1,9 +1,9 @@
-var config = require('./config')
-var uuid = require('uuid')
+const config = require('./config')
+const uuid = require('uuid')
-var CspStrategy = {}
+const CspStrategy = {}
-var defaultDirectives = {
+const defaultDirectives = {
defaultSrc: ['\'self\''],
scriptSrc: ['\'self\'', 'vimeo.com', 'https://gist.github.com', 'www.slideshare.net', 'https://query.yahooapis.com', '\'unsafe-eval\''],
// ^ TODO: Remove unsafe-eval - webpack script-loader issues https://github.com/hackmdio/codimd/issues/594
@@ -16,28 +16,28 @@ var defaultDirectives = {
connectSrc: ['*']
}
-var cdnDirectives = {
+const cdnDirectives = {
scriptSrc: ['https://cdnjs.cloudflare.com', 'https://cdn.mathjax.org'],
styleSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.googleapis.com'],
fontSrc: ['https://cdnjs.cloudflare.com', 'https://fonts.gstatic.com']
}
-var disqusDirectives = {
+const disqusDirectives = {
scriptSrc: ['https://disqus.com', 'https://*.disqus.com', 'https://*.disquscdn.com'],
styleSrc: ['https://*.disquscdn.com'],
fontSrc: ['https://*.disquscdn.com']
}
-var googleAnalyticsDirectives = {
+const googleAnalyticsDirectives = {
scriptSrc: ['https://www.google-analytics.com']
}
-var dropboxDirectives = {
+const dropboxDirectives = {
scriptSrc: ['https://www.dropbox.com', '\'unsafe-inline\'']
}
CspStrategy.computeDirectives = function () {
- var directives = {}
+ const directives = {}
mergeDirectives(directives, config.csp.directives)
mergeDirectivesIf(config.csp.addDefaults, directives, defaultDirectives)
mergeDirectivesIf(config.useCDN, directives, cdnDirectives)
@@ -53,10 +53,10 @@ CspStrategy.computeDirectives = function () {
}
function mergeDirectives (existingDirectives, newDirectives) {
- for (var propertyName in newDirectives) {
- var newDirective = newDirectives[propertyName]
+ for (const propertyName in newDirectives) {
+ const newDirective = newDirectives[propertyName]
if (newDirective) {
- var existingDirective = existingDirectives[propertyName] || []
+ const existingDirective = existingDirectives[propertyName] || []
existingDirectives[propertyName] = existingDirective.concat(newDirective)
}
}
diff --git a/lib/history.js b/lib/history.js
index 3ebf77fd..e4ce9221 100644
--- a/lib/history.js
+++ b/lib/history.js
@@ -1,15 +1,15 @@
'use strict'
// history
// external modules
-var LZString = require('lz-string')
+const LZString = require('lz-string')
// core
-var logger = require('./logger')
-var models = require('./models')
+const logger = require('./logger')
+const models = require('./models')
const errors = require('./errors')
// public
-var History = {
+const History = {
historyGet: historyGet,
historyPost: historyPost,
historyDelete: historyDelete,
@@ -25,7 +25,7 @@ function getHistory (userid, callback) {
if (!user) {
return callback(null, null)
}
- var history = {}
+ let history = {}
if (user.history) {
history = JSON.parse(user.history)
// migrate LZString encoded note id to base64url encoded note id
@@ -40,7 +40,7 @@ function getHistory (userid, callback) {
continue
}
try {
- let id = LZString.decompressFromBase64(history[i].id)
+ const id = LZString.decompressFromBase64(history[i].id)
if (id && models.Note.checkNoteIdValid(id)) {
history[i].id = models.Note.encodeNoteId(id)
}
@@ -85,8 +85,8 @@ function updateHistory (userid, noteId, document, time) {
if (!history[noteId]) {
history[noteId] = {}
}
- var noteHistory = history[noteId]
- var noteInfo = models.Note.parseNoteInfo(document)
+ const noteHistory = history[noteId]
+ const noteInfo = models.Note.parseNoteInfo(document)
noteHistory.id = noteId
noteHistory.text = noteInfo.title
noteHistory.time = time || Date.now()
@@ -101,18 +101,18 @@ function updateHistory (userid, noteId, document, time) {
}
function parseHistoryToArray (history) {
- var _history = []
+ const _history = []
Object.keys(history).forEach(function (key) {
- var item = history[key]
+ const item = history[key]
_history.push(item)
})
return _history
}
function parseHistoryToObject (history) {
- var _history = {}
- for (var i = 0, l = history.length; i < l; i++) {
- var item = history[i]
+ const _history = {}
+ for (let i = 0, l = history.length; i < l; i++) {
+ const item = history[i]
_history[item.id] = item
}
return _history
@@ -134,25 +134,25 @@ function historyGet (req, res) {
function historyPost (req, res) {
if (req.isAuthenticated()) {
- var noteId = req.params.noteId
+ const noteId = req.params.noteId
if (!noteId) {
- if (typeof req.body['history'] === 'undefined') return errors.errorBadRequest(res)
+ if (typeof req.body.history === 'undefined') return errors.errorBadRequest(res)
logger.debug(`SERVER received history from [${req.user.id}]: ${req.body.history}`)
try {
- var history = JSON.parse(req.body.history)
+ const history = JSON.parse(req.body.history)
+ if (Array.isArray(history)) {
+ setHistory(req.user.id, history, function (err, count) {
+ if (err) return errors.errorInternalError(res)
+ res.end()
+ })
+ } else {
+ return errors.errorBadRequest(res)
+ }
} catch (err) {
return errors.errorBadRequest(res)
}
- if (Array.isArray(history)) {
- setHistory(req.user.id, history, function (err, count) {
- if (err) return errors.errorInternalError(res)
- res.end()
- })
- } else {
- return errors.errorBadRequest(res)
- }
} else {
- if (typeof req.body['pinned'] === 'undefined') return errors.errorBadRequest(res)
+ if (typeof req.body.pinned === 'undefined') return errors.errorBadRequest(res)
getHistory(req.user.id, function (err, history) {
if (err) return errors.errorInternalError(res)
if (!history) return errors.errorNotFound(res)
@@ -175,7 +175,7 @@ function historyPost (req, res) {
function historyDelete (req, res) {
if (req.isAuthenticated()) {
- var noteId = req.params.noteId
+ const noteId = req.params.noteId
if (!noteId) {
setHistory(req.user.id, [], function (err, count) {
if (err) return errors.errorInternalError(res)
diff --git a/lib/letter-avatars.js b/lib/letter-avatars.js
index 6fb1888a..bb7a9fe8 100644
--- a/lib/letter-avatars.js
+++ b/lib/letter-avatars.js
@@ -32,9 +32,9 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
}
name = encodeURIComponent(name)
- let hash = crypto.createHash('md5')
+ const hash = crypto.createHash('md5')
hash.update(email.toLowerCase())
- let hexDigest = hash.digest('hex')
+ const hexDigest = hash.digest('hex')
if (email !== '' && config.allowGravatar) {
photo = 'https://cdn.libravatar.org/avatar/' + hexDigest
diff --git a/lib/models/author.js b/lib/models/author.js
index e65791cb..4c995745 100644
--- a/lib/models/author.js
+++ b/lib/models/author.js
@@ -1,9 +1,9 @@
'use strict'
// external modules
-var Sequelize = require('sequelize')
+const Sequelize = require('sequelize')
module.exports = function (sequelize, DataTypes) {
- var Author = sequelize.define('Author', {
+ const Author = sequelize.define('Author', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
diff --git a/lib/models/index.js b/lib/models/index.js
index 88c1b168..e752a993 100644
--- a/lib/models/index.js
+++ b/lib/models/index.js
@@ -1,20 +1,22 @@
'use strict'
// external modules
-var fs = require('fs')
-var path = require('path')
-var Sequelize = require('sequelize')
+const fs = require('fs')
+const path = require('path')
+const Sequelize = require('sequelize')
const { cloneDeep } = require('lodash')
// core
-var config = require('../config')
-var logger = require('../logger')
+const config = require('../config')
+const logger = require('../logger')
-var dbconfig = cloneDeep(config.db)
-dbconfig.logging = config.debug ? (data) => {
- logger.info(data)
-} : false
+const dbconfig = cloneDeep(config.db)
+dbconfig.logging = config.debug
+ ? (data) => {
+ logger.info(data)
+ }
+ : false
-var sequelize = null
+let sequelize = null
// Heroku specific
if (config.dbURL) {
@@ -38,14 +40,14 @@ function processData (data, _default, process) {
}
sequelize.processData = processData
-var db = {}
+const db = {}
fs.readdirSync(__dirname)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js')
})
.forEach(function (file) {
- var model = sequelize.import(path.join(__dirname, file))
+ const model = sequelize.import(path.join(__dirname, file))
db[model.name] = model
})
diff --git a/lib/models/note.js b/lib/models/note.js
index 7418c47e..7b8b6783 100644
--- a/lib/models/note.js
+++ b/lib/models/note.js
@@ -1,32 +1,32 @@
'use strict'
// external modules
-var fs = require('fs')
-var path = require('path')
-var LZString = require('lz-string')
-var base64url = require('base64url')
-var md = require('markdown-it')()
-var metaMarked = require('meta-marked')
-var cheerio = require('cheerio')
-var shortId = require('shortid')
-var Sequelize = require('sequelize')
-var async = require('async')
-var moment = require('moment')
-var DiffMatchPatch = require('diff-match-patch')
-var dmp = new DiffMatchPatch()
-var S = require('string')
+const fs = require('fs')
+const path = require('path')
+const LZString = require('lz-string')
+const base64url = require('base64url')
+const md = require('markdown-it')()
+const metaMarked = require('meta-marked')
+const cheerio = require('cheerio')
+const shortId = require('shortid')
+const Sequelize = require('sequelize')
+const async = require('async')
+const moment = require('moment')
+const DiffMatchPatch = require('diff-match-patch')
+const dmp = new DiffMatchPatch()
+const S = require('string')
// core
-var config = require('../config')
-var logger = require('../logger')
+const config = require('../config')
+const logger = require('../logger')
// ot
-var ot = require('../ot')
+const ot = require('../ot')
// permission types
-var permissionTypes = ['freely', 'editable', 'limited', 'locked', 'protected', 'private']
+const permissionTypes = ['freely', 'editable', 'limited', 'locked', 'protected', 'private']
module.exports = function (sequelize, DataTypes) {
- var Note = sequelize.define('Note', {
+ const Note = sequelize.define('Note', {
id: {
type: DataTypes.UUID,
primaryKey: true,
@@ -91,7 +91,7 @@ module.exports = function (sequelize, DataTypes) {
return new Promise(function (resolve, reject) {
// if no content specified then use default note
if (!note.content) {
- var body = null
+ let body = null
let filePath = null
if (note.alias) {
filePath = path.join(config.docsPath, note.alias + '.md')
@@ -100,7 +100,7 @@ module.exports = function (sequelize, DataTypes) {
filePath = config.defaultNotePath
}
if (Note.checkFileExist(filePath)) {
- var fsCreatedTime = moment(fs.statSync(filePath).ctime)
+ const fsCreatedTime = moment(fs.statSync(filePath).ctime)
body = fs.readFileSync(filePath, 'utf8')
note.title = Note.parseNoteTitle(body)
note.content = body
@@ -165,15 +165,15 @@ module.exports = function (sequelize, DataTypes) {
}
Note.encodeNoteId = function (id) {
// remove dashes in UUID and encode in url-safe base64
- let str = id.replace(/-/g, '')
- let hexStr = Buffer.from(str, 'hex')
+ const str = id.replace(/-/g, '')
+ const hexStr = Buffer.from(str, 'hex')
return base64url.encode(hexStr)
}
Note.decodeNoteId = function (encodedId) {
// 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
- let idParts = []
+ const idParts = []
idParts.push(id.substr(0, 8))
idParts.push(id.substr(8, 4))
idParts.push(id.substr(12, 4))
@@ -182,8 +182,8 @@ module.exports = function (sequelize, DataTypes) {
return idParts.join('-')
}
Note.checkNoteIdValid = function (id) {
- var 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
- var result = id.match(uuidRegex)
+ 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
+ const result = id.match(uuidRegex)
if (result && result.length === 1) { return true } else { return false }
}
Note.parseNoteId = function (noteId, callback) {
@@ -196,15 +196,15 @@ module.exports = function (sequelize, DataTypes) {
}
}).then(function (note) {
if (note) {
- let filePath = path.join(config.docsPath, noteId + '.md')
+ const filePath = path.join(config.docsPath, noteId + '.md')
if (Note.checkFileExist(filePath)) {
// if doc in filesystem have newer modified time than last change time
// then will update the doc in db
- var fsModifiedTime = moment(fs.statSync(filePath).mtime)
- var dbModifiedTime = moment(note.lastchangeAt || note.createdAt)
- var body = fs.readFileSync(filePath, 'utf8')
- var contentLength = body.length
- var title = Note.parseNoteTitle(body)
+ const fsModifiedTime = moment(fs.statSync(filePath).mtime)
+ const dbModifiedTime = moment(note.lastchangeAt || note.createdAt)
+ const body = fs.readFileSync(filePath, 'utf8')
+ const contentLength = body.length
+ const title = Note.parseNoteTitle(body)
if (fsModifiedTime.isAfter(dbModifiedTime) && note.content !== body) {
note.update({
title: title,
@@ -214,9 +214,9 @@ module.exports = function (sequelize, DataTypes) {
sequelize.models.Revision.saveNoteRevision(note, function (err, revision) {
if (err) return _callback(err, null)
// update authorship on after making revision of docs
- var patch = dmp.patch_fromText(revision.patch)
- var operations = Note.transformPatchToOperations(patch, contentLength)
- var authorship = note.authorship
+ const patch = dmp.patch_fromText(revision.patch)
+ const operations = Note.transformPatchToOperations(patch, contentLength)
+ let authorship = note.authorship
for (let i = 0; i < operations.length; i++) {
authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship)
}
@@ -238,7 +238,7 @@ module.exports = function (sequelize, DataTypes) {
return callback(null, note.id)
}
} else {
- var filePath = path.join(config.docsPath, noteId + '.md')
+ const filePath = path.join(config.docsPath, noteId + '.md')
if (Note.checkFileExist(filePath)) {
Note.create({
alias: noteId,
@@ -270,7 +270,7 @@ module.exports = function (sequelize, DataTypes) {
}
// try to parse note id by LZString Base64
try {
- var id = LZString.decompressFromBase64(noteId)
+ const id = LZString.decompressFromBase64(noteId)
if (id && Note.checkNoteIdValid(id)) { return callback(null, id) } else { return _callback(null, null) }
} catch (err) {
if (err.message === 'Cannot read property \'charAt\' of undefined') {
@@ -284,7 +284,7 @@ module.exports = function (sequelize, DataTypes) {
parseNoteIdByBase64Url: function (_callback) {
// try to parse note id by base64url
try {
- var id = Note.decodeNoteId(noteId)
+ const id = Note.decodeNoteId(noteId)
if (id && Note.checkNoteIdValid(id)) { return callback(null, id) } else { return _callback(null, null) }
} catch (err) {
logger.error(err)
@@ -321,24 +321,24 @@ module.exports = function (sequelize, DataTypes) {
})
}
Note.parseNoteInfo = function (body) {
- var parsed = Note.extractMeta(body)
- var $ = cheerio.load(md.render(parsed.markdown))
+ const parsed = Note.extractMeta(body)
+ const $ = cheerio.load(md.render(parsed.markdown))
return {
title: Note.extractNoteTitle(parsed.meta, $),
tags: Note.extractNoteTags(parsed.meta, $)
}
}
Note.parseNoteTitle = function (body) {
- var parsed = Note.extractMeta(body)
- var $ = cheerio.load(md.render(parsed.markdown))
+ const parsed = Note.extractMeta(body)
+ const $ = cheerio.load(md.render(parsed.markdown))
return Note.extractNoteTitle(parsed.meta, $)
}
Note.extractNoteTitle = function (meta, $) {
- var title = ''
+ let title = ''
if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) {
title = meta.title
} else {
- var h1s = $('h1')
+ const h1s = $('h1')
if (h1s.length > 0 && h1s.first().text().split('\n').length === 1) { title = S(h1s.first().text()).stripTags().s }
}
if (!title) title = 'Untitled'
@@ -355,28 +355,28 @@ module.exports = function (sequelize, DataTypes) {
return title
}
Note.extractNoteTags = function (meta, $) {
- var tags = []
- var rawtags = []
+ const tags = []
+ const rawtags = []
if (meta.tags && (typeof meta.tags === 'string' || typeof meta.tags === 'number')) {
- var metaTags = ('' + meta.tags).split(',')
+ const metaTags = ('' + meta.tags).split(',')
for (let i = 0; i < metaTags.length; i++) {
- var text = metaTags[i].trim()
+ const text = metaTags[i].trim()
if (text) rawtags.push(text)
}
} else {
- var h6s = $('h6')
+ const h6s = $('h6')
h6s.each(function (key, value) {
if (/^tags/gmi.test($(value).text())) {
- var codes = $(value).find('code')
+ const codes = $(value).find('code')
for (let i = 0; i < codes.length; i++) {
- var text = S($(codes[i]).text().trim()).stripTags().s
+ const text = S($(codes[i]).text().trim()).stripTags().s
if (text) rawtags.push(text)
}
}
})
}
for (let i = 0; i < rawtags.length; i++) {
- var found = false
+ let found = false
for (let j = 0; j < tags.length; j++) {
if (tags[j] === rawtags[i]) {
found = true
@@ -388,7 +388,7 @@ module.exports = function (sequelize, DataTypes) {
return tags
}
Note.extractMeta = function (content) {
- var obj = null
+ let obj = null
try {
obj = metaMarked(content)
if (!obj.markdown) obj.markdown = ''
@@ -402,7 +402,7 @@ module.exports = function (sequelize, DataTypes) {
return obj
}
Note.parseMeta = function (meta) {
- var _meta = {}
+ const _meta = {}
if (meta) {
if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) { _meta.title = meta.title }
if (meta.description && (typeof meta.description === 'string' || typeof meta.description === 'number')) { _meta.description = meta.description }
@@ -416,7 +416,7 @@ module.exports = function (sequelize, DataTypes) {
return _meta
}
Note.parseOpengraph = function (meta, title) {
- var _ogdata = {}
+ let _ogdata = {}
if (meta.opengraph) { _ogdata = meta.opengraph }
if (!(_ogdata.title && (typeof _ogdata.title === 'string' || typeof _ogdata.title === 'number'))) { _ogdata.title = title }
if (!(_ogdata.description && (typeof _ogdata.description === 'string' || typeof _ogdata.description === 'number'))) { _ogdata.description = meta.description || '' }
@@ -424,27 +424,27 @@ module.exports = function (sequelize, DataTypes) {
return _ogdata
}
Note.updateAuthorshipByOperation = function (operation, userId, authorships) {
- var index = 0
- var timestamp = Date.now()
+ let index = 0
+ const timestamp = Date.now()
for (let i = 0; i < operation.length; i++) {
- var op = operation[i]
+ const op = operation[i]
if (ot.TextOperation.isRetain(op)) {
index += op
} else if (ot.TextOperation.isInsert(op)) {
- let opStart = index
- let opEnd = index + op.length
- var inserted = false
+ const opStart = index
+ const opEnd = index + op.length
+ let inserted = false
// authorship format: [userId, startPos, endPos, createdAt, updatedAt]
if (authorships.length <= 0) authorships.push([userId, opStart, opEnd, timestamp, timestamp])
else {
for (let j = 0; j < authorships.length; j++) {
- let authorship = authorships[j]
+ const authorship = authorships[j]
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 (authorship[1] < opStart && authorship[2] > opStart) {
// divide
- let postLength = authorship[2] - opStart
+ const postLength = authorship[2] - opStart
authorship[2] = opStart
authorship[4] = timestamp
authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp])
@@ -470,13 +470,13 @@ module.exports = function (sequelize, DataTypes) {
}
index += op.length
} else if (ot.TextOperation.isDelete(op)) {
- let opStart = index
- let opEnd = index - op
+ const opStart = index
+ const opEnd = index - op
if (operation.length === 1) {
authorships = []
} else if (authorships.length > 0) {
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) {
authorships.splice(j, 1)
j -= 1
@@ -501,12 +501,12 @@ module.exports = function (sequelize, DataTypes) {
}
// merge
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++) {
- let nextAuthorship = authorships[k]
+ const nextAuthorship = authorships[k]
if (nextAuthorship && authorship[0] === nextAuthorship[0] && authorship[2] === nextAuthorship[1]) {
- let minTimestamp = Math.min(authorship[3], nextAuthorship[3])
- let maxTimestamp = Math.max(authorship[3], nextAuthorship[3])
+ const minTimestamp = Math.min(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(k, 1)
j -= 1
@@ -516,7 +516,7 @@ module.exports = function (sequelize, DataTypes) {
}
// clear
for (let j = 0; j < authorships.length; j++) {
- let authorship = authorships[j]
+ const authorship = authorships[j]
if (!authorship[0]) {
authorships.splice(j, 1)
j -= 1
@@ -525,13 +525,13 @@ module.exports = function (sequelize, DataTypes) {
return authorships
}
Note.transformPatchToOperations = function (patch, contentLength) {
- var operations = []
+ const operations = []
if (patch.length > 0) {
// calculate original content length
for (let j = patch.length - 1; j >= 0; j--) {
- var p = patch[j]
+ const p = patch[j]
for (let i = 0; i < p.diffs.length; i++) {
- var diff = p.diffs[i]
+ const diff = p.diffs[i]
switch (diff[0]) {
case 1: // insert
contentLength -= diff[1].length
@@ -543,15 +543,15 @@ module.exports = function (sequelize, DataTypes) {
}
}
// generate operations
- var bias = 0
- var lengthBias = 0
+ let bias = 0
+ let lengthBias = 0
for (let j = 0; j < patch.length; j++) {
- var operation = []
- let p = patch[j]
- var currIndex = p.start1
- var currLength = contentLength - bias
+ const operation = []
+ const p = patch[j]
+ let currIndex = p.start1
+ const currLength = contentLength - bias
for (let i = 0; i < p.diffs.length; i++) {
- let diff = p.diffs[i]
+ const diff = p.diffs[i]
switch (diff[0]) {
case 0: // retain
if (i === 0) {
diff --git a/lib/models/revision.js b/lib/models/revision.js
index dbd76e4e..80136c68 100644
--- a/lib/models/revision.js
+++ b/lib/models/revision.js
@@ -1,22 +1,22 @@
'use strict'
// external modules
-var Sequelize = require('sequelize')
-var async = require('async')
-var moment = require('moment')
-var childProcess = require('child_process')
-var shortId = require('shortid')
-var path = require('path')
+const Sequelize = require('sequelize')
+const async = require('async')
+const moment = require('moment')
+const childProcess = require('child_process')
+const shortId = require('shortid')
+const path = require('path')
-var Op = Sequelize.Op
+const Op = Sequelize.Op
// core
-var logger = require('../logger')
+const logger = require('../logger')
-var dmpWorker = createDmpWorker()
-var dmpCallbackCache = {}
+let dmpWorker = createDmpWorker()
+const dmpCallbackCache = {}
function createDmpWorker () {
- var worker = childProcess.fork(path.resolve(__dirname, '../workers/dmpWorker.js'), {
+ const worker = childProcess.fork(path.resolve(__dirname, '../workers/dmpWorker.js'), {
stdio: 'ignore'
})
logger.debug('dmp worker process started')
@@ -24,7 +24,7 @@ function createDmpWorker () {
if (!data || !data.msg || !data.cacheKey) {
return logger.error('dmp worker error: not enough data on message')
}
- var cacheKey = data.cacheKey
+ const cacheKey = data.cacheKey
switch (data.msg) {
case 'error':
dmpCallbackCache[cacheKey](data.error, null)
@@ -44,7 +44,7 @@ function createDmpWorker () {
function sendDmpWorker (data, callback) {
if (!dmpWorker) dmpWorker = createDmpWorker()
- var cacheKey = Date.now() + '_' + shortId.generate()
+ const cacheKey = Date.now() + '_' + shortId.generate()
dmpCallbackCache[cacheKey] = callback
data = Object.assign(data, {
cacheKey: cacheKey
@@ -53,7 +53,7 @@ function sendDmpWorker (data, callback) {
}
module.exports = function (sequelize, DataTypes) {
- var Revision = sequelize.define('Revision', {
+ const Revision = sequelize.define('Revision', {
id: {
type: DataTypes.UUID,
primaryKey: true,
@@ -116,9 +116,9 @@ module.exports = function (sequelize, DataTypes) {
},
order: [['createdAt', 'DESC']]
}).then(function (revisions) {
- var data = []
- for (var i = 0, l = revisions.length; i < l; i++) {
- var revision = revisions[i]
+ const data = []
+ for (let i = 0, l = revisions.length; i < l; i++) {
+ const revision = revisions[i]
data.push({
time: moment(revision.createdAt).valueOf(),
length: revision.length
@@ -199,12 +199,12 @@ module.exports = function (sequelize, DataTypes) {
}
}).then(function (notes) {
if (notes.length <= 0) return callback(null, notes)
- var savedNotes = []
+ const savedNotes = []
async.each(notes, function (note, _callback) {
// revision saving policy: note not been modified for 5 mins or not save for 10 mins
if (note.lastchangeAt && note.savedAt) {
- var lastchangeAt = moment(note.lastchangeAt)
- var savedAt = moment(note.savedAt)
+ const lastchangeAt = moment(note.lastchangeAt)
+ const savedAt = moment(note.savedAt)
if (moment().isAfter(lastchangeAt.add(5, 'minutes'))) {
savedNotes.push(note)
Revision.saveNoteRevision(note, _callback)
@@ -223,7 +223,7 @@ module.exports = function (sequelize, DataTypes) {
return callback(err, null)
}
// return null when no notes need saving at this moment but have delayed tasks to be done
- var result = ((savedNotes.length === 0) && (notes.length > savedNotes.length)) ? null : savedNotes
+ const result = ((savedNotes.length === 0) && (notes.length > savedNotes.length)) ? null : savedNotes
return callback(null, result)
})
}).catch(function (err) {
@@ -250,9 +250,9 @@ module.exports = function (sequelize, DataTypes) {
return callback(err, null)
})
} else {
- var latestRevision = revisions[0]
- var lastContent = latestRevision.content || latestRevision.lastContent
- var content = note.content
+ const latestRevision = revisions[0]
+ const lastContent = latestRevision.content || latestRevision.lastContent
+ const content = note.content
sendDmpWorker({
msg: 'create patch',
lastDoc: lastContent,
diff --git a/lib/models/temp.js b/lib/models/temp.js
index 2ad23fb5..dee6c573 100644
--- a/lib/models/temp.js
+++ b/lib/models/temp.js
@@ -1,9 +1,9 @@
'use strict'
// external modules
-var shortId = require('shortid')
+const shortId = require('shortid')
module.exports = function (sequelize, DataTypes) {
- var Temp = sequelize.define('Temp', {
+ const Temp = sequelize.define('Temp', {
id: {
type: DataTypes.STRING,
primaryKey: true,
diff --git a/lib/models/user.js b/lib/models/user.js
index 50c78108..26a557a7 100644
--- a/lib/models/user.js
+++ b/lib/models/user.js
@@ -17,7 +17,7 @@ const logger = require('../logger')
const { generateAvatarURL } = require('../letter-avatars')
module.exports = function (sequelize, DataTypes) {
- var User = sequelize.define('User', {
+ const User = sequelize.define('User', {
id: {
type: DataTypes.UUID,
primaryKey: true,
@@ -91,7 +91,7 @@ module.exports = function (sequelize, DataTypes) {
return profile
}
User.parsePhotoByProfile = function (profile, bigger) {
- var photo = null
+ let photo = null
switch (profile.provider) {
case 'facebook':
photo = 'https://graph.facebook.com/' + profile.id + '/picture'
diff --git a/lib/realtime.js b/lib/realtime.js
index ec99707e..abea7165 100644
--- a/lib/realtime.js
+++ b/lib/realtime.js
@@ -1,25 +1,25 @@
'use strict'
// realtime
// external modules
-var cookie = require('cookie')
-var cookieParser = require('cookie-parser')
-var async = require('async')
-var randomcolor = require('randomcolor')
-var Chance = require('chance')
-var chance = new Chance()
-var moment = require('moment')
+const cookie = require('cookie')
+const cookieParser = require('cookie-parser')
+const async = require('async')
+const randomcolor = require('randomcolor')
+const Chance = require('chance')
+const chance = new Chance()
+const moment = require('moment')
// core
-var config = require('./config')
-var logger = require('./logger')
-var history = require('./history')
-var models = require('./models')
+const config = require('./config')
+const logger = require('./logger')
+const history = require('./history')
+const models = require('./models')
// ot
-var ot = require('./ot')
+const ot = require('./ot')
// public
-var realtime = {
+const realtime = {
io: null,
onAuthorizeSuccess: onAuthorizeSuccess,
onAuthorizeFail: onAuthorizeFail,
@@ -41,7 +41,7 @@ function onAuthorizeFail (data, message, error, accept) {
// secure the origin by the cookie
function secure (socket, next) {
try {
- var handshakeData = socket.request
+ const handshakeData = socket.request
if (handshakeData.headers.cookie) {
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie)
handshakeData.sessionID = cookieParser.signedCookie(handshakeData.cookie[config.sessionName], config.sessionSecret)
@@ -62,7 +62,7 @@ function secure (socket, next) {
}
function emitCheck (note) {
- var out = {
+ const out = {
title: note.title,
updatetime: note.updatetime,
lastchangeuser: note.lastchangeuser,
@@ -74,12 +74,12 @@ function emitCheck (note) {
}
// actions
-var users = {}
-var notes = {}
+const users = {}
+const notes = {}
// update when the note is dirty
setInterval(function () {
async.each(Object.keys(notes), function (key, callback) {
- var note = notes[key]
+ const note = notes[key]
if (note.server.isDirty) {
logger.debug(`updater found dirty note: ${key}`)
note.server.isDirty = false
@@ -93,8 +93,8 @@ setInterval(function () {
logger.error('note not found: ', note.id)
}
if (err || !_note) {
- for (var i = 0, l = note.socks.length; i < l; i++) {
- var sock = note.socks[i]
+ for (let i = 0, l = note.socks.length; i < l; i++) {
+ const sock = note.socks[i]
if (typeof sock !== 'undefined' && sock) {
setTimeout(function () {
sock.disconnect(true)
@@ -123,7 +123,7 @@ function updateNote (note, callback) {
}).then(function (_note) {
if (!_note) return callback(null, null)
// update user note history
- var tempUsers = Object.assign({}, note.tempUsers)
+ const tempUsers = Object.assign({}, note.tempUsers)
note.tempUsers = {}
Object.keys(tempUsers).forEach(function (key) {
updateHistory(key, note, tempUsers[key])
@@ -157,9 +157,9 @@ function updateNote (note, callback) {
function finishUpdateNote (note, _note, callback) {
if (!note || !note.server) return callback(null, null)
- var body = note.server.document
- var title = note.title = models.Note.parseNoteTitle(body)
- var values = {
+ const body = note.server.document
+ const title = note.title = models.Note.parseNoteTitle(body)
+ const values = {
title: title,
content: body,
authorship: note.authorship,
@@ -178,7 +178,7 @@ function finishUpdateNote (note, _note, callback) {
// clean when user not in any rooms or user not in connected list
setInterval(function () {
async.each(Object.keys(users), function (key, callback) {
- var socket = realtime.io.sockets.connected[key]
+ let socket = realtime.io.sockets.connected[key]
if ((!socket && users[key]) ||
(socket && (!socket.rooms || socket.rooms.length <= 0))) {
logger.debug(`cleaner found redundant user: ${key}`)
@@ -196,7 +196,7 @@ setInterval(function () {
})
}, 60000)
-var saverSleep = false
+let saverSleep = false
// save note revision in interval
setInterval(function () {
if (saverSleep) return
@@ -210,11 +210,11 @@ setInterval(function () {
function getStatus (callback) {
models.Note.count().then(function (notecount) {
- var distinctaddresses = []
- var regaddresses = []
- var distinctregaddresses = []
+ const distinctaddresses = []
+ const regaddresses = []
+ const distinctregaddresses = []
Object.keys(users).forEach(function (key) {
- var user = users[key]
+ const user = users[key]
if (!user) return
let found = false
for (let i = 0; i < distinctaddresses.length; i++) {
@@ -241,20 +241,22 @@ function getStatus (callback) {
}
})
models.User.count().then(function (regcount) {
- // eslint-disable-next-line standard/no-callback-literal
- return callback ? callback({
- onlineNotes: Object.keys(notes).length,
- onlineUsers: Object.keys(users).length,
- distinctOnlineUsers: distinctaddresses.length,
- notesCount: notecount,
- registeredUsers: regcount,
- onlineRegisteredUsers: regaddresses.length,
- distinctOnlineRegisteredUsers: distinctregaddresses.length,
- isConnectionBusy: isConnectionBusy,
- connectionSocketQueueLength: connectionSocketQueue.length,
- isDisconnectBusy: isDisconnectBusy,
- disconnectSocketQueueLength: disconnectSocketQueue.length
- }) : null
+ return callback
+ // eslint-disable-next-line node/no-callback-literal
+ ? callback({
+ onlineNotes: Object.keys(notes).length,
+ onlineUsers: Object.keys(users).length,
+ distinctOnlineUsers: distinctaddresses.length,
+ notesCount: notecount,
+ registeredUsers: regcount,
+ onlineRegisteredUsers: regaddresses.length,
+ distinctOnlineRegisteredUsers: distinctregaddresses.length,
+ isConnectionBusy: isConnectionBusy,
+ connectionSocketQueueLength: connectionSocketQueue.length,
+ isDisconnectBusy: isDisconnectBusy,
+ disconnectSocketQueueLength: disconnectSocketQueue.length
+ })
+ : null
}).catch(function (err) {
return logger.error('count user failed: ' + err)
})
@@ -282,7 +284,7 @@ function extractNoteIdFromSocket (socket) {
}
function parseNoteIdFromSocket (socket, callback) {
- var noteId = extractNoteIdFromSocket(socket)
+ const noteId = extractNoteIdFromSocket(socket)
if (!noteId) {
return callback(null, null)
}
@@ -293,32 +295,32 @@ function parseNoteIdFromSocket (socket, callback) {
}
function emitOnlineUsers (socket) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var users = []
+ const users = []
Object.keys(notes[noteId].users).forEach(function (key) {
- var user = notes[noteId].users[key]
+ const user = notes[noteId].users[key]
if (user) { users.push(buildUserOutData(user)) }
})
- var out = {
+ const out = {
users: users
}
realtime.io.to(noteId).emit('online users', out)
}
function emitUserStatus (socket) {
- var noteId = socket.noteId
- var user = users[socket.id]
+ const noteId = socket.noteId
+ const user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
- var out = buildUserOutData(user)
+ const out = buildUserOutData(user)
socket.broadcast.to(noteId).emit('user status', out)
}
function emitRefresh (socket) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var note = notes[noteId]
- var out = {
+ const note = notes[noteId]
+ const out = {
title: note.title,
docmaxlength: config.documentMaxLength,
owner: note.owner,
@@ -335,7 +337,7 @@ function emitRefresh (socket) {
}
function isDuplicatedInSocketQueue (queue, socket) {
- for (var i = 0; i < queue.length; i++) {
+ for (let i = 0; i < queue.length; i++) {
if (queue[i] && queue[i].id === socket.id) {
return true
}
@@ -344,7 +346,7 @@ function isDuplicatedInSocketQueue (queue, socket) {
}
function clearSocketQueue (queue, socket) {
- for (var i = 0; i < queue.length; i++) {
+ for (let i = 0; i < queue.length; i++) {
if (!queue[i] || queue[i].id === socket.id) {
queue.splice(i, 1)
i--
@@ -378,10 +380,10 @@ function checkViewPermission (req, note) {
}
}
-var isConnectionBusy = false
-var connectionSocketQueue = []
-var isDisconnectBusy = false
-var disconnectSocketQueue = []
+let isConnectionBusy = false
+const connectionSocketQueue = []
+let isDisconnectBusy = false
+const disconnectSocketQueue = []
function finishConnection (socket, noteId, socketId) {
// if no valid info provided will drop the client
@@ -393,8 +395,8 @@ function finishConnection (socket, noteId, socketId) {
interruptConnection(socket, noteId, socketId)
return failConnection(403, 'connection forbidden', socket)
}
- let note = notes[noteId]
- let user = users[socketId]
+ const note = notes[noteId]
+ const user = users[socketId]
// update user color to author color
if (note.authors[user.userid]) {
user.color = users[socket.id].color = note.authors[user.userid].color
@@ -417,7 +419,7 @@ function finishConnection (socket, noteId, socketId) {
connectNextSocket()
if (config.debug) {
- let noteId = socket.noteId
+ const noteId = socket.noteId
logger.debug(`SERVER connected a client to [${noteId}]:`)
logger.debug(JSON.stringify(user))
logger.debug(notes)
@@ -431,13 +433,13 @@ function startConnection (socket) {
if (isConnectionBusy) return
isConnectionBusy = true
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId) {
return failConnection(404, 'note id not found', socket)
}
if (!notes[noteId]) {
- var include = [{
+ const include = [{
model: models.User,
as: 'owner'
}, {
@@ -461,21 +463,21 @@ function startConnection (socket) {
if (!note) {
return failConnection(404, 'note not found', socket)
}
- var owner = note.ownerId
- var ownerprofile = note.owner ? models.User.getProfile(note.owner) : null
+ const owner = note.ownerId
+ const ownerprofile = note.owner ? models.User.getProfile(note.owner) : null
- var lastchangeuser = note.lastchangeuserId
- var lastchangeuserprofile = note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null
+ const lastchangeuser = note.lastchangeuserId
+ const lastchangeuserprofile = note.lastchangeuser ? models.User.getProfile(note.lastchangeuser) : null
- var body = note.content
- var createtime = note.createdAt
- var updatetime = note.lastchangeAt
- var server = new ot.EditorSocketIOServer(body, [], noteId, ifMayEdit, operationCallback)
+ const body = note.content
+ const createtime = note.createdAt
+ const updatetime = note.lastchangeAt
+ const server = new ot.EditorSocketIOServer(body, [], noteId, ifMayEdit, operationCallback)
- var authors = {}
- for (var i = 0; i < note.authors.length; i++) {
- var author = note.authors[i]
- var profile = models.User.getProfile(author.user)
+ const authors = {}
+ for (let i = 0; i < note.authors.length; i++) {
+ const author = note.authors[i]
+ const profile = models.User.getProfile(author.user)
if (profile) {
authors[author.userId] = {
userid: author.userId,
@@ -536,16 +538,17 @@ function disconnect (socket) {
if (users[socket.id]) {
delete users[socket.id]
}
- var noteId = socket.noteId
- var note = notes[noteId]
+ const noteId = socket.noteId
+ const note = notes[noteId]
if (note) {
// delete user in users
if (note.users[socket.id]) {
delete note.users[socket.id]
}
// remove sockets in the note socks
+ let index
do {
- var index = note.socks.indexOf(socket)
+ index = note.socks.indexOf(socket)
if (index !== -1) {
note.socks.splice(index, 1)
}
@@ -590,7 +593,7 @@ function disconnect (socket) {
}
function buildUserOutData (user) {
- var out = {
+ const out = {
id: user.id,
login: user.login,
userid: user.userid,
@@ -607,7 +610,7 @@ function buildUserOutData (user) {
function updateUserData (socket, user) {
// retrieve user data from passport
if (socket.request.user && socket.request.user.logged_in) {
- var profile = models.User.getProfile(socket.request.user)
+ const profile = models.User.getProfile(socket.request.user)
user.photo = profile.photo
user.name = profile.name
user.userid = socket.request.user.id
@@ -620,10 +623,10 @@ function updateUserData (socket, user) {
}
function ifMayEdit (socket, callback) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var note = notes[noteId]
- var mayEdit = true
+ const note = notes[noteId]
+ let mayEdit = true
switch (note.permission) {
case 'freely':
// not blocking anyone
@@ -650,13 +653,13 @@ function ifMayEdit (socket, callback) {
}
function operationCallback (socket, operation) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var note = notes[noteId]
- var userId = null
+ const note = notes[noteId]
+ let userId = null
// save authors
if (socket.request.user && socket.request.user.logged_in) {
- var user = users[socket.id]
+ const user = users[socket.id]
if (!user) return
userId = socket.request.user.id
if (!note.authors[userId]) {
@@ -692,7 +695,7 @@ function operationCallback (socket, operation) {
}
function updateHistory (userId, note, time) {
- var noteId = note.alias ? note.alias : models.Note.encodeNoteId(note.id)
+ const noteId = note.alias ? note.alias : models.Note.encodeNoteId(note.id)
if (note.server) history.updateHistory(userId, noteId, note.server.document, time)
}
@@ -713,12 +716,12 @@ function connection (socket) {
// initialize user data
// random color
- var color = randomcolor()
+ let color = randomcolor()
// make sure color not duplicated or reach max random count
if (notes[noteId]) {
- var randomcount = 0
- var maxrandomcount = 10
- var found = false
+ let randomcount = 0
+ const maxrandomcount = 10
+ let found = false
do {
Object.keys(notes[noteId].users).forEach(function (userId) {
if (notes[noteId].users[userId].color === color) {
@@ -758,8 +761,8 @@ function connection (socket) {
// received user status
socket.on('user status', function (data) {
- var noteId = socket.noteId
- var user = users[socket.id]
+ const noteId = socket.noteId
+ const user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
logger.debug(`SERVER received [${noteId}] user status from [${socket.id}]: ${JSON.stringify(data)}`)
if (data) {
@@ -773,9 +776,9 @@ function connection (socket) {
socket.on('permission', function (permission) {
// need login to do more actions
if (socket.request.user && socket.request.user.logged_in) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var note = notes[noteId]
+ const note = notes[noteId]
// Only owner can change permission
if (note.owner && note.owner === socket.request.user.id) {
if (permission === 'freely' && !config.allowAnonymous && !config.allowAnonymousEdits) return
@@ -790,12 +793,12 @@ function connection (socket) {
if (!count) {
return
}
- var out = {
+ const out = {
permission: permission
}
realtime.io.to(note.id).emit('permission', out)
- for (var i = 0, l = note.socks.length; i < l; i++) {
- var sock = note.socks[i]
+ for (let i = 0, l = note.socks.length; i < l; i++) {
+ const sock = note.socks[i]
if (typeof sock !== 'undefined' && sock) {
// check view permission
if (!checkViewPermission(sock.request, note)) {
@@ -819,9 +822,9 @@ function connection (socket) {
socket.on('delete', function () {
// need login to do more actions
if (socket.request.user && socket.request.user.logged_in) {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var note = notes[noteId]
+ const note = notes[noteId]
// Only owner can delete note
if (note.owner && note.owner === socket.request.user.id) {
models.Note.destroy({
@@ -830,8 +833,8 @@ function connection (socket) {
}
}).then(function (count) {
if (!count) return
- for (var i = 0, l = note.socks.length; i < l; i++) {
- var sock = note.socks[i]
+ for (let i = 0, l = note.socks.length; i < l; i++) {
+ const sock = note.socks[i]
if (typeof sock !== 'undefined' && sock) {
sock.emit('delete')
setTimeout(function () {
@@ -849,9 +852,9 @@ function connection (socket) {
// reveiced when user logout or changed
socket.on('user changed', function () {
logger.info('user changed')
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var user = notes[noteId].users[socket.id]
+ const user = notes[noteId].users[socket.id]
if (!user) return
updateUserData(socket, user)
emitOnlineUsers(socket)
@@ -859,14 +862,14 @@ function connection (socket) {
// received sync of online users request
socket.on('online users', function () {
- var noteId = socket.noteId
+ const noteId = socket.noteId
if (!noteId || !notes[noteId]) return
- var users = []
+ const users = []
Object.keys(notes[noteId].users).forEach(function (key) {
- var user = notes[noteId].users[key]
+ const user = notes[noteId].users[key]
if (user) { users.push(buildUserOutData(user)) }
})
- var out = {
+ const out = {
users: users
}
socket.emit('online users', out)
@@ -882,31 +885,31 @@ function connection (socket) {
// received cursor focus
socket.on('cursor focus', function (data) {
- var noteId = socket.noteId
- var user = users[socket.id]
+ const noteId = socket.noteId
+ const user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = data
- var out = buildUserOutData(user)
+ const out = buildUserOutData(user)
socket.broadcast.to(noteId).emit('cursor focus', out)
})
// received cursor activity
socket.on('cursor activity', function (data) {
- var noteId = socket.noteId
- var user = users[socket.id]
+ const noteId = socket.noteId
+ const user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = data
- var out = buildUserOutData(user)
+ const out = buildUserOutData(user)
socket.broadcast.to(noteId).emit('cursor activity', out)
})
// received cursor blur
socket.on('cursor blur', function () {
- var noteId = socket.noteId
- var user = users[socket.id]
+ const noteId = socket.noteId
+ const user = users[socket.id]
if (!noteId || !notes[noteId] || !user) return
user.cursor = null
- var out = {
+ const out = {
id: socket.id
}
socket.broadcast.to(noteId).emit('cursor blur', out)
diff --git a/lib/response.js b/lib/response.js
index a56273a2..10ecd035 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -1,28 +1,28 @@
'use strict'
// response
// external modules
-var fs = require('fs')
-var path = require('path')
-var request = require('request')
+const fs = require('fs')
+const path = require('path')
+const request = require('request')
// core
-var config = require('./config')
-var logger = require('./logger')
-var models = require('./models')
+const config = require('./config')
+const logger = require('./logger')
+const models = require('./models')
const noteUtil = require('./web/note/util')
const errors = require('./errors')
// public
-var response = {
+const response = {
showIndex: showIndex,
githubActions: githubActions,
gitlabActions: gitlabActions
}
function showIndex (req, res, next) {
- var authStatus = req.isAuthenticated()
- var deleteToken = ''
+ const authStatus = req.isAuthenticated()
+ const deleteToken = ''
- var data = {
+ const data = {
signin: authStatus,
infoMessage: req.flash('info'),
errorMessage: req.flash('error'),
@@ -49,9 +49,9 @@ function showIndex (req, res, next) {
}
function githubActions (req, res, next) {
- var noteId = req.params.noteId
+ const noteId = req.params.noteId
noteUtil.findNote(req, res, function (note) {
- var action = req.params.action
+ const action = req.params.action
switch (action) {
case 'gist':
githubActionGist(req, res, note)
@@ -64,41 +64,41 @@ function githubActions (req, res, next) {
}
function githubActionGist (req, res, note) {
- var code = req.query.code
- var state = req.query.state
+ const code = req.query.code
+ const state = req.query.state
if (!code || !state) {
return errors.errorForbidden(res)
} else {
- var data = {
+ const data = {
client_id: config.github.clientID,
client_secret: config.github.clientSecret,
code: code,
state: state
}
- var authUrl = 'https://github.com/login/oauth/access_token'
+ const authUrl = 'https://github.com/login/oauth/access_token'
request({
url: authUrl,
method: 'POST',
json: data
}, function (error, httpResponse, body) {
if (!error && httpResponse.statusCode === 200) {
- var accessToken = body.access_token
+ const accessToken = body.access_token
if (accessToken) {
- var content = note.content
- var title = models.Note.decodeTitle(note.title)
- var filename = title.replace('/', ' ') + '.md'
- var gist = {
- 'files': {}
+ const content = note.content
+ const title = models.Note.decodeTitle(note.title)
+ const filename = title.replace('/', ' ') + '.md'
+ const gist = {
+ files: {}
}
gist.files[filename] = {
- 'content': content
+ content: content
}
- var gistUrl = 'https://api.github.com/gists'
+ const gistUrl = 'https://api.github.com/gists'
request({
url: gistUrl,
headers: {
'User-Agent': 'HedgeDoc',
- 'Authorization': 'token ' + accessToken
+ Authorization: 'token ' + accessToken
},
method: 'POST',
json: gist
@@ -121,9 +121,9 @@ function githubActionGist (req, res, note) {
}
function gitlabActions (req, res, next) {
- var noteId = req.params.noteId
+ const noteId = req.params.noteId
noteUtil.findNote(req, res, function (note) {
- var action = req.params.action
+ const action = req.params.action
switch (action) {
case 'projects':
gitlabActionProjects(req, res, note)
@@ -143,7 +143,7 @@ function gitlabActionProjects (req, res, note) {
}
}).then(function (user) {
if (!user) { return errors.errorNotFound(res) }
- var ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
+ const ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
ret.accesstoken = user.accessToken
ret.profileid = user.profileid
request(
diff --git a/lib/utils.js b/lib/utils.js
index 23873ffc..44ff8892 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -5,7 +5,7 @@ exports.isSQLite = function isSQLite (sequelize) {
}
exports.getImageMimeType = function getImageMimeType (imagePath) {
- var fileExtension = /[^.]+$/.exec(imagePath)
+ const fileExtension = /[^.]+$/.exec(imagePath)
switch (fileExtension[0].toLowerCase()) {
case 'bmp':
diff --git a/lib/web/auth/dropbox/index.js b/lib/web/auth/dropbox/index.js
index aef011cb..c35f04e3 100644
--- a/lib/web/auth/dropbox/index.js
+++ b/lib/web/auth/dropbox/index.js
@@ -6,7 +6,7 @@ const DropboxStrategy = require('passport-dropbox-oauth2').Strategy
const config = require('../../../config')
const { passportGeneralCallback } = require('../utils')
-let dropboxAuth = module.exports = Router()
+const dropboxAuth = module.exports = Router()
passport.use(new DropboxStrategy({
apiVersion: '2',
diff --git a/lib/web/auth/email/index.js b/lib/web/auth/email/index.js
index 78ca933b..74922966 100644
--- a/lib/web/auth/email/index.js
+++ b/lib/web/auth/email/index.js
@@ -10,7 +10,7 @@ const logger = require('../../../logger')
const { urlencodedParser } = require('../../utils')
const errors = require('../../../errors')
-let emailAuth = module.exports = Router()
+const emailAuth = module.exports = Router()
passport.use(new LocalStrategy({
usernameField: 'email'
diff --git a/lib/web/auth/facebook/index.js b/lib/web/auth/facebook/index.js
index 0ba948bb..acf566eb 100644
--- a/lib/web/auth/facebook/index.js
+++ b/lib/web/auth/facebook/index.js
@@ -7,7 +7,7 @@ const FacebookStrategy = require('passport-facebook').Strategy
const config = require('../../../config')
const { passportGeneralCallback } = require('../utils')
-let facebookAuth = module.exports = Router()
+const facebookAuth = module.exports = Router()
passport.use(new FacebookStrategy({
clientID: config.facebook.clientID,
diff --git a/lib/web/auth/github/index.js b/lib/web/auth/github/index.js
index 3a3a84c6..c7f7e5d1 100644
--- a/lib/web/auth/github/index.js
+++ b/lib/web/auth/github/index.js
@@ -7,7 +7,7 @@ const config = require('../../../config')
const response = require('../../../response')
const { passportGeneralCallback } = require('../utils')
-let githubAuth = module.exports = Router()
+const githubAuth = module.exports = Router()
passport.use(new GithubStrategy({
clientID: config.github.clientID,
diff --git a/lib/web/auth/gitlab/index.js b/lib/web/auth/gitlab/index.js
index 1b628e81..11579bd1 100644
--- a/lib/web/auth/gitlab/index.js
+++ b/lib/web/auth/gitlab/index.js
@@ -7,7 +7,7 @@ const config = require('../../../config')
const response = require('../../../response')
const { passportGeneralCallback } = require('../utils')
-let gitlabAuth = module.exports = Router()
+const gitlabAuth = module.exports = Router()
passport.use(new GitlabStrategy({
baseURL: config.gitlab.baseURL,
diff --git a/lib/web/auth/google/index.js b/lib/web/auth/google/index.js
index 6edf07a9..0262dedf 100644
--- a/lib/web/auth/google/index.js
+++ b/lib/web/auth/google/index.js
@@ -2,11 +2,11 @@
const Router = require('express').Router
const passport = require('passport')
-var GoogleStrategy = require('passport-google-oauth20').Strategy
+const GoogleStrategy = require('passport-google-oauth20').Strategy
const config = require('../../../config')
const { passportGeneralCallback } = require('../utils')
-let googleAuth = module.exports = Router()
+const googleAuth = module.exports = Router()
passport.use(new GoogleStrategy({
clientID: config.google.clientID,
diff --git a/lib/web/auth/ldap/index.js b/lib/web/auth/ldap/index.js
index b501106d..4142194f 100644
--- a/lib/web/auth/ldap/index.js
+++ b/lib/web/auth/ldap/index.js
@@ -9,7 +9,7 @@ const logger = require('../../../logger')
const { urlencodedParser } = require('../../utils')
const errors = require('../../../errors')
-let ldapAuth = module.exports = Router()
+const ldapAuth = module.exports = Router()
passport.use(new LDAPStrategy({
server: {
@@ -22,7 +22,7 @@ passport.use(new LDAPStrategy({
tlsOptions: config.ldap.tlsOptions || null
}
}, function (user, done) {
- var uuid = user.uidNumber || user.uid || user.sAMAccountName || undefined
+ let uuid = user.uidNumber || user.uid || user.sAMAccountName || undefined
if (config.ldap.useridField && user[config.ldap.useridField]) {
uuid = user[config.ldap.useridField]
}
@@ -34,12 +34,12 @@ passport.use(new LDAPStrategy({
'"useridField" option in ldap settings.')
}
- var username = uuid
+ let username = uuid
if (config.ldap.usernameField && user[config.ldap.usernameField]) {
username = user[config.ldap.usernameField]
}
- var profile = {
+ const profile = {
id: 'LDAP-' + uuid,
username: username,
displayName: user.displayName,
@@ -48,7 +48,7 @@ passport.use(new LDAPStrategy({
profileUrl: null,
provider: 'ldap'
}
- var stringifiedProfile = JSON.stringify(profile)
+ const stringifiedProfile = JSON.stringify(profile)
models.User.findOrCreate({
where: {
profileid: profile.id.toString()
@@ -58,7 +58,7 @@ passport.use(new LDAPStrategy({
}
}).spread(function (user, created) {
if (user) {
- var needSave = false
+ let needSave = false
if (user.profile !== stringifiedProfile) {
user.profile = stringifiedProfile
needSave = true
diff --git a/lib/web/auth/mattermost/index.js b/lib/web/auth/mattermost/index.js
index 78eca2af..2f15c812 100644
--- a/lib/web/auth/mattermost/index.js
+++ b/lib/web/auth/mattermost/index.js
@@ -9,9 +9,9 @@ const { passportGeneralCallback } = require('../utils')
const mattermost = new Mattermost.Client()
-let mattermostAuth = module.exports = Router()
+const mattermostAuth = module.exports = Router()
-let mattermostStrategy = new OAuthStrategy({
+const mattermostStrategy = new OAuthStrategy({
authorizationURL: config.mattermost.baseURL + '/oauth/authorize',
tokenURL: config.mattermost.baseURL + '/oauth/access_token',
clientID: config.mattermost.clientID,
diff --git a/lib/web/auth/oauth2/index.js b/lib/web/auth/oauth2/index.js
index 9cb17f26..e9032e0b 100644
--- a/lib/web/auth/oauth2/index.js
+++ b/lib/web/auth/oauth2/index.js
@@ -7,7 +7,7 @@ const config = require('../../../config')
const logger = require('../../../logger')
const { passportGeneralCallback } = require('../utils')
-let oauth2Auth = module.exports = Router()
+const oauth2Auth = module.exports = Router()
class OAuth2CustomStrategy extends Strategy {
constructor (options, verify) {
@@ -20,7 +20,7 @@ class OAuth2CustomStrategy extends Strategy {
userProfile (accessToken, done) {
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
- var json
+ let json
if (err) {
return done(new InternalOAuthError('Failed to fetch user profile', err))
@@ -33,7 +33,7 @@ class OAuth2CustomStrategy extends Strategy {
}
checkAuthorization(json, done)
- let profile = parseProfile(json)
+ const profile = parseProfile(json)
profile.provider = 'oauth2'
done(null, profile)
@@ -91,7 +91,7 @@ function checkAuthorization (data, done) {
OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) {
- var json
+ let json
if (err) {
return done(new InternalOAuthError('Failed to fetch user profile', err))
@@ -104,7 +104,7 @@ OAuth2CustomStrategy.prototype.userProfile = function (accessToken, done) {
}
checkAuthorization(json, done)
- let profile = parseProfile(json)
+ const profile = parseProfile(json)
profile.provider = 'oauth2'
done(null, profile)
diff --git a/lib/web/auth/openid/index.js b/lib/web/auth/openid/index.js
index 28e164f5..84d0970c 100644
--- a/lib/web/auth/openid/index.js
+++ b/lib/web/auth/openid/index.js
@@ -8,14 +8,14 @@ const models = require('../../../models')
const logger = require('../../../logger')
const { urlencodedParser } = require('../../utils')
-let openIDAuth = module.exports = Router()
+const openIDAuth = module.exports = Router()
passport.use(new OpenIDStrategy({
returnURL: config.serverURL + '/auth/openid/callback',
realm: config.serverURL,
profile: true
}, function (openid, profile, done) {
- var stringifiedProfile = JSON.stringify(profile)
+ const stringifiedProfile = JSON.stringify(profile)
models.User.findOrCreate({
where: {
profileid: openid
@@ -25,7 +25,7 @@ passport.use(new OpenIDStrategy({
}
}).spread(function (user, created) {
if (user) {
- var needSave = false
+ let needSave = false
if (user.profile !== stringifiedProfile) {
user.profile = stringifiedProfile
needSave = true
diff --git a/lib/web/auth/saml/index.js b/lib/web/auth/saml/index.js
index c48b93e2..deb04007 100644
--- a/lib/web/auth/saml/index.js
+++ b/lib/web/auth/saml/index.js
@@ -10,19 +10,21 @@ const { urlencodedParser } = require('../../utils')
const fs = require('fs')
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({
callbackUrl: config.serverURL + '/auth/saml/callback',
entryPoint: config.saml.idpSsoUrl,
issuer: config.saml.issuer || config.serverURL,
- privateCert: config.saml.clientCert === undefined ? undefined : (function () {
- try {
- return fs.readFileSync(config.saml.clientCert, 'utf-8')
- } catch (e) {
- logger.error(`SAML client certificate: ${e.message}`)
- }
- }()),
+ privateCert: config.saml.clientCert === undefined
+ ? undefined
+ : (function () {
+ try {
+ return fs.readFileSync(config.saml.clientCert, 'utf-8')
+ } catch (e) {
+ logger.error(`SAML client certificate: ${e.message}`)
+ }
+ }()),
cert: (function () {
try {
return fs.readFileSync(config.saml.idpCert, 'utf-8')
@@ -36,7 +38,7 @@ passport.use(new SamlStrategy({
}, function (user, done) {
// check authorization if needed
if (config.saml.externalGroups && config.saml.groupAttribute) {
- var externalGroups = intersection(config.saml.externalGroups, user[config.saml.groupAttribute])
+ const externalGroups = intersection(config.saml.externalGroups, user[config.saml.groupAttribute])
if (externalGroups.length > 0) {
logger.error('saml permission denied: ' + externalGroups.join(', '))
return done('Permission denied', null)
@@ -49,8 +51,8 @@ passport.use(new SamlStrategy({
}
}
// user creation
- var uuid = user[config.saml.attribute.id] || user.nameID
- var profile = {
+ const uuid = user[config.saml.attribute.id] || user.nameID
+ const profile = {
provider: 'saml',
id: 'SAML-' + uuid,
username: user[config.saml.attribute.username] || user.nameID,
@@ -59,7 +61,7 @@ passport.use(new SamlStrategy({
if (profile.emails.length === 0 && config.saml.identifierFormat === 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress') {
profile.emails.push(user.nameID)
}
- var stringifiedProfile = JSON.stringify(profile)
+ const stringifiedProfile = JSON.stringify(profile)
models.User.findOrCreate({
where: {
profileid: profile.id.toString()
@@ -69,7 +71,7 @@ passport.use(new SamlStrategy({
}
}).spread(function (user, created) {
if (user) {
- var needSave = false
+ let needSave = false
if (user.profile !== stringifiedProfile) {
user.profile = stringifiedProfile
needSave = true
diff --git a/lib/web/auth/twitter/index.js b/lib/web/auth/twitter/index.js
index 56389f84..76744e09 100644
--- a/lib/web/auth/twitter/index.js
+++ b/lib/web/auth/twitter/index.js
@@ -7,7 +7,7 @@ const TwitterStrategy = require('passport-twitter').Strategy
const config = require('../../../config')
const { passportGeneralCallback } = require('../utils')
-let twitterAuth = module.exports = Router()
+const twitterAuth = module.exports = Router()
passport.use(new TwitterStrategy({
consumerKey: config.twitter.consumerKey,
diff --git a/lib/web/auth/utils.js b/lib/web/auth/utils.js
index fb69f08c..bb69f15f 100644
--- a/lib/web/auth/utils.js
+++ b/lib/web/auth/utils.js
@@ -4,7 +4,7 @@ const models = require('../../models')
const logger = require('../../logger')
exports.passportGeneralCallback = function callback (accessToken, refreshToken, profile, done) {
- var stringifiedProfile = JSON.stringify(profile)
+ const stringifiedProfile = JSON.stringify(profile)
models.User.findOrCreate({
where: {
profileid: profile.id.toString()
@@ -16,7 +16,7 @@ exports.passportGeneralCallback = function callback (accessToken, refreshToken,
}
}).spread(function (user, created) {
if (user) {
- var needSave = false
+ let needSave = false
if (user.profile !== stringifiedProfile) {
user.profile = stringifiedProfile
needSave = true
diff --git a/lib/web/imageRouter/azure.js b/lib/web/imageRouter/azure.js
index 22ee5585..c56ac860 100644
--- a/lib/web/imageRouter/azure.js
+++ b/lib/web/imageRouter/azure.js
@@ -17,7 +17,7 @@ exports.uploadImage = function (imagePath, callback) {
return
}
- var azureBlobService = azure.createBlobService(config.azure.connectionString)
+ const azureBlobService = azure.createBlobService(config.azure.connectionString)
azureBlobService.createContainerIfNotExists(config.azure.container, { publicAccessLevel: 'blob' }, function (err, result, response) {
if (err) {
diff --git a/lib/web/imageRouter/index.js b/lib/web/imageRouter/index.js
index afa9bbf6..0a72c65c 100644
--- a/lib/web/imageRouter/index.js
+++ b/lib/web/imageRouter/index.js
@@ -12,20 +12,28 @@ const config = require('../../config')
const logger = require('../../logger')
const errors = require('../../errors')
-const imageRouter = module.exports = Router()
+const imageRouter = (module.exports = Router())
async function checkUploadType (filePath) {
const typeFromMagic = await FileType.fromFile(filePath)
if (typeFromMagic === undefined) {
- logger.error(`Image upload error: Could not determine MIME-type`)
+ logger.error('Image upload error: Could not determine MIME-type')
return false
}
if (path.extname(filePath) !== '.' + typeFromMagic.ext) {
- logger.error(`Image upload error: Provided file extension does not match MIME-type`)
+ logger.error(
+ 'Image upload error: Provided file extension does not match MIME-type'
+ )
return false
}
if (!config.allowedUploadMimeTypes.includes(typeFromMagic.mime)) {
- logger.error(`Image upload error: MIME-type "${typeFromMagic.mime}" of uploaded file not allowed, only "${config.allowedUploadMimeTypes.join(', ')}" are allowed`)
+ logger.error(
+ `Image upload error: MIME-type "${
+ typeFromMagic.mime
+ }" of uploaded file not allowed, only "${config.allowedUploadMimeTypes.join(
+ ', '
+ )}" are allowed`
+ )
return false
}
return true
@@ -33,12 +41,18 @@ async function checkUploadType (filePath) {
// upload image
imageRouter.post('/uploadimage', function (req, res) {
- if (!req.isAuthenticated() && !config.allowAnonymous && !config.allowAnonymousEdits) {
- logger.error(`Image upload error: Anonymous edits and therefore uploads are not allowed)`)
+ if (
+ !req.isAuthenticated() &&
+ !config.allowAnonymous &&
+ !config.allowAnonymousEdits
+ ) {
+ logger.error(
+ 'Image upload error: Anonymous edits and therefore uploads are not allowed'
+ )
return errors.errorForbidden(res)
}
- var form = new formidable.IncomingForm()
+ const form = new formidable.IncomingForm()
form.keepExtensions = true
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hedgedoc-'))
form.uploadDir = tmpDir
@@ -49,17 +63,21 @@ imageRouter.post('/uploadimage', function (req, res) {
rimraf(tmpDir)
return errors.errorForbidden(res)
} else if (!files.image || !files.image.path) {
- logger.error(`Image upload error: Upload didn't contain file)`)
+ logger.error("Image upload error: Upload didn't contain file)")
rimraf.sync(tmpDir)
return errors.errorBadRequest(res)
- } else if (!await checkUploadType(files.image.path)) {
+ } else if (!(await checkUploadType(files.image.path))) {
rimraf.sync(tmpDir)
return errors.errorBadRequest(res)
} else {
- logger.debug(`SERVER received uploadimage: ${JSON.stringify(files.image)}`)
+ logger.debug(
+ `SERVER received uploadimage: ${JSON.stringify(files.image)}`
+ )
const uploadProvider = require('./' + config.imageUploadType)
- logger.debug(`imageRouter: Uploading ${files.image.path} using ${config.imageUploadType}`)
+ logger.debug(
+ `imageRouter: Uploading ${files.image.path} using ${config.imageUploadType}`
+ )
uploadProvider.uploadImage(files.image.path, function (err, url) {
rimraf.sync(tmpDir)
if (err !== null) {
diff --git a/lib/web/imageRouter/minio.js b/lib/web/imageRouter/minio.js
index 91de5ff1..3ced94e2 100644
--- a/lib/web/imageRouter/minio.js
+++ b/lib/web/imageRouter/minio.js
@@ -32,16 +32,16 @@ exports.uploadImage = function (imagePath, callback) {
return
}
- let key = path.join('uploads', path.basename(imagePath))
- let protocol = config.minio.secure ? 'https' : 'http'
+ const key = path.join('uploads', path.basename(imagePath))
+ const protocol = config.minio.secure ? 'https' : 'http'
minioClient.putObject(config.s3bucket, key, buffer, buffer.size, getImageMimeType(imagePath), function (err, data) {
if (err) {
callback(new Error(err), null)
return
}
- let hidePort = [80, 443].includes(config.minio.port)
- let urlPort = hidePort ? '' : `:${config.minio.port}`
+ const hidePort = [80, 443].includes(config.minio.port)
+ const urlPort = hidePort ? '' : `:${config.minio.port}`
callback(null, `${protocol}://${config.minio.endPoint}${urlPort}/${config.s3bucket}/${key}`)
})
})
diff --git a/lib/web/imageRouter/s3.js b/lib/web/imageRouter/s3.js
index 2bf08cc7..5bb8e160 100644
--- a/lib/web/imageRouter/s3.js
+++ b/lib/web/imageRouter/s3.js
@@ -26,7 +26,7 @@ exports.uploadImage = function (imagePath, callback) {
callback(new Error(err), null)
return
}
- let params = {
+ const params = {
Bucket: config.s3bucket,
Key: path.join('uploads', path.basename(imagePath)),
Body: buffer
diff --git a/lib/web/statusRouter.js b/lib/web/statusRouter.js
index febe2df3..d939a3fe 100644
--- a/lib/web/statusRouter.js
+++ b/lib/web/statusRouter.js
@@ -25,11 +25,11 @@ statusRouter.get('/status', function (req, res, next) {
})
// get status
statusRouter.get('/temp', function (req, res) {
- var host = req.get('host')
+ const host = req.get('host')
if (config.allowOrigin.indexOf(host) === -1) {
errors.errorForbidden(res)
} else {
- var tempid = req.query.tempid
+ const tempid = req.query.tempid
if (!tempid) {
errors.errorForbidden(res)
} else {
@@ -60,11 +60,11 @@ statusRouter.get('/temp', function (req, res) {
})
// post status
statusRouter.post('/temp', urlencodedParser, function (req, res) {
- var host = req.get('host')
+ const host = req.get('host')
if (config.allowOrigin.indexOf(host) === -1) {
errors.errorForbidden(res)
} else {
- var data = req.body.data
+ const data = req.body.data
if (!data) {
errors.errorForbidden(res)
} else {
@@ -90,7 +90,7 @@ statusRouter.post('/temp', urlencodedParser, function (req, res) {
})
statusRouter.get('/config', function (req, res) {
- var data = {
+ const data = {
domain: config.domain,
urlpath: config.urlPath,
debug: config.debug,
diff --git a/lib/web/userRouter.js b/lib/web/userRouter.js
index f1f999f1..117668fa 100644
--- a/lib/web/userRouter.js
+++ b/lib/web/userRouter.js
@@ -21,7 +21,7 @@ UserRouter.get('/me', function (req, res) {
}
}).then(function (user) {
if (!user) { return errors.errorNotFound(res) }
- var profile = models.User.getProfile(user)
+ const profile = models.User.getProfile(user)
res.send({
status: 'ok',
id: req.user.id,
@@ -70,7 +70,7 @@ UserRouter.get('/me/delete/:token?', function (req, res) {
UserRouter.get('/me/export', function (req, res) {
if (req.isAuthenticated()) {
// let output = fs.createWriteStream(__dirname + '/example.zip');
- let archive = archiver('zip', {
+ const archive = archiver('zip', {
zlib: { level: 3 } // Sets the compression level.
})
res.setHeader('Content-Type', 'application/zip')
@@ -90,13 +90,13 @@ UserRouter.get('/me/export', function (req, res) {
ownerId: user.id
}
}).then(function (notes) {
- let filenames = {}
+ const filenames = {}
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 suffix = ''
do {
- let seperator = typeof suffix === 'number' ? '-' : ''
+ const seperator = typeof suffix === 'number' ? '-' : ''
filename = basename + seperator + suffix + '.md'
suffix++
} while (filenames[filename])
diff --git a/lib/workers/dmpWorker.js b/lib/workers/dmpWorker.js
index ca68b4ab..7b5439c7 100644
--- a/lib/workers/dmpWorker.js
+++ b/lib/workers/dmpWorker.js
@@ -1,10 +1,10 @@
'use strict'
// external modules
-var DiffMatchPatch = require('diff-match-patch')
-var dmp = new DiffMatchPatch()
+const DiffMatchPatch = require('diff-match-patch')
+const dmp = new DiffMatchPatch()
// core
-var logger = require('../logger')
+const logger = require('../logger')
process.on('message', function (data) {
if (!data || !data.msg || !data.cacheKey) {
@@ -12,11 +12,16 @@ process.on('message', function (data) {
}
switch (data.msg) {
case 'create patch':
- if (!data.hasOwnProperty('lastDoc') || !data.hasOwnProperty('currDoc')) {
- return logger.error('dmp worker error: not enough data on create patch')
+ if (
+ !Object.prototype.hasOwnProperty.call(data, 'lastDoc') ||
+ !Object.prototype.hasOwnProperty.call(data, 'currDoc')
+ ) {
+ return logger.error(
+ 'dmp worker error: not enough data on create patch'
+ )
}
try {
- var patch = createPatch(data.lastDoc, data.currDoc)
+ const patch = createPatch(data.lastDoc, data.currDoc)
process.send({
msg: 'check',
result: patch,
@@ -32,11 +37,16 @@ process.on('message', function (data) {
}
break
case 'get revision':
- if (!data.hasOwnProperty('revisions') || !data.hasOwnProperty('count')) {
- return logger.error('dmp worker error: not enough data on get revision')
+ if (
+ !Object.prototype.hasOwnProperty.call(data, 'revisions') ||
+ !Object.prototype.hasOwnProperty.call(data, 'count')
+ ) {
+ return logger.error(
+ 'dmp worker error: not enough data on get revision'
+ )
}
try {
- var result = getRevision(data.revisions, data.count)
+ const result = getRevision(data.revisions, data.count)
process.send({
msg: 'check',
result: result,
@@ -55,31 +65,31 @@ process.on('message', function (data) {
})
function createPatch (lastDoc, currDoc) {
- var msStart = (new Date()).getTime()
- var diff = dmp.diff_main(lastDoc, currDoc)
- var patch = dmp.patch_make(lastDoc, diff)
+ const msStart = new Date().getTime()
+ const diff = dmp.diff_main(lastDoc, currDoc)
+ let patch = dmp.patch_make(lastDoc, diff)
patch = dmp.patch_toText(patch)
- var msEnd = (new Date()).getTime()
+ const msEnd = new Date().getTime()
logger.debug(patch)
- logger.debug((msEnd - msStart) + 'ms')
+ logger.debug(msEnd - msStart + 'ms')
return patch
}
function getRevision (revisions, count) {
- var msStart = (new Date()).getTime()
- var startContent = null
- var lastPatch = []
- var applyPatches = []
- var authorship = []
+ const msStart = new Date().getTime()
+ let startContent = null
+ let lastPatch = []
+ let applyPatches = []
+ let authorship = []
if (count <= Math.round(revisions.length / 2)) {
// start from top to target
for (let i = 0; i < count; i++) {
- let revision = revisions[i]
+ const revision = revisions[i]
if (i === 0) {
startContent = revision.content || revision.lastContent
}
if (i !== count - 1) {
- let patch = dmp.patch_fromText(revision.patch)
+ const patch = dmp.patch_fromText(revision.patch)
applyPatches = applyPatches.concat(patch)
}
lastPatch = revision.patch
@@ -88,21 +98,25 @@ function getRevision (revisions, count) {
// swap DIFF_INSERT and DIFF_DELETE to achieve unpatching
for (let i = 0, l = applyPatches.length; i < l; i++) {
for (let j = 0, m = applyPatches[i].diffs.length; j < m; j++) {
- var diff = applyPatches[i].diffs[j]
- if (diff[0] === DiffMatchPatch.DIFF_INSERT) { diff[0] = DiffMatchPatch.DIFF_DELETE } else if (diff[0] === DiffMatchPatch.DIFF_DELETE) { diff[0] = DiffMatchPatch.DIFF_INSERT }
+ const diff = applyPatches[i].diffs[j]
+ if (diff[0] === DiffMatchPatch.DIFF_INSERT) {
+ diff[0] = DiffMatchPatch.DIFF_DELETE
+ } else if (diff[0] === DiffMatchPatch.DIFF_DELETE) {
+ diff[0] = DiffMatchPatch.DIFF_INSERT
+ }
}
}
} else {
// start from bottom to target
- var l = revisions.length - 1
- for (var i = l; i >= count - 1; i--) {
- let revision = revisions[i]
+ const l = revisions.length - 1
+ for (let i = l; i >= count - 1; i--) {
+ const revision = revisions[i]
if (i === l) {
startContent = revision.lastContent
authorship = revision.authorship
}
if (revision.patch) {
- let patch = dmp.patch_fromText(revision.patch)
+ const patch = dmp.patch_fromText(revision.patch)
applyPatches = applyPatches.concat(patch)
}
lastPatch = revision.patch
@@ -110,18 +124,18 @@ function getRevision (revisions, count) {
}
}
try {
- var finalContent = dmp.patch_apply(applyPatches, startContent)[0]
+ const finalContent = dmp.patch_apply(applyPatches, startContent)[0]
+ const data = {
+ content: finalContent,
+ patch: dmp.patch_fromText(lastPatch),
+ authorship: authorship
+ }
+ const msEnd = new Date().getTime()
+ logger.debug(msEnd - msStart + 'ms')
+ return data
} catch (err) {
throw new Error(err)
}
- var data = {
- content: finalContent,
- patch: dmp.patch_fromText(lastPatch),
- authorship: authorship
- }
- var msEnd = (new Date()).getTime()
- logger.debug((msEnd - msStart) + 'ms')
- return data
}
// log uncaught exception
diff --git a/public/.eslintrc.js b/public/.eslintrc.js
index dc37b3cb..77cd2c0d 100644
--- a/public/.eslintrc.js
+++ b/public/.eslintrc.js
@@ -1,28 +1,28 @@
// this config file is used in concert with the root .eslintrc.js in the root dir.
module.exports = {
- "env": {
- "browser": true
+ env: {
+ browser: true
},
- "globals": {
- "$": false,
- "CodeMirror": false,
- "Cookies": false,
- "moment": false,
- "editor": false,
- "ui": false,
- "Spinner": false,
- "modeType": false,
- "Idle": false,
- "serverurl": false,
- "key": false,
- "gapi": false,
- "Dropbox": false,
- "FilePicker": false,
- "ot": false,
- "MediaUploader": false,
- "hex2rgb": false,
- "num_loaded": false,
- "Visibility": false,
- "inlineAttachment": false
+ globals: {
+ $: false,
+ CodeMirror: false,
+ Cookies: false,
+ moment: false,
+ editor: false,
+ ui: false,
+ Spinner: false,
+ modeType: false,
+ Idle: false,
+ serverurl: false,
+ key: false,
+ gapi: false,
+ Dropbox: false,
+ FilePicker: false,
+ ot: false,
+ MediaUploader: false,
+ hex2rgb: false,
+ num_loaded: false,
+ Visibility: false,
+ inlineAttachment: false
}
-};
+}
diff --git a/public/js/cover.js b/public/js/cover.js
index ed10afbf..bad92574 100644
--- a/public/js/cover.js
+++ b/public/js/cover.js
@@ -262,8 +262,8 @@ function updateItemFromNow () {
}
}
-var clearHistory = false
-var deleteId = null
+let clearHistory = false
+let deleteId = null
function deleteHistory () {
checkIfAuth(() => {
@@ -431,9 +431,9 @@ $('.search').keyup(() => {
// focus user field after opening login modal
$('.signin-modal').on('shown.bs.modal', function () {
- let fieldLDAP = $('input[name=username]')
- let fieldEmail = $('input[name=email]')
- let fieldOpenID = $('input[name=openid_identifier]')
+ const fieldLDAP = $('input[name=username]')
+ const fieldEmail = $('input[name=email]')
+ const fieldOpenID = $('input[name=openid_identifier]')
if (fieldLDAP.length === 1) {
fieldLDAP.focus()
} else if (fieldEmail.length === 1) {
diff --git a/public/js/extra.js b/public/js/extra.js
index 44db742a..7f06ebda 100644
--- a/public/js/extra.js
+++ b/public/js/extra.js
@@ -29,7 +29,7 @@ require('prismjs/components/prism-gherkin')
require('./lib/common/login')
require('./locale')
require('../vendor/md-toc')
-var Viz = require('viz.js')
+const Viz = require('viz.js')
const ui = getUIElements()
// auto update last change
@@ -314,8 +314,9 @@ export function finishView (view) {
// sequence diagram
const sequences = view.find('div.sequence-diagram.raw').removeClass('raw')
sequences.each((key, value) => {
+ let $value
try {
- var $value = $(value)
+ $value = $(value)
const $ele = $(value).parent().parent()
const sequence = $value
@@ -337,15 +338,16 @@ export function finishView (view) {
// flowchart
const flow = view.find('div.flow-chart.raw').removeClass('raw')
flow.each((key, value) => {
+ let $value
try {
- var $value = $(value)
+ $value = $(value)
const $ele = $(value).parent().parent()
const chart = window.flowchart.parse($value.text())
$value.html('')
chart.drawSVG(value, {
'line-width': 2,
- 'fill': 'none',
+ fill: 'none',
'font-size': '16px',
'font-family': "'Andale Mono', monospace"
})
@@ -359,13 +361,14 @@ export function finishView (view) {
}
})
// graphviz
- var graphvizs = view.find('div.graphviz.raw').removeClass('raw')
+ const graphvizs = view.find('div.graphviz.raw').removeClass('raw')
graphvizs.each(function (key, value) {
+ let $value
try {
- var $value = $(value)
- var $ele = $(value).parent().parent()
+ $value = $(value)
+ const $ele = $(value).parent().parent()
- var graphviz = Viz($value.text())
+ const graphviz = Viz($value.text())
if (!graphviz) throw Error('viz.js output empty graph')
$value.html(graphviz)
@@ -380,8 +383,9 @@ export function finishView (view) {
// mermaid
const mermaids = view.find('div.mermaid.raw').removeClass('raw')
mermaids.each((key, value) => {
+ let $value
try {
- var $value = $(value)
+ $value = $(value)
const $ele = $(value).closest('pre')
window.mermaid.mermaidAPI.parse($value.text())
@@ -389,7 +393,7 @@ export function finishView (view) {
$ele.text($value.text())
window.mermaid.init(undefined, $ele)
} catch (err) {
- var errormessage = err
+ let errormessage = err
if (err.str) {
errormessage = err.str
}
@@ -402,9 +406,10 @@ export function finishView (view) {
// abc.js
const abcs = view.find('div.abc.raw').removeClass('raw')
abcs.each((key, value) => {
+ let $value
try {
- var $value = $(value)
- var $ele = $(value).parent().parent()
+ $value = $(value)
+ const $ele = $(value).parent().parent()
window.ABCJS.renderAbc(value, $value.text())
@@ -493,7 +498,7 @@ export function finishView (view) {
let code = ''
if (codeDiv.length > 0) code = codeDiv.html()
else code = langDiv.html()
- var result
+ let result
if (!reallang) {
result = {
value: code
@@ -571,7 +576,7 @@ export function postProcess (code) {
}
// show yaml meta paring error
if (md.metaError) {
- var warning = result.find('div#meta-error')
+ let warning = result.find('div#meta-error')
if (warning && warning.length > 0) {
warning.text(md.metaError)
} else {
@@ -583,14 +588,14 @@ export function postProcess (code) {
}
window.postProcess = postProcess
-var domevents = Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(window))).filter(function (i) {
+const domevents = Object.getOwnPropertyNames(document).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(Object.getPrototypeOf(document)))).concat(Object.getOwnPropertyNames(Object.getPrototypeOf(window))).filter(function (i) {
return !i.indexOf('on') && (document[i] === null || typeof document[i] === 'function')
}).filter(function (elem, pos, self) {
return self.indexOf(elem) === pos
})
export function removeDOMEvents (view) {
- for (var i = 0, l = domevents.length; i < l; i++) {
+ for (let i = 0, l = domevents.length; i < l; i++) {
view.find('[' + domevents[i] + ']').removeAttr(domevents[i])
}
}
@@ -739,13 +744,13 @@ export function generateToc (id) {
const target = $(`#${id}`)
target.html('')
/* eslint-disable no-unused-vars */
- var toc = new window.Toc('doc', {
- 'level': 3,
- 'top': -1,
- 'class': 'toc',
- 'ulClass': 'nav',
- 'targetId': id,
- 'process': getHeaderContent
+ const toc = new window.Toc('doc', {
+ level: 3,
+ top: -1,
+ class: 'toc',
+ ulClass: 'nav',
+ targetId: id,
+ process: getHeaderContent
})
/* eslint-enable no-unused-vars */
if (target.text() === 'undefined') { target.html('') }
@@ -858,7 +863,7 @@ const linkifyAnchors = (level, containingElement) => {
const headers = containingElement.getElementsByTagName(`h${level}`)
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 (typeof header.id === 'undefined' || header.id === '') {
header.id = createHeaderId(getHeaderContent(header))
@@ -903,7 +908,7 @@ export function deduplicatedHeaderId (view) {
if (window.linkifyHeaderStyle === 'gfm') {
// consistent with GitHub, GitLab, Pandoc & co.
// all headers contained in the document, in order of appearance
- const allHeaders = view.find(`:header`).toArray()
+ const allHeaders = view.find(':header').toArray()
// list of finaly assigned header IDs
const headerIds = new Set()
for (let j = 0; j < allHeaders.length; j++) {
@@ -938,12 +943,12 @@ export function renderTOC (view) {
const target = $(`#${id}`)
target.html('')
/* eslint-disable no-unused-vars */
- let TOC = new window.Toc('doc', {
- 'level': 3,
- 'top': -1,
- 'class': 'toc',
- 'targetId': id,
- 'process': getHeaderContent
+ const TOC = new window.Toc('doc', {
+ level: 3,
+ top: -1,
+ class: 'toc',
+ targetId: id,
+ process: getHeaderContent
})
/* eslint-enable no-unused-vars */
if (target.text() === 'undefined') { target.html('') }
@@ -991,7 +996,7 @@ function highlightRender (code, lang) {
return result.value
}
-export let md = markdownit('default', {
+export const md = markdownit('default', {
html: true,
breaks: true,
langPrefix: '',
@@ -1044,7 +1049,7 @@ md.use(markdownitContainer, 'info', { render: renderContainer })
md.use(markdownitContainer, 'warning', { render: renderContainer })
md.use(markdownitContainer, 'danger', { render: renderContainer })
-let defaultImageRender = md.renderer.rules.image
+const defaultImageRender = md.renderer.rules.image
md.renderer.rules.image = function (tokens, idx, options, env, self) {
tokens[idx].attrJoin('class', 'raw')
return defaultImageRender(...arguments)
@@ -1203,7 +1208,8 @@ function meta (state, start, end, silent) {
if (!get(state, start).match(/^---$/)) return false
const data = []
- for (var line = start + 1; line < end; line++) {
+ let line
+ for (line = start + 1; line < end; line++) {
const str = get(state, line)
if (str.match(/^(\.{3}|-{3})$/)) break
if (state.tShift[line] < 0) break
diff --git a/public/js/history.js b/public/js/history.js
index e0154185..b8935eb3 100644
--- a/public/js/history.js
+++ b/public/js/history.js
@@ -147,7 +147,7 @@ export function writeHistory (title, tags) {
}
function writeHistoryToStorage (title, tags) {
- let data = store.get('notehistory')
+ const data = store.get('notehistory')
let notehistory
if (data && typeof data === 'string') {
notehistory = JSON.parse(data)
@@ -220,7 +220,7 @@ export function getStorageHistory (callback) {
if (typeof data === 'string') { data = JSON.parse(data) }
callback(data)
}
- // eslint-disable-next-line standard/no-callback-literal
+ // eslint-disable-next-line node/no-callback-literal
callback([])
}
@@ -263,7 +263,7 @@ function parseToHistory (list, notehistory, callback) {
for (let i = 0; i < notehistory.length; i++) {
// migrate LZString encoded id to base64url encoded id
try {
- let id = LZString.decompressFromBase64(notehistory[i].id)
+ const id = LZString.decompressFromBase64(notehistory[i].id)
if (id && checkNoteIdValid(id)) {
notehistory[i].id = encodeNoteId(id)
}
diff --git a/public/js/index.js b/public/js/index.js
index adc95461..03cae1b4 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -85,19 +85,49 @@ require('../css/site.css')
require('highlight.js/styles/github-gist.css')
-var defaultTextHeight = 20
-var viewportMargin = 20
-var defaultEditorMode = 'gfm'
-
-var idleTime = 300000 // 5 mins
-var updateViewDebounce = 100
-var cursorMenuThrottle = 50
-var cursorActivityDebounce = 50
-var cursorAnimatePeriod = 100
-var supportContainers = ['success', 'info', 'warning', 'danger']
-var supportCodeModes = ['javascript', 'typescript', 'jsx', 'htmlmixed', 'htmlembedded', 'css', 'xml', 'clike', 'clojure', 'ruby', 'python', 'shell', 'php', 'sql', 'haskell', 'coffeescript', 'yaml', 'pug', 'lua', 'cmake', 'nginx', 'perl', 'sass', 'r', 'dockerfile', 'tiddlywiki', 'mediawiki', 'go', 'gherkin'].concat(hljs.listLanguages())
-var supportCharts = ['sequence', 'flow', 'graphviz', 'mermaid', 'abc']
-var supportHeaders = [
+let defaultTextHeight = 20
+let viewportMargin = 20
+const defaultEditorMode = 'gfm'
+
+const idleTime = 300000 // 5 mins
+const updateViewDebounce = 100
+const cursorMenuThrottle = 50
+const cursorActivityDebounce = 50
+const cursorAnimatePeriod = 100
+const supportContainers = ['success', 'info', 'warning', 'danger']
+const supportCodeModes = [
+ 'javascript',
+ 'typescript',
+ 'jsx',
+ 'htmlmixed',
+ 'htmlembedded',
+ 'css',
+ 'xml',
+ 'clike',
+ 'clojure',
+ 'ruby',
+ 'python',
+ 'shell',
+ 'php',
+ 'sql',
+ 'haskell',
+ 'coffeescript',
+ 'yaml',
+ 'pug',
+ 'lua',
+ 'cmake',
+ 'nginx',
+ 'perl',
+ 'sass',
+ 'r',
+ 'dockerfile',
+ 'tiddlywiki',
+ 'mediawiki',
+ 'go',
+ 'gherkin'
+].concat(hljs.listLanguages())
+const supportCharts = ['sequence', 'flow', 'graphviz', 'mermaid', 'abc']
+const supportHeaders = [
{
text: '# h1',
search: '#'
@@ -225,7 +255,7 @@ const supportExtraTags = [
text: '[random color tag]',
search: '[]',
command: function () {
- var color = randomColor()
+ const color = randomColor()
return '[color=' + color + ']'
}
}
@@ -259,7 +289,7 @@ let visibleMD = false
let visibleLG = false
const isTouchDevice = 'ontouchstart' in document.documentElement
let currentStatus = statusType.offline
-let lastInfo = {
+const lastInfo = {
needRestore: false,
cursor: null,
scroll: null,
@@ -285,14 +315,14 @@ let lastInfo = {
let personalInfo = {}
let onlineUsers = []
const fileTypes = {
- 'pl': 'perl',
- 'cgi': 'perl',
- 'js': 'javascript',
- 'php': 'php',
- 'sh': 'bash',
- 'rb': 'ruby',
- 'html': 'html',
- 'py': 'python'
+ pl: 'perl',
+ cgi: 'perl',
+ js: 'javascript',
+ php: 'php',
+ sh: 'bash',
+ rb: 'ruby',
+ html: 'html',
+ py: 'python'
}
// editor settings
@@ -302,7 +332,7 @@ if (!textit) {
}
const editorInstance = new Editor()
-var editor = editorInstance.init(textit)
+const editor = editorInstance.init(textit)
// FIXME: global referncing in jquery-textcomplete patch
window.editor = editor
@@ -313,7 +343,7 @@ defaultTextHeight = parseInt($('.CodeMirror').css('line-height'))
const ui = getUIElements()
// page actions
-var opts = {
+const opts = {
lines: 11, // The number of lines to draw
length: 20, // The length of each line
width: 2, // The line thickness
@@ -333,11 +363,11 @@ var opts = {
}
/* eslint-disable no-unused-vars */
-var spinner = new Spinner(opts).spin(ui.spinner[0])
+const spinner = new Spinner(opts).spin(ui.spinner[0])
/* eslint-enable no-unused-vars */
// idle
-var idle = new Idle({
+const idle = new Idle({
onAway: function () {
idle.isAway = true
emitUserStatus()
@@ -356,7 +386,7 @@ ui.area.codemirror.on('touchstart', function () {
idle.onActive()
})
-var haveUnreadChanges = false
+let haveUnreadChanges = false
function setHaveUnreadChanges (bool) {
if (!window.loaded) return
@@ -379,7 +409,9 @@ function updateTitleReminder () {
function setRefreshModal (status) {
$('#refreshModal').modal('show')
$('#refreshModal').find('.modal-body > div').hide()
- $('#refreshModal').find('.' + status).show()
+ $('#refreshModal')
+ .find('.' + status)
+ .show()
}
function setNeedRefresh () {
@@ -395,9 +427,9 @@ setloginStateChangeEvent(function () {
})
// visibility
-var wasFocus = false
+let wasFocus = false
Visibility.change(function (e, state) {
- var hidden = Visibility.hidden()
+ const hidden = Visibility.hidden()
if (hidden) {
if (editorHasFocus()) {
wasFocus = true
@@ -421,7 +453,7 @@ $(document).ready(function () {
idle.checkAway()
checkResponsive()
// if in smaller screen, we don't need advanced scrollbar
- var scrollbarStyle
+ let scrollbarStyle
if (visibleXS) {
scrollbarStyle = 'native'
} else {
@@ -434,7 +466,7 @@ $(document).ready(function () {
checkEditorStyle()
/* cache dom references */
- var $body = $('body')
+ const $body = $('body')
/* we need this only on touch devices */
if (isTouchDevice) {
@@ -463,7 +495,9 @@ $(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip()
// shortcuts
// allow on all tags
- key.filter = function (e) { return true }
+ key.filter = function (e) {
+ return true
+ }
key('ctrl+alt+e', function (e) {
changeMode(modeType.edit)
})
@@ -488,13 +522,18 @@ $(window).resize(function () {
})
// when page unload
$(window).on('unload', function () {
-// updateHistoryInner();
+ // updateHistoryInner();
})
$(window).on('error', function () {
// setNeedRefresh();
})
-setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown, editor)
+setupSyncAreas(
+ ui.area.codemirrorScroll,
+ ui.area.view,
+ ui.area.markdown,
+ editor
+)
function autoSyncscroll () {
if (editorHasFocus()) {
@@ -504,8 +543,8 @@ function autoSyncscroll () {
}
}
-var windowResizeDebounce = 200
-var windowResize = _.debounce(windowResizeInner, windowResizeDebounce)
+const windowResizeDebounce = 200
+const windowResize = _.debounce(windowResizeInner, windowResizeDebounce)
function windowResizeInner (callback) {
checkLayout()
@@ -520,7 +559,9 @@ function windowResizeInner (callback) {
clearMap()
autoSyncscroll()
updateScrollspy()
- if (callback && typeof callback === 'function') { callback() }
+ if (callback && typeof callback === 'function') {
+ callback()
+ }
}, 1)
} else {
// force it load all docs at once to prevent scroll knob blink
@@ -530,18 +571,22 @@ function windowResizeInner (callback) {
autoSyncscroll()
editor.setOption('viewportMargin', viewportMargin)
// add or update user cursors
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id !== personalInfo.id) { buildCursor(onlineUsers[i]) }
+ for (let i = 0; i < onlineUsers.length; i++) {
+ if (onlineUsers[i].id !== personalInfo.id) {
+ buildCursor(onlineUsers[i])
+ }
}
updateScrollspy()
- if (callback && typeof callback === 'function') { callback() }
+ if (callback && typeof callback === 'function') {
+ callback()
+ }
}, 1)
}
}
}
function checkLayout () {
- var navbarHieght = $('.navbar').outerHeight()
+ const navbarHieght = $('.navbar').outerHeight()
$('body').css('padding-top', navbarHieght + 'px')
}
@@ -557,22 +602,28 @@ function checkResponsive () {
visibleLG = $('.visible-lg').is(':visible')
if (visibleXS && appState.currentMode === modeType.both) {
- if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) }
+ if (editorHasFocus()) {
+ changeMode(modeType.edit)
+ } else {
+ changeMode(modeType.view)
+ }
}
emitUserStatus()
}
-var lastEditorWidth = 0
-var previousFocusOnEditor = null
+let lastEditorWidth = 0
+let previousFocusOnEditor = null
function checkEditorStyle () {
- var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height()
+ let desireHeight = editorInstance.statusBar
+ ? ui.area.edit.height() - editorInstance.statusBar.outerHeight()
+ : ui.area.edit.height()
if (editorInstance.toolBar) {
desireHeight = desireHeight - editorInstance.toolBar.outerHeight()
}
// set editor height and min height based on scrollbar style and mode
- var scrollbarStyle = editor.getOption('scrollbarStyle')
+ const scrollbarStyle = editor.getOption('scrollbarStyle')
if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) {
ui.area.codemirrorScroll.css('height', desireHeight + 'px')
ui.area.codemirrorScroll.css('min-height', '')
@@ -590,9 +641,11 @@ function checkEditorStyle () {
maxWidth: $(window).width() * 0.7,
minWidth: $(window).width() * 0.2,
create: function (e, ui) {
- $(this).parent().on('resize', function (e) {
- e.stopPropagation()
- })
+ $(this)
+ .parent()
+ .on('resize', function (e) {
+ e.stopPropagation()
+ })
},
start: function (e) {
editor.setOption('viewportMargin', Infinity)
@@ -622,23 +675,31 @@ function checkEditorStyle () {
ui.area.resize.handle = $('.ui-resizable-handle')
}
if (!ui.area.resize.syncToggle.length) {
- ui.area.resize.syncToggle = $('<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>')
- ui.area.resize.syncToggle.hover(function () {
- previousFocusOnEditor = editorHasFocus()
- }, function () {
- previousFocusOnEditor = null
- })
+ ui.area.resize.syncToggle = $(
+ '<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>'
+ )
+ ui.area.resize.syncToggle.hover(
+ function () {
+ previousFocusOnEditor = editorHasFocus()
+ },
+ function () {
+ previousFocusOnEditor = null
+ }
+ )
ui.area.resize.syncToggle.click(function () {
appState.syncscroll = !appState.syncscroll
checkSyncToggle()
})
ui.area.resize.handle.append(ui.area.resize.syncToggle)
ui.area.resize.syncToggle.hide()
- ui.area.resize.handle.hover(function () {
- ui.area.resize.syncToggle.stop(true, true).delay(200).fadeIn(100)
- }, function () {
- ui.area.resize.syncToggle.stop(true, true).delay(300).fadeOut(300)
- })
+ ui.area.resize.handle.hover(
+ function () {
+ ui.area.resize.syncToggle.stop(true, true).delay(200).fadeIn(100)
+ },
+ function () {
+ ui.area.resize.syncToggle.stop(true, true).delay(300).fadeOut(300)
+ }
+ )
}
}
@@ -651,37 +712,53 @@ function checkSyncToggle () {
window.preventSyncScrollToEdit = false
syncScrollToEdit()
}
- ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link')
+ ui.area.resize.syncToggle
+ .find('i')
+ .removeClass('fa-unlink')
+ .addClass('fa-link')
} else {
- ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink')
+ ui.area.resize.syncToggle
+ .find('i')
+ .removeClass('fa-link')
+ .addClass('fa-unlink')
}
}
-var checkEditorScrollbar = _.debounce(function () {
+const checkEditorScrollbar = _.debounce(function () {
editor.operation(checkEditorScrollbarInner)
}, 50)
function checkEditorScrollbarInner () {
// workaround simple scroll bar knob
// will get wrong position when editor height changed
- var scrollInfo = editor.getScrollInfo()
+ const scrollInfo = editor.getScrollInfo()
editor.scrollTo(null, scrollInfo.top - 1)
editor.scrollTo(null, scrollInfo.top)
}
function checkTocStyle () {
// toc right
- var paddingRight = parseFloat(ui.area.markdown.css('padding-right'))
- var right = ($(window).width() - (ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - paddingRight))
+ const paddingRight = parseFloat(ui.area.markdown.css('padding-right'))
+ const right =
+ $(window).width() -
+ (ui.area.markdown.offset().left +
+ ui.area.markdown.outerWidth() -
+ paddingRight)
ui.toc.toc.css('right', right + 'px')
// affix toc left
- var newbool
- var rightMargin = (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) / 2
+ let newbool
+ const rightMargin =
+ (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) /
+ 2
// for ipad or wider device
if (rightMargin >= 133) {
newbool = true
- var affixLeftMargin = (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2
- var left = ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - affixLeftMargin
+ const affixLeftMargin =
+ (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2
+ const left =
+ ui.area.markdown.offset().left +
+ ui.area.markdown.outerWidth() -
+ affixLeftMargin
ui.toc.affix.css('left', left + 'px')
ui.toc.affix.css('width', rightMargin + 'px')
} else {
@@ -708,12 +785,12 @@ function checkTocStyle () {
function showStatus (type, num) {
currentStatus = type
- var shortStatus = ui.toolbar.shortStatus
- var status = ui.toolbar.status
- var label = $('<span class="label"></span>')
- var fa = $('<i class="fa"></i>')
- var msg = ''
- var shortMsg = ''
+ const shortStatus = ui.toolbar.shortStatus
+ const status = ui.toolbar.status
+ const label = $('<span class="label"></span>')
+ const fa = $('<i class="fa"></i>')
+ let msg = ''
+ let shortMsg = ''
shortStatus.html('')
status.html('')
@@ -738,7 +815,7 @@ function showStatus (type, num) {
}
label.append(fa)
- var shortLabel = label.clone()
+ const shortLabel = label.clone()
shortLabel.append(' ' + shortMsg)
shortStatus.append(shortLabel)
@@ -761,7 +838,7 @@ function toggleMode () {
}
}
-var lastMode = null
+let lastMode = null
function changeMode (type) {
// lock navbar to prevent it hide after changeMode
@@ -771,8 +848,8 @@ function changeMode (type) {
lastMode = appState.currentMode
appState.currentMode = type
}
- var responsiveClass = 'col-lg-6 col-md-6 col-sm-6'
- var scrollClass = 'ui-scrollable'
+ const responsiveClass = 'col-lg-6 col-md-6 col-sm-6'
+ const scrollClass = 'ui-scrollable'
ui.area.codemirror.removeClass(scrollClass)
ui.area.edit.removeClass(responsiveClass)
ui.area.view.removeClass(scrollClass)
@@ -798,11 +875,20 @@ function changeMode (type) {
break
}
// save mode to url
- if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + appState.currentMode.name)
+ if (history.replaceState && window.loaded) {
+ history.replaceState(
+ null,
+ '',
+ serverurl + '/' + noteid + '?' + appState.currentMode.name
+ )
+ }
if (appState.currentMode === modeType.view) {
editor.getInputField().blur()
}
- if (appState.currentMode === modeType.edit || appState.currentMode === modeType.both) {
+ if (
+ appState.currentMode === modeType.edit ||
+ appState.currentMode === modeType.both
+ ) {
// add and update status bar
if (!editorInstance.statusBar) {
editorInstance.addStatusBar()
@@ -820,7 +906,10 @@ function changeMode (type) {
$(document.body).css('background-color', 'white')
updateView()
} else {
- $(document.body).css('background-color', ui.area.codemirror.css('background-color'))
+ $(document.body).css(
+ 'background-color',
+ ui.area.codemirror.css('background-color')
+ )
}
// check resizable editor style
if (appState.currentMode === modeType.both) {
@@ -864,15 +953,18 @@ function changeMode (type) {
ui.toolbar.both.removeClass('active')
ui.toolbar.edit.removeClass('active')
ui.toolbar.view.removeClass('active')
- var modeIcon = ui.toolbar.mode.find('i')
+ const modeIcon = ui.toolbar.mode.find('i')
modeIcon.removeClass('fa-pencil').removeClass('fa-eye')
- if (ui.area.edit.is(':visible') && ui.area.view.is(':visible')) { // both
+ if (ui.area.edit.is(':visible') && ui.area.view.is(':visible')) {
+ // both
ui.toolbar.both.addClass('active')
modeIcon.addClass('fa-eye')
- } else if (ui.area.edit.is(':visible')) { // edit
+ } else if (ui.area.edit.is(':visible')) {
+ // edit
ui.toolbar.edit.addClass('active')
modeIcon.addClass('fa-eye')
- } else if (ui.area.view.is(':visible')) { // view
+ } else if (ui.area.view.is(':visible')) {
+ // view
ui.toolbar.view.addClass('active')
modeIcon.addClass('fa-pencil')
}
@@ -883,17 +975,27 @@ function lockNavbar () {
$('.navbar').addClass('locked')
}
-var unlockNavbar = _.debounce(function () {
+const unlockNavbar = _.debounce(function () {
$('.navbar').removeClass('locked')
}, 200)
function showMessageModal (title, header, href, text, success) {
- var modal = $('.message-modal')
+ const modal = $('.message-modal')
modal.find('.modal-title').html(title)
modal.find('.modal-body h5').html(header)
- if (href) { modal.find('.modal-body a').attr('href', href).text(text) } else { modal.find('.modal-body a').removeAttr('href').text(text) }
- modal.find('.modal-footer button').removeClass('btn-default btn-success btn-danger')
- if (success) { modal.find('.modal-footer button').addClass('btn-success') } else { modal.find('.modal-footer button').addClass('btn-danger') }
+ if (href) {
+ modal.find('.modal-body a').attr('href', href).text(text)
+ } else {
+ modal.find('.modal-body a').removeAttr('href').text(text)
+ }
+ modal
+ .find('.modal-footer button')
+ .removeClass('btn-default btn-success btn-danger')
+ if (success) {
+ modal.find('.modal-footer button').addClass('btn-success')
+ } else {
+ modal.find('.modal-footer button').addClass('btn-danger')
+ }
modal.modal('show')
}
@@ -923,9 +1025,9 @@ ui.toolbar.extra.slide.attr('href', noteurl + '/slide')
ui.toolbar.download.markdown.click(function (e) {
e.preventDefault()
e.stopPropagation()
- var filename = renderFilename(ui.area.markdown) + '.md'
- var markdown = editor.getValue()
- var blob = new Blob([markdown], {
+ const filename = renderFilename(ui.area.markdown) + '.md'
+ const markdown = editor.getValue()
+ const blob = new Blob([markdown], {
type: 'text/markdown;charset=utf-8'
})
saveAs(blob, filename, true)
@@ -945,12 +1047,12 @@ ui.toolbar.download.rawhtml.click(function (e) {
// export to dropbox
ui.toolbar.export.dropbox.click(function (event) {
event.preventDefault()
- var filename = renderFilename(ui.area.markdown) + '.md'
- var options = {
+ const filename = renderFilename(ui.area.markdown) + '.md'
+ const options = {
files: [
{
- 'url': noteurl + '/download',
- 'filename': filename
+ url: noteurl + '/download',
+ filename: filename
}
],
error: function (errorMessage) {
@@ -971,25 +1073,48 @@ ui.toolbar.export.snippet.click(function () {
$('#snippetExportModalVersion').val(data.version)
$('#snippetExportModalLoading').hide()
$('#snippetExportModal').modal('toggle')
- $('#snippetExportModalProjects').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>')
+ $('#snippetExportModalProjects')
+ .find('option')
+ .remove()
+ .end()
+ .append(
+ '<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>'
+ )
if (data.projects) {
data.projects.sort(function (a, b) {
- return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)
+ return a.path_with_namespace < b.path_with_namespace
+ ? -1
+ : a.path_with_namespace > b.path_with_namespace
+ ? 1
+ : 0
})
data.projects.forEach(function (project) {
- if (!project.snippets_enabled ||
- (project.permissions.project_access === null && project.permissions.group_access === null) ||
- (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {
+ if (
+ !project.snippets_enabled ||
+ (project.permissions.project_access === null &&
+ project.permissions.group_access === null) ||
+ (project.permissions.project_access !== null &&
+ project.permissions.project_access.access_level < 20)
+ ) {
return
}
- $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetExportModalProjects')
+ $('<option>')
+ .val(project.id)
+ .text(project.path_with_namespace)
+ .appendTo('#snippetExportModalProjects')
})
$('#snippetExportModalProjects').prop('disabled', false)
}
$('#snippetExportModalLoading').hide()
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-gitlab"></i> Import from Snippet',
+ 'Unable to fetch gitlab parameters :(',
+ '',
+ '',
+ false
+ )
})
.always(function () {
ui.spinner.hide()
@@ -998,10 +1123,10 @@ ui.toolbar.export.snippet.click(function () {
// import from dropbox
ui.toolbar.import.dropbox.click(function (event) {
event.preventDefault()
- var options = {
+ const options = {
success: function (files) {
ui.spinner.show()
- var url = files[0].link
+ const url = files[0].link
importFromUrl(url)
},
linkType: 'direct',
@@ -1026,25 +1151,48 @@ ui.toolbar.import.snippet.click(function () {
$('#snippetImportModalConfirm').prop('disabled', false)
$('#snippetImportModalLoading').hide()
$('#snippetImportModal').modal('toggle')
- $('#snippetImportModalProjects').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>')
+ $('#snippetImportModalProjects')
+ .find('option')
+ .remove()
+ .end()
+ .append(
+ '<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>'
+ )
if (data.projects) {
data.projects.sort(function (a, b) {
- return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)
+ return a.path_with_namespace < b.path_with_namespace
+ ? -1
+ : a.path_with_namespace > b.path_with_namespace
+ ? 1
+ : 0
})
data.projects.forEach(function (project) {
- if (!project.snippets_enabled ||
- (project.permissions.project_access === null && project.permissions.group_access === null) ||
- (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {
+ if (
+ !project.snippets_enabled ||
+ (project.permissions.project_access === null &&
+ project.permissions.group_access === null) ||
+ (project.permissions.project_access !== null &&
+ project.permissions.project_access.access_level < 20)
+ ) {
return
}
- $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetImportModalProjects')
+ $('<option>')
+ .val(project.id)
+ .text(project.path_with_namespace)
+ .appendTo('#snippetImportModalProjects')
})
$('#snippetImportModalProjects').prop('disabled', false)
}
$('#snippetImportModalLoading').hide()
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-gitlab"></i> Import from Snippet',
+ 'Unable to fetch gitlab parameters :(',
+ '',
+ '',
+ false
+ )
})
.always(function () {
ui.spinner.hide()
@@ -1060,15 +1208,15 @@ $('a[href="#"]').click(function (e) {
})
// modal actions
-var revisions = []
-var revisionViewer = null
-var revisionInsert = []
-var revisionDelete = []
-var revisionInsertAnnotation = null
-var revisionDeleteAnnotation = null
-var revisionList = ui.modal.revision.find('.ui-revision-list')
-var revision = null
-var revisionTime = null
+let revisions = []
+let revisionViewer = null
+let revisionInsert = []
+let revisionDelete = []
+let revisionInsertAnnotation = null
+let revisionDeleteAnnotation = null
+const revisionList = ui.modal.revision.find('.ui-revision-list')
+let revision = null
+let revisionTime = null
ui.modal.revision.on('show.bs.modal', function (e) {
$.get(noteurl + '/revision')
.done(function (data) {
@@ -1087,7 +1235,7 @@ ui.modal.revision.on('show.bs.modal', function (e) {
})
function checkRevisionViewer () {
if (revisionViewer) {
- var container = $(revisionViewer.display.wrapper).parent()
+ const container = $(revisionViewer.display.wrapper).parent()
$(revisionViewer.display.scroller).css('height', container.height() + 'px')
revisionViewer.refresh()
}
@@ -1097,23 +1245,27 @@ $(window).resize(checkRevisionViewer)
function parseRevisions (_revisions) {
if (_revisions.length !== revisions) {
revisions = _revisions
- var lastRevision = null
+ let lastRevision = null
if (revisionList.children().length > 0) {
lastRevision = revisionList.find('.active').attr('data-revision-time')
}
revisionList.html('')
- for (var i = 0; i < revisions.length; i++) {
- var revision = revisions[i]
- var item = $('<a class="list-group-item"></a>')
+ for (let i = 0; i < revisions.length; i++) {
+ const revision = revisions[i]
+ const item = $('<a class="list-group-item"></a>')
item.attr('data-revision-time', revision.time)
if (lastRevision === revision.time) item.addClass('active')
- var itemHeading = $('<h5 class="list-group-item-heading"></h5>')
- itemHeading.html('<i class="fa fa-clock-o"></i> ' + moment(revision.time).format('llll'))
- var itemText = $('<p class="list-group-item-text"></p>')
- itemText.html('<i class="fa fa-file-text"></i> Length: ' + revision.length)
+ const itemHeading = $('<h5 class="list-group-item-heading"></h5>')
+ itemHeading.html(
+ '<i class="fa fa-clock-o"></i> ' + moment(revision.time).format('llll')
+ )
+ const itemText = $('<p class="list-group-item-text"></p>')
+ itemText.html(
+ '<i class="fa fa-file-text"></i> Length: ' + revision.length
+ )
item.append(itemHeading).append(itemText)
item.click(function (e) {
- var time = $(this).attr('data-revision-time')
+ const time = $(this).attr('data-revision-time')
selectRevision(time)
})
revisionList.append(item)
@@ -1129,52 +1281,59 @@ function selectRevision (time) {
.done(function (data) {
revision = data
revisionTime = time
- var lastScrollInfo = revisionViewer.getScrollInfo()
+ const lastScrollInfo = revisionViewer.getScrollInfo()
revisionList.children().removeClass('active')
- revisionList.find('[data-revision-time="' + time + '"]').addClass('active')
- var content = revision.content
+ revisionList
+ .find('[data-revision-time="' + time + '"]')
+ .addClass('active')
+ const content = revision.content
revisionViewer.setValue(content)
revisionViewer.scrollTo(null, lastScrollInfo.top)
revisionInsert = []
revisionDelete = []
// mark the text which have been insert or delete
if (revision.patch.length > 0) {
- var bias = 0
- for (var j = 0; j < revision.patch.length; j++) {
- var patch = revision.patch[j]
- var currIndex = patch.start1 + bias
- for (var i = 0; i < patch.diffs.length; i++) {
- var diff = patch.diffs[i]
+ let bias = 0
+ for (let j = 0; j < revision.patch.length; j++) {
+ const patch = revision.patch[j]
+ let currIndex = patch.start1 + bias
+ for (let i = 0; i < patch.diffs.length; i++) {
+ const diff = patch.diffs[i]
// ignore if diff only contains line breaks
- if ((diff[1].match(/\n/g) || []).length === diff[1].length) continue
- var prePos
- var postPos
+ if ((diff[1].match(/\n/g) || []).length === diff[1].length) { continue }
+ let prePos, postPos
switch (diff[0]) {
case 0: // retain
currIndex += diff[1].length
break
case 1: // insert
prePos = revisionViewer.posFromIndex(currIndex)
- postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)
+ postPos = revisionViewer.posFromIndex(
+ currIndex + diff[1].length
+ )
revisionInsert.push({
from: prePos,
to: postPos
})
revisionViewer.markText(prePos, postPos, {
- css: 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'
+ css:
+ 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'
})
currIndex += diff[1].length
break
case -1: // delete
prePos = revisionViewer.posFromIndex(currIndex)
revisionViewer.replaceRange(diff[1], prePos)
- postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)
+ postPos = revisionViewer.posFromIndex(
+ currIndex + diff[1].length
+ )
revisionDelete.push({
from: prePos,
to: postPos
})
revisionViewer.markText(prePos, postPos, {
- css: 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'
+ css:
+ 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'
})
bias += diff[1].length
currIndex += diff[1].length
@@ -1198,7 +1357,7 @@ function selectRevision (time) {
}
function initRevisionViewer () {
if (revisionViewer) return
- var revisionViewerTextArea = document.getElementById('revisionViewer')
+ const revisionViewerTextArea = document.getElementById('revisionViewer')
revisionViewer = CodeMirror.fromTextArea(revisionViewerTextArea, {
mode: defaultEditorMode,
viewportMargin: viewportMargin,
@@ -1213,14 +1372,19 @@ function initRevisionViewer () {
autoRefresh: true,
scrollbarStyle: 'overlay'
})
- revisionInsertAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-insert-match' })
- revisionDeleteAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-delete-match' })
+ revisionInsertAnnotation = revisionViewer.annotateScrollbar({
+ className: 'CodeMirror-insert-match'
+ })
+ revisionDeleteAnnotation = revisionViewer.annotateScrollbar({
+ className: 'CodeMirror-delete-match'
+ })
checkRevisionViewer()
}
$('#revisionModalDownload').click(function () {
if (!revision) return
- var filename = renderFilename(ui.area.markdown) + '_' + revisionTime + '.md'
- var blob = new Blob([revision.content], {
+ const filename =
+ renderFilename(ui.area.markdown) + '_' + revisionTime + '.md'
+ const blob = new Blob([revision.content], {
type: 'text/markdown;charset=utf-8'
})
saveAs(blob, filename, true)
@@ -1232,17 +1396,34 @@ $('#revisionModalRevert').click(function () {
})
// snippet projects
ui.modal.snippetImportProjects.change(function () {
- var accesstoken = $('#snippetImportModalAccessToken').val()
- var baseURL = $('#snippetImportModalBaseURL').val()
- var project = $('#snippetImportModalProjects').val()
- var version = $('#snippetImportModalVersion').val()
+ const accesstoken = $('#snippetImportModalAccessToken').val()
+ const baseURL = $('#snippetImportModalBaseURL').val()
+ const project = $('#snippetImportModalProjects').val()
+ const version = $('#snippetImportModalVersion').val()
$('#snippetImportModalLoading').show()
$('#snippetImportModalContent').val('/projects/' + project)
- $.get(baseURL + '/api/' + version + '/projects/' + project + '/snippets?access_token=' + accesstoken)
+ $.get(
+ baseURL +
+ '/api/' +
+ version +
+ '/projects/' +
+ project +
+ '/snippets?access_token=' +
+ accesstoken
+ )
.done(function (data) {
- $('#snippetImportModalSnippets').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Snippets</option>')
+ $('#snippetImportModalSnippets')
+ .find('option')
+ .remove()
+ .end()
+ .append(
+ '<option value="init" selected="selected" disabled="disabled">Select From Available Snippets</option>'
+ )
data.forEach(function (snippet) {
- $('<option>').val(snippet.id).text(snippet.title).appendTo($('#snippetImportModalSnippets'))
+ $('<option>')
+ .val(snippet.id)
+ .text(snippet.title)
+ .appendTo($('#snippetImportModalSnippets'))
})
$('#snippetImportModalLoading').hide()
$('#snippetImportModalSnippets').prop('disabled', false)
@@ -1259,44 +1440,68 @@ ui.modal.snippetImportProjects.change(function () {
})
// snippet snippets
ui.modal.snippetImportSnippets.change(function () {
- var snippet = $('#snippetImportModalSnippets').val()
- $('#snippetImportModalContent').val($('#snippetImportModalContent').val() + '/snippets/' + snippet)
+ const snippet = $('#snippetImportModalSnippets').val()
+ $('#snippetImportModalContent').val(
+ $('#snippetImportModalContent').val() + '/snippets/' + snippet
+ )
})
function scrollToTop () {
if (appState.currentMode === modeType.both) {
- if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else {
- ui.area.view.animate({
- scrollTop: 0
- }, 100, 'linear')
+ if (editor.getScrollInfo().top !== 0) {
+ editor.scrollTo(0, 0)
+ } else {
+ ui.area.view.animate(
+ {
+ scrollTop: 0
+ },
+ 100,
+ 'linear'
+ )
}
} else {
- $('body, html').stop(true, true).animate({
- scrollTop: 0
- }, 100, 'linear')
+ $('body, html').stop(true, true).animate(
+ {
+ scrollTop: 0
+ },
+ 100,
+ 'linear'
+ )
}
}
function scrollToBottom () {
if (appState.currentMode === modeType.both) {
- var scrollInfo = editor.getScrollInfo()
- var scrollHeight = scrollInfo.height
- if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else {
- ui.area.view.animate({
- scrollTop: ui.area.view[0].scrollHeight
- }, 100, 'linear')
+ const scrollInfo = editor.getScrollInfo()
+ const scrollHeight = scrollInfo.height
+ if (scrollInfo.top !== scrollHeight) {
+ editor.scrollTo(0, scrollHeight * 2)
+ } else {
+ ui.area.view.animate(
+ {
+ scrollTop: ui.area.view[0].scrollHeight
+ },
+ 100,
+ 'linear'
+ )
}
} else {
- $('body, html').stop(true, true).animate({
- scrollTop: $(document.body)[0].scrollHeight
- }, 100, 'linear')
+ $('body, html')
+ .stop(true, true)
+ .animate(
+ {
+ scrollTop: $(document.body)[0].scrollHeight
+ },
+ 100,
+ 'linear'
+ )
}
}
window.scrollToTop = scrollToTop
window.scrollToBottom = scrollToBottom
-var enoughForAffixToc = true
+let enoughForAffixToc = true
// scrollspy
function generateScrollspy () {
@@ -1320,29 +1525,53 @@ function generateScrollspy () {
}
function updateScrollspy () {
- var headers = ui.area.markdown.find('h1, h2, h3').toArray()
- var headerMap = []
- for (var i = 0; i < headers.length; i++) {
- headerMap.push($(headers[i]).offset().top - parseInt($(headers[i]).css('margin-top')))
+ const headers = ui.area.markdown.find('h1, h2, h3').toArray()
+ const headerMap = []
+ for (let i = 0; i < headers.length; i++) {
+ headerMap.push(
+ $(headers[i]).offset().top - parseInt($(headers[i]).css('margin-top'))
+ )
}
- applyScrollspyActive($(window).scrollTop(), headerMap, headers,
- $('.scrollspy-body'), 0)
- var offset = ui.area.view.scrollTop() - ui.area.view.offset().top
- applyScrollspyActive(ui.area.view.scrollTop(), headerMap, headers,
- $('.scrollspy-view'), offset - 10)
+ applyScrollspyActive(
+ $(window).scrollTop(),
+ headerMap,
+ headers,
+ $('.scrollspy-body'),
+ 0
+ )
+ const offset = ui.area.view.scrollTop() - ui.area.view.offset().top
+ applyScrollspyActive(
+ ui.area.view.scrollTop(),
+ headerMap,
+ headers,
+ $('.scrollspy-view'),
+ offset - 10
+ )
}
function applyScrollspyActive (top, headerMap, headers, target, offset) {
- var index = 0
- for (var i = headerMap.length - 1; i >= 0; i--) {
- if (top >= (headerMap[i] + offset) && headerMap[i + 1] && top < (headerMap[i + 1] + offset)) {
+ let index = 0
+ for (let i = headerMap.length - 1; i >= 0; i--) {
+ if (
+ top >= headerMap[i] + offset &&
+ headerMap[i + 1] &&
+ top < headerMap[i + 1] + offset
+ ) {
index = i
break
}
}
- var header = $(headers[index])
- var active = target.find('a[href="#' + header.attr('id') + '"]')
- active.closest('li').addClass('active').parent().closest('li').addClass('active').parent().closest('li').addClass('active')
+ const header = $(headers[index])
+ const active = target.find('a[href="#' + header.attr('id') + '"]')
+ active
+ .closest('li')
+ .addClass('active')
+ .parent()
+ .closest('li')
+ .addClass('active')
+ .parent()
+ .closest('li')
+ .addClass('active')
}
// clipboard modal
@@ -1354,7 +1583,7 @@ $('#clipboardModalClear').click(function () {
$('#clipboardModalContent').html('')
})
$('#clipboardModalConfirm').click(function () {
- var data = $('#clipboardModalContent').html()
+ const data = $('#clipboardModalContent').html()
if (data) {
parseToEditor(data)
$('#clipboardModal').modal('hide')
@@ -1372,22 +1601,34 @@ $('#gistImportModalClear').click(function () {
$('#gistImportModalContent').val('')
})
$('#gistImportModalConfirm').click(function () {
- var gisturl = $('#gistImportModalContent').val()
+ const gisturl = $('#gistImportModalContent').val()
if (!gisturl) return
$('#gistImportModal').modal('hide')
$('#gistImportModalContent').val('')
if (!isValidURL(gisturl)) {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid URL :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-github"></i> Import from Gist',
+ 'Not a valid URL :(',
+ '',
+ '',
+ false
+ )
} else {
- var hostname = url('hostname', gisturl)
+ const hostname = url('hostname', gisturl)
if (hostname !== 'gist.github.com') {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-github"></i> Import from Gist',
+ 'Not a valid Gist URL :(',
+ '',
+ '',
+ false
+ )
} else {
ui.spinner.show()
$.get('https://api.github.com/gists/' + url('-1', gisturl))
.done(function (data) {
if (data.files) {
- var contents = ''
+ let contents = ''
Object.keys(data.files).forEach(function (key) {
contents += key
contents += '\n---\n'
@@ -1396,11 +1637,23 @@ $('#gistImportModalConfirm').click(function () {
})
replaceAll(contents)
} else {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Unable to fetch gist files :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-github"></i> Import from Gist',
+ 'Unable to fetch gist files :(',
+ '',
+ '',
+ false
+ )
}
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', JSON.stringify(data), false)
+ showMessageModal(
+ '<i class="fa fa-github"></i> Import from Gist',
+ 'Not a valid Gist URL :(',
+ '',
+ JSON.stringify(data),
+ false
+ )
})
.always(function () {
ui.spinner.hide()
@@ -1417,21 +1670,32 @@ $('#snippetImportModalClear').click(function () {
$('#snippetImportModalSnippets').prop('disabled', true)
})
$('#snippetImportModalConfirm').click(function () {
- var snippeturl = $('#snippetImportModalContent').val()
+ const snippeturl = $('#snippetImportModalContent').val()
if (!snippeturl) return
$('#snippetImportModal').modal('hide')
$('#snippetImportModalContent').val('')
if (!/^.+\/snippets\/.+$/.test(snippeturl)) {
- showMessageModal('<i class="fa fa-github"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-github"></i> Import from Snippet',
+ 'Not a valid Snippet URL :(',
+ '',
+ '',
+ false
+ )
} else {
ui.spinner.show()
- var accessToken = '?access_token=' + $('#snippetImportModalAccessToken').val()
- var fullURL = $('#snippetImportModalBaseURL').val() + '/api/' + $('#snippetImportModalVersion').val() + snippeturl
+ const accessToken =
+ '?access_token=' + $('#snippetImportModalAccessToken').val()
+ const fullURL =
+ $('#snippetImportModalBaseURL').val() +
+ '/api/' +
+ $('#snippetImportModalVersion').val() +
+ snippeturl
$.get(fullURL + accessToken)
.done(function (data) {
- var content = '# ' + (data.title || 'Snippet Import')
- var fileInfo = data.file_name.split('.')
- fileInfo[1] = (fileInfo[1]) ? fileInfo[1] : 'md'
+ let content = '# ' + (data.title || 'Snippet Import')
+ const fileInfo = data.file_name.split('.')
+ fileInfo[1] = fileInfo[1] ? fileInfo[1] : 'md'
$.get(fullURL + '/raw' + accessToken)
.done(function (raw) {
if (raw) {
@@ -1447,82 +1711,147 @@ $('#snippetImportModalConfirm').click(function () {
}
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)
+ showMessageModal(
+ '<i class="fa fa-gitlab"></i> Import from Snippet',
+ 'Not a valid Snippet URL :(',
+ '',
+ JSON.stringify(data),
+ false
+ )
})
.always(function () {
ui.spinner.hide()
})
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)
+ showMessageModal(
+ '<i class="fa fa-gitlab"></i> Import from Snippet',
+ 'Not a valid Snippet URL :(',
+ '',
+ JSON.stringify(data),
+ false
+ )
})
}
})
// snippet export modal
$('#snippetExportModalConfirm').click(function () {
- var accesstoken = $('#snippetExportModalAccessToken').val()
- var baseURL = $('#snippetExportModalBaseURL').val()
- var version = $('#snippetExportModalVersion').val()
+ const accesstoken = $('#snippetExportModalAccessToken').val()
+ const baseURL = $('#snippetExportModalBaseURL').val()
+ const version = $('#snippetExportModalVersion').val()
- var data = {
+ const data = {
title: $('#snippetExportModalTitle').val(),
file_name: $('#snippetExportModalFileName').val(),
code: editor.getValue(),
visibility_level: $('#snippetExportModalVisibility').val(),
- visibility: $('#snippetExportModalVisibility').val() === '0' ? 'private' : ($('#snippetExportModalVisibility').val() === '10' ? 'internal' : 'private')
- }
-
- if (!data.title || !data.file_name || !data.code || !data.visibility_level || !$('#snippetExportModalProjects').val()) return
+ visibility:
+ $('#snippetExportModalVisibility').val() === '0'
+ ? 'private'
+ : $('#snippetExportModalVisibility').val() === '10'
+ ? 'internal'
+ : 'private'
+ }
+
+ if (
+ !data.title ||
+ !data.file_name ||
+ !data.code ||
+ !data.visibility_level ||
+ !$('#snippetExportModalProjects').val()
+ ) { return }
$('#snippetExportModalLoading').show()
- var fullURL = baseURL + '/api/' + version + '/projects/' + $('#snippetExportModalProjects').val() + '/snippets?access_token=' + accesstoken
- $.post(fullURL
- , data
- , function (ret) {
- $('#snippetExportModalLoading').hide()
- $('#snippetExportModal').modal('hide')
- var redirect = baseURL + '/' + $("#snippetExportModalProjects option[value='" + $('#snippetExportModalProjects').val() + "']").text() + '/snippets/' + ret.id
- showMessageModal('<i class="fa fa-gitlab"></i> Export to Snippet', 'Export Successful!', redirect, 'View Snippet Here', true)
- }
- )
+ const fullURL =
+ baseURL +
+ '/api/' +
+ version +
+ '/projects/' +
+ $('#snippetExportModalProjects').val() +
+ '/snippets?access_token=' +
+ accesstoken
+ $.post(fullURL, data, function (ret) {
+ $('#snippetExportModalLoading').hide()
+ $('#snippetExportModal').modal('hide')
+ const redirect =
+ baseURL +
+ '/' +
+ $(
+ "#snippetExportModalProjects option[value='" +
+ $('#snippetExportModalProjects').val() +
+ "']"
+ ).text() +
+ '/snippets/' +
+ ret.id
+ showMessageModal(
+ '<i class="fa fa-gitlab"></i> Export to Snippet',
+ 'Export Successful!',
+ redirect,
+ 'View Snippet Here',
+ true
+ )
+ })
})
function parseToEditor (data) {
- var turndownService = new TurndownService({
+ const turndownService = new TurndownService({
defaultReplacement: function (innerHTML, node) {
return node.isBlock ? '\n\n' + node.outerHTML + '\n\n' : node.outerHTML
}
})
- var parsed = turndownService.turndown(data)
- if (parsed) { replaceAll(parsed) }
+ const parsed = turndownService.turndown(data)
+ if (parsed) {
+ replaceAll(parsed)
+ }
}
function replaceAll (data) {
- editor.replaceRange(data, {
- line: 0,
- ch: 0
- }, {
- line: editor.lastLine(),
- ch: editor.lastLine().length
- }, '+input')
+ editor.replaceRange(
+ data,
+ {
+ line: 0,
+ ch: 0
+ },
+ {
+ line: editor.lastLine(),
+ ch: editor.lastLine().length
+ },
+ '+input'
+ )
}
function importFromUrl (url) {
// console.debug(url);
if (!url) return
if (!isValidURL(url)) {
- showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Not a valid URL :(', '', '', false)
+ showMessageModal(
+ '<i class="fa fa-cloud-download"></i> Import from URL',
+ 'Not a valid URL :(',
+ '',
+ '',
+ false
+ )
return
}
$.ajax({
method: 'GET',
url: url,
success: function (data) {
- var extension = url.split('.').pop()
- if (extension === 'html') { parseToEditor(data) } else { replaceAll(data) }
+ const extension = url.split('.').pop()
+ if (extension === 'html') {
+ parseToEditor(data)
+ } else {
+ replaceAll(data)
+ }
},
error: function (data) {
- showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Import failed :(', '', JSON.stringify(data), false)
+ showMessageModal(
+ '<i class="fa fa-cloud-download"></i> Import from URL',
+ 'Import failed :(',
+ '',
+ JSON.stringify(data),
+ false
+ )
},
complete: function () {
ui.spinner.hide()
@@ -1584,8 +1913,8 @@ $('.ui-delete-modal-confirm').click(function () {
})
function toggleNightMode () {
- var $body = $('body')
- var isActive = ui.toolbar.night.hasClass('active')
+ const $body = $('body')
+ const isActive = ui.toolbar.night.hasClass('active')
if (isActive) {
$body.removeClass('night')
appState.nightMode = false
@@ -1613,8 +1942,8 @@ function updatePermission (newPermission) {
permission = newPermission
if (window.loaded) refreshView()
}
- var label = null
- var title = null
+ let label = null
+ let title = null
switch (permission) {
case 'freely':
label = '<i class="fa fa-leaf"></i> Freely'
@@ -1641,7 +1970,11 @@ function updatePermission (newPermission) {
title = 'Only owner can view & edit'
break
}
- if (personalInfo.userid && window.owner && personalInfo.userid === window.owner) {
+ if (
+ personalInfo.userid &&
+ window.owner &&
+ personalInfo.userid === window.owner
+ ) {
label += ' <i class="fa fa-caret-down"></i>'
ui.infobar.permission.label.removeClass('disabled')
} else {
@@ -1651,7 +1984,7 @@ function updatePermission (newPermission) {
}
function havePermission () {
- var bool = false
+ let bool = false
switch (permission) {
case 'freely':
bool = true
@@ -1680,8 +2013,8 @@ function havePermission () {
window.havePermission = havePermission
// socket.io actions
-var io = require('socket.io-client')
-var socket = io.connect({
+const io = require('socket.io-client')
+const socket = io.connect({
path: urlpath ? '/' + urlpath + '/socket.io/' : '',
query: {
noteId: noteid
@@ -1690,13 +2023,17 @@ var socket = io.connect({
reconnectionAttempts: 20 // retry 20 times on connect failed
})
// overwrite original event for checking login state
-var on = socket.on
+const on = socket.on
socket.on = function () {
- if (!checkLoginStateChanged() && !needRefresh) { return on.apply(socket, arguments) }
+ if (!checkLoginStateChanged() && !needRefresh) {
+ return on.apply(socket, arguments)
+ }
}
-var emit = socket.emit
+const emit = socket.emit
socket.emit = function () {
- if (!checkLoginStateChanged() && !needRefresh) { emit.apply(socket, arguments) }
+ if (!checkLoginStateChanged() && !needRefresh) {
+ emit.apply(socket, arguments)
+ }
}
socket.on('info', function (data) {
console.error(data)
@@ -1714,7 +2051,9 @@ socket.on('info', function (data) {
})
socket.on('error', function (data) {
console.error(data)
- if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' }
+ if (data.message && data.message.indexOf('AUTH failed') === 0) {
+ location.href = serverurl + '/403'
+ }
})
socket.on('delete', function () {
if (personalInfo.login) {
@@ -1723,13 +2062,13 @@ socket.on('delete', function () {
})
} else {
getHistory(function (notehistory) {
- var newnotehistory = removeHistory(noteid, notehistory)
+ const newnotehistory = removeHistory(noteid, notehistory)
saveHistory(newnotehistory)
location.href = serverurl
})
}
})
-var retryTimer = null
+let retryTimer = null
socket.on('maintenance', function () {
cmClient.revision = -1
})
@@ -1739,7 +2078,9 @@ socket.on('disconnect', function (data) {
saveInfo()
lastInfo.history = editor.getHistory()
}
- if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) }
+ if (!editor.getOption('readOnly')) {
+ editor.setOption('readOnly', true)
+ }
if (!retryTimer) {
retryTimer = setInterval(function () {
if (!needRefresh) socket.connect()
@@ -1755,7 +2096,7 @@ socket.on('reconnect', function (data) {
socket.on('connect', function (data) {
clearInterval(retryTimer)
retryTimer = null
- personalInfo['id'] = socket.id
+ personalInfo.id = socket.id
showStatus(statusType.connected)
socket.emit('version')
})
@@ -1769,40 +2110,58 @@ socket.on('version', function (data) {
}
}
})
-var authors = []
-var authorship = []
-var authorMarks = {} // temp variable
-var addTextMarkers = [] // temp variable
+let authors = []
+let authorship = []
+let authorMarks = {} // temp variable
+let addTextMarkers = [] // temp variable
function updateInfo (data) {
// console.debug(data);
- if (data.hasOwnProperty('createtime') && window.createtime !== data.createtime) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'createtime') &&
+ window.createtime !== data.createtime
+ ) {
window.createtime = data.createtime
updateLastChange()
}
- if (data.hasOwnProperty('updatetime') && window.lastchangetime !== data.updatetime) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'updatetime') &&
+ window.lastchangetime !== data.updatetime
+ ) {
window.lastchangetime = data.updatetime
updateLastChange()
}
- if (data.hasOwnProperty('owner') && window.owner !== data.owner) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'owner') &&
+ window.owner !== data.owner
+ ) {
window.owner = data.owner
window.ownerprofile = data.ownerprofile
updateOwner()
}
- if (data.hasOwnProperty('lastchangeuser') && window.lastchangeuser !== data.lastchangeuser) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'lastchangeuser') &&
+ window.lastchangeuser !== data.lastchangeuser
+ ) {
window.lastchangeuser = data.lastchangeuser
window.lastchangeuserprofile = data.lastchangeuserprofile
updateLastChangeUser()
updateOwner()
}
- if (data.hasOwnProperty('authors') && authors !== data.authors) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'authors') &&
+ authors !== data.authors
+ ) {
authors = data.authors
}
- if (data.hasOwnProperty('authorship') && authorship !== data.authorship) {
+ if (
+ Object.prototype.hasOwnProperty.call(data, 'authorship') &&
+ authorship !== data.authorship
+ ) {
authorship = data.authorship
updateAuthorship()
}
}
-var updateAuthorship = _.debounce(function () {
+const updateAuthorship = _.debounce(function () {
editor.operation(updateAuthorshipInner)
}, 50)
function initMark () {
@@ -1822,46 +2181,59 @@ function initMarkAndCheckGutter (mark, author, timestamp) {
}
return mark
}
-var addStyleRule = (function () {
- var added = {}
- var styleElement = document.createElement('style')
- document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement)
- var styleSheet = styleElement.sheet
+const addStyleRule = (function () {
+ const added = {}
+ const styleElement = document.createElement('style')
+ document.documentElement
+ .getElementsByTagName('head')[0]
+ .appendChild(styleElement)
+ const styleSheet = styleElement.sheet
return function (css) {
if (added[css]) {
return
}
added[css] = true
- styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length)
+ styleSheet.insertRule(
+ css,
+ (styleSheet.cssRules || styleSheet.rules).length
+ )
}
-}())
+})()
function updateAuthorshipInner () {
// ignore when ot not synced yet
if (havePendingOperation()) return
authorMarks = {}
for (let i = 0; i < authorship.length; i++) {
- var atom = authorship[i]
- let author = authors[atom[0]]
+ const atom = authorship[i]
+ const author = authors[atom[0]]
if (author) {
- var prePos = editor.posFromIndex(atom[1])
- var preLine = editor.getLine(prePos.line)
- var postPos = editor.posFromIndex(atom[2])
- var postLine = editor.getLine(postPos.line)
+ const prePos = editor.posFromIndex(atom[1])
+ const preLine = editor.getLine(prePos.line)
+ const postPos = editor.posFromIndex(atom[2])
+ const postLine = editor.getLine(postPos.line)
if (prePos.ch === 0 && postPos.ch === postLine.length) {
for (let j = prePos.line; j <= postPos.line; j++) {
if (editor.getLine(j)) {
- authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])
+ authorMarks[j] = initMarkAndCheckGutter(
+ authorMarks[j],
+ author,
+ atom[3]
+ )
}
}
} else if (postPos.line - prePos.line >= 1) {
- var startLine = prePos.line
- var endLine = postPos.line
+ let startLine = prePos.line
+ let endLine = postPos.line
if (prePos.ch === preLine.length) {
startLine++
} else if (prePos.ch !== 0) {
- let mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
- var _postPos = {
+ const mark = initMarkAndCheckGutter(
+ authorMarks[prePos.line],
+ author,
+ atom[3]
+ )
+ const _postPos = {
line: prePos.line,
ch: preLine.length
}
@@ -1877,8 +2249,12 @@ function updateAuthorshipInner () {
if (postPos.ch === 0) {
endLine--
} else if (postPos.ch !== postLine.length) {
- let mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3])
- var _prePos = {
+ const mark = initMarkAndCheckGutter(
+ authorMarks[postPos.line],
+ author,
+ atom[3]
+ )
+ const _prePos = {
line: postPos.line,
ch: 0
}
@@ -1893,11 +2269,19 @@ function updateAuthorshipInner () {
}
for (let j = startLine; j <= endLine; j++) {
if (editor.getLine(j)) {
- authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])
+ authorMarks[j] = initMarkAndCheckGutter(
+ authorMarks[j],
+ author,
+ atom[3]
+ )
}
}
} 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)) {
mark.textmarkers.push({
userid: author.userid,
@@ -1910,38 +2294,45 @@ function updateAuthorshipInner () {
}
addTextMarkers = []
editor.eachLine(iterateLine)
- var allTextMarks = editor.getAllMarks()
+ const allTextMarks = editor.getAllMarks()
for (let i = 0; i < allTextMarks.length; i++) {
- let _textMarker = allTextMarks[i]
- var pos = _textMarker.find()
- var found = false
+ const _textMarker = allTextMarks[i]
+ const pos = _textMarker.find()
+ let found = false
for (let j = 0; j < addTextMarkers.length; j++) {
- let textMarker = addTextMarkers[j]
- let author = authors[textMarker.userid]
- let className = 'authorship-inline-' + author.color.substr(1)
- var obj = {
+ const textMarker = addTextMarkers[j]
+ const author = authors[textMarker.userid]
+ const className = 'authorship-inline-' + author.color.substr(1)
+ const obj = {
from: textMarker.pos[0],
to: textMarker.pos[1]
}
- if (JSON.stringify(pos) === JSON.stringify(obj) && _textMarker.className &&
- _textMarker.className.indexOf(className) > -1) {
+ if (
+ JSON.stringify(pos) === JSON.stringify(obj) &&
+ _textMarker.className &&
+ _textMarker.className.indexOf(className) > -1
+ ) {
addTextMarkers.splice(j, 1)
j--
found = true
break
}
}
- if (!found && _textMarker.className && _textMarker.className.indexOf('authorship-inline') > -1) {
+ if (
+ !found &&
+ _textMarker.className &&
+ _textMarker.className.indexOf('authorship-inline') > -1
+ ) {
_textMarker.clear()
}
}
for (let i = 0; i < addTextMarkers.length; i++) {
- let textMarker = addTextMarkers[i]
- let author = authors[textMarker.userid]
+ const textMarker = addTextMarkers[i]
+ const author = authors[textMarker.userid]
const rgbcolor = hex2rgb(author.color)
const colorString = `rgba(${rgbcolor.red},${rgbcolor.green},${rgbcolor.blue},0.7)`
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} }`
addStyleRule(rule)
editor.markText(textMarker.pos[0], textMarker.pos[1], {
@@ -1951,19 +2342,22 @@ function updateAuthorshipInner () {
}
}
function iterateLine (line) {
- var lineNumber = line.lineNo()
- var currMark = authorMarks[lineNumber]
- var author = currMark ? authors[currMark.gutter.userid] : null
+ const lineNumber = line.lineNo()
+ const currMark = authorMarks[lineNumber]
+ const author = currMark ? authors[currMark.gutter.userid] : null
if (currMark && author) {
- let className = 'authorship-gutter-' + author.color.substr(1)
+ const className = 'authorship-gutter-' + author.color.substr(1)
const gutters = line.gutterMarkers
- if (!gutters || !gutters['authorship-gutters'] ||
- !gutters['authorship-gutters'].className ||
- !gutters['authorship-gutters'].className.indexOf(className) < 0) {
+ if (
+ !gutters ||
+ !gutters['authorship-gutters'] ||
+ !gutters['authorship-gutters'].className ||
+ !gutters['authorship-gutters'].className.indexOf(className) < 0
+ ) {
const styleString = `border-left: 3px solid ${author.color}; height: ${defaultTextHeight}px; margin-left: 3px;`
const rule = `.${className} { ${styleString} }`
addStyleRule(rule)
- var gutter = $('<div>', {
+ const gutter = $('<div>', {
class: 'authorship-gutter ' + className,
title: author.name
})
@@ -1973,8 +2367,8 @@ function iterateLine (line) {
editor.setGutterMarker(line, 'authorship-gutters', null)
}
if (currMark && currMark.textmarkers.length > 0) {
- for (var i = 0; i < currMark.textmarkers.length; i++) {
- let textMarker = currMark.textmarkers[i]
+ for (let i = 0; i < currMark.textmarkers.length; i++) {
+ const textMarker = currMark.textmarkers[i]
if (textMarker.userid !== currMark.gutter.userid) {
addTextMarkers.push(textMarker)
}
@@ -1985,17 +2379,17 @@ editorInstance.on('update', function () {
$('.authorship-gutter:not([data-original-title])').tooltip({
container: '.CodeMirror-lines',
placement: 'right',
- delay: { 'show': 500, 'hide': 100 }
+ delay: { show: 500, hide: 100 }
})
$('.authorship-inline:not([data-original-title])').tooltip({
container: '.CodeMirror-lines',
placement: 'bottom',
- delay: { 'show': 500, 'hide': 100 }
+ delay: { show: 500, hide: 100 }
})
// clear tooltip which described element has been removed
$('[id^="tooltip"]').each(function (index, element) {
- var $ele = $(element)
- if ($('[aria-describedby="' + $ele.attr('id') + '"]').length <= 0) $ele.remove()
+ const $ele = $(element)
+ if ($('[aria-describedby="' + $ele.attr('id') + '"]').length <= 0) { $ele.remove() }
})
})
socket.on('check', function (data) {
@@ -2006,7 +2400,7 @@ socket.on('permission', function (data) {
updatePermission(data.permission)
})
-var permission = null
+let permission = null
socket.on('refresh', function (data) {
// console.debug(data);
editorInstance.config.docmaxlength = data.docmaxlength
@@ -2015,13 +2409,17 @@ socket.on('refresh', function (data) {
updatePermission(data.permission)
if (!window.loaded) {
// auto change mode if no content detected
- var nocontent = editor.getValue().length <= 0
+ const nocontent = editor.getValue().length <= 0
if (nocontent) {
- if (visibleXS) { appState.currentMode = modeType.edit } else { appState.currentMode = modeType.both }
+ if (visibleXS) {
+ appState.currentMode = modeType.edit
+ } else {
+ appState.currentMode = modeType.both
+ }
}
// parse mode from url
if (window.location.search.length > 0) {
- var urlMode = modeType[window.location.search.substr(1)]
+ const urlMode = modeType[window.location.search.substr(1)]
if (urlMode) appState.currentMode = urlMode
}
changeMode(appState.currentMode)
@@ -2041,23 +2439,34 @@ socket.on('refresh', function (data) {
scrollToHash()
}, 1)
}
- if (editor.getOption('readOnly')) { editor.setOption('readOnly', false) }
+ if (editor.getOption('readOnly')) {
+ editor.setOption('readOnly', false)
+ }
})
-var EditorClient = ot.EditorClient
-var SocketIOAdapter = ot.SocketIOAdapter
-var CodeMirrorAdapter = ot.CodeMirrorAdapter
-var cmClient = null
-var synchronized_ = null
+const EditorClient = ot.EditorClient
+const SocketIOAdapter = ot.SocketIOAdapter
+const CodeMirrorAdapter = ot.CodeMirrorAdapter
+let cmClient = null
+let synchronized_ = null
function havePendingOperation () {
- return !!((cmClient && cmClient.state && cmClient.state.hasOwnProperty('outstanding')))
+ return !!(
+ cmClient &&
+ cmClient.state &&
+ Object.prototype.hasOwnProperty.call(cmClient, 'outstanding')
+ )
}
socket.on('doc', function (obj) {
- var body = obj.str
- var bodyMismatch = editor.getValue() !== body
- var setDoc = !cmClient || (cmClient && (cmClient.revision === -1 || (cmClient.revision !== obj.revision && !havePendingOperation()))) || obj.force
+ const body = obj.str
+ const bodyMismatch = editor.getValue() !== body
+ const setDoc =
+ !cmClient ||
+ (cmClient &&
+ (cmClient.revision === -1 ||
+ (cmClient.revision !== obj.revision && !havePendingOperation()))) ||
+ obj.force
saveInfo()
if (setDoc && bodyMismatch) {
@@ -2079,8 +2488,10 @@ socket.on('doc', function (obj) {
if (!cmClient) {
cmClient = window.cmClient = new EditorClient(
- obj.revision, obj.clients,
- new SocketIOAdapter(socket), new CodeMirrorAdapter(editor)
+ obj.revision,
+ obj.clients,
+ new SocketIOAdapter(socket),
+ new CodeMirrorAdapter(editor)
)
synchronized_ = cmClient.state
} else if (setDoc) {
@@ -2115,91 +2526,120 @@ socket.on('operation', function () {
})
socket.on('online users', function (data) {
- if (debug) { console.debug(data) }
+ if (debug) {
+ console.debug(data)
+ }
onlineUsers = data.users
updateOnlineStatus()
- $('.CodeMirror-other-cursors').children().each(function (key, value) {
- var found = false
- for (var i = 0; i < data.users.length; i++) {
- var user = data.users[i]
- if ($(this).attr('id') === user.id) { found = true }
- }
- if (!found) {
- $(this).stop(true).fadeOut('normal', function () {
- $(this).remove()
- })
+ $('.CodeMirror-other-cursors')
+ .children()
+ .each(function (key, value) {
+ let found = false
+ for (let i = 0; i < data.users.length; i++) {
+ const user = data.users[i]
+ if ($(this).attr('id') === user.id) {
+ found = true
+ }
+ }
+ if (!found) {
+ $(this)
+ .stop(true)
+ .fadeOut('normal', function () {
+ $(this).remove()
+ })
+ }
+ })
+ for (let i = 0; i < data.users.length; i++) {
+ const user = data.users[i]
+ if (user.id !== socket.id) {
+ buildCursor(user)
+ } else {
+ personalInfo = user
}
- })
- for (var i = 0; i < data.users.length; i++) {
- var user = data.users[i]
- if (user.id !== socket.id) { buildCursor(user) } else { personalInfo = user }
}
})
socket.on('user status', function (data) {
- if (debug) { console.debug(data) }
- for (var i = 0; i < onlineUsers.length; i++) {
+ if (debug) {
+ console.debug(data)
+ }
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === data.id) {
onlineUsers[i] = data
}
}
updateOnlineStatus()
- if (data.id !== socket.id) { buildCursor(data) }
+ if (data.id !== socket.id) {
+ buildCursor(data)
+ }
})
socket.on('cursor focus', function (data) {
- if (debug) { console.debug(data) }
- for (var i = 0; i < onlineUsers.length; i++) {
+ if (debug) {
+ console.debug(data)
+ }
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === data.id) {
onlineUsers[i].cursor = data.cursor
}
}
- if (data.id !== socket.id) { buildCursor(data) }
+ if (data.id !== socket.id) {
+ buildCursor(data)
+ }
// force show
- var cursor = $('div[data-clientid="' + data.id + '"]')
+ const cursor = $('div[data-clientid="' + data.id + '"]')
if (cursor.length > 0) {
cursor.stop(true).fadeIn()
}
})
socket.on('cursor activity', function (data) {
- if (debug) { console.debug(data) }
- for (var i = 0; i < onlineUsers.length; i++) {
+ if (debug) {
+ console.debug(data)
+ }
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === data.id) {
onlineUsers[i].cursor = data.cursor
}
}
- if (data.id !== socket.id) { buildCursor(data) }
+ if (data.id !== socket.id) {
+ buildCursor(data)
+ }
})
socket.on('cursor blur', function (data) {
- if (debug) { console.debug(data) }
- for (var i = 0; i < onlineUsers.length; i++) {
+ if (debug) {
+ console.debug(data)
+ }
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === data.id) {
onlineUsers[i].cursor = null
}
}
- if (data.id !== socket.id) { buildCursor(data) }
+ if (data.id !== socket.id) {
+ buildCursor(data)
+ }
// force hide
- var cursor = $('div[data-clientid="' + data.id + '"]')
+ const cursor = $('div[data-clientid="' + data.id + '"]')
if (cursor.length > 0) {
cursor.stop(true).fadeOut()
}
})
-var options = {
+const options = {
valueNames: ['id', 'name'],
- item: '<li class="ui-user-item">' +
- '<span class="id" style="display:none;"></span>' +
- '<a href="#">' +
- '<span class="pull-left"><i class="ui-user-icon"></i></span><span class="ui-user-name name"></span><span class="pull-right"><i class="fa fa-circle ui-user-status"></i></span>' +
- '</a>' +
- '</li>'
+ item:
+ '<li class="ui-user-item">' +
+ '<span class="id" style="display:none;"></span>' +
+ '<a href="#">' +
+ '<span class="pull-left"><i class="ui-user-icon"></i></span><span class="ui-user-name name"></span><span class="pull-right"><i class="fa fa-circle ui-user-status"></i></span>' +
+ '</a>' +
+ '</li>'
}
-var onlineUserList = new List('online-user-list', options)
-var shortOnlineUserList = new List('short-online-user-list', options)
+const onlineUserList = new List('online-user-list', options)
+const shortOnlineUserList = new List('short-online-user-list', options)
function updateOnlineStatus () {
if (!window.loaded || !socket.connected) return
- var _onlineUsers = deduplicateOnlineUsers(onlineUsers)
+ const _onlineUsers = deduplicateOnlineUsers(onlineUsers)
showStatus(statusType.online, _onlineUsers.length)
- var items = onlineUserList.items
+ const items = onlineUserList.items
// update or remove current list items
for (let i = 0; i < items.length; i++) {
let found = false
@@ -2211,7 +2651,7 @@ function updateOnlineStatus () {
break
}
}
- let id = items[i].values().id
+ const id = items[i].values().id
if (found) {
onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
@@ -2246,23 +2686,57 @@ function sortOnlineUserList (list) {
// sort order by isSelf, login state, idle state, alphabet name, color brightness
list.sort('', {
sortFunction: function (a, b) {
- var usera = a.values()
- var userb = b.values()
- var useraIsSelf = (usera.id === personalInfo.id || (usera.login && usera.userid === personalInfo.userid))
- var userbIsSelf = (userb.id === personalInfo.id || (userb.login && userb.userid === personalInfo.userid))
+ const usera = a.values()
+ const userb = b.values()
+ const useraIsSelf =
+ usera.id === personalInfo.id ||
+ (usera.login && usera.userid === personalInfo.userid)
+ const userbIsSelf =
+ userb.id === personalInfo.id ||
+ (userb.login && userb.userid === personalInfo.userid)
if (useraIsSelf && !userbIsSelf) {
return -1
} else if (!useraIsSelf && userbIsSelf) {
return 1
} else {
- if (usera.login && !userb.login) { return -1 } else if (!usera.login && userb.login) { return 1 } else {
- if (!usera.idle && userb.idle) { return -1 } else if (usera.idle && !userb.idle) { return 1 } else {
- if (usera.name && userb.name && usera.name.toLowerCase() < userb.name.toLowerCase()) {
+ if (usera.login && !userb.login) {
+ return -1
+ } else if (!usera.login && userb.login) {
+ return 1
+ } else {
+ if (!usera.idle && userb.idle) {
+ return -1
+ } else if (usera.idle && !userb.idle) {
+ return 1
+ } else {
+ if (
+ usera.name &&
+ userb.name &&
+ usera.name.toLowerCase() < userb.name.toLowerCase()
+ ) {
return -1
- } else if (usera.name && userb.name && usera.name.toLowerCase() > userb.name.toLowerCase()) {
+ } else if (
+ usera.name &&
+ userb.name &&
+ usera.name.toLowerCase() > userb.name.toLowerCase()
+ ) {
return 1
} else {
- if (usera.color && userb.color && usera.color.toLowerCase() < userb.color.toLowerCase()) { return -1 } else if (usera.color && userb.color && usera.color.toLowerCase() > userb.color.toLowerCase()) { return 1 } else { return 0 }
+ if (
+ usera.color &&
+ userb.color &&
+ usera.color.toLowerCase() < userb.color.toLowerCase()
+ ) {
+ return -1
+ } else if (
+ usera.color &&
+ userb.color &&
+ usera.color.toLowerCase() > userb.color.toLowerCase()
+ ) {
+ return 1
+ } else {
+ return 0
+ }
}
}
}
@@ -2272,11 +2746,11 @@ function sortOnlineUserList (list) {
}
function renderUserStatusList (list) {
- var items = list.items
- for (var j = 0; j < items.length; j++) {
- var item = items[j]
- var userstatus = $(item.elm).find('.ui-user-status')
- var usericon = $(item.elm).find('.ui-user-icon')
+ const items = list.items
+ for (let j = 0; j < items.length; j++) {
+ const item = items[j]
+ const userstatus = $(item.elm).find('.ui-user-status')
+ const usericon = $(item.elm).find('.ui-user-icon')
if (item.values().login && item.values().photo) {
usericon.css('background-image', 'url(' + item.values().photo + ')')
// add 1px more to right, make it feel aligned
@@ -2286,18 +2760,26 @@ function renderUserStatusList (list) {
} else {
usericon.css('background-color', item.values().color)
}
- userstatus.removeClass('ui-user-status-offline ui-user-status-online ui-user-status-idle')
- if (item.values().idle) { userstatus.addClass('ui-user-status-idle') } else { userstatus.addClass('ui-user-status-online') }
+ userstatus.removeClass(
+ 'ui-user-status-offline ui-user-status-online ui-user-status-idle'
+ )
+ if (item.values().idle) {
+ userstatus.addClass('ui-user-status-idle')
+ } else {
+ userstatus.addClass('ui-user-status-online')
+ }
}
}
function deduplicateOnlineUsers (list) {
- var _onlineUsers = []
- for (var i = 0; i < list.length; i++) {
- var user = $.extend({}, list[i])
- if (!user.userid) { _onlineUsers.push(user) } else {
- var found = false
- for (var j = 0; j < _onlineUsers.length; j++) {
+ const _onlineUsers = []
+ for (let i = 0; i < list.length; i++) {
+ const user = $.extend({}, list[i])
+ if (!user.userid) {
+ _onlineUsers.push(user)
+ } else {
+ let found = false
+ for (let j = 0; j < _onlineUsers.length; j++) {
if (_onlineUsers[j].userid === user.userid) {
// keep self color when login
if (user.id === personalInfo.id) {
@@ -2312,29 +2794,39 @@ function deduplicateOnlineUsers (list) {
break
}
}
- if (!found) { _onlineUsers.push(user) }
+ if (!found) {
+ _onlineUsers.push(user)
+ }
}
}
return _onlineUsers
}
-var userStatusCache = null
+let userStatusCache = null
function emitUserStatus (force) {
if (!window.loaded) return
- var type = null
- if (visibleXS) { type = 'xs' } else if (visibleSM) { type = 'sm' } else if (visibleMD) { type = 'md' } else if (visibleLG) { type = 'lg' }
+ let type = null
+ if (visibleXS) {
+ type = 'xs'
+ } else if (visibleSM) {
+ type = 'sm'
+ } else if (visibleMD) {
+ type = 'md'
+ } else if (visibleLG) {
+ type = 'lg'
+ }
- personalInfo['idle'] = idle.isAway
- personalInfo['type'] = type
+ personalInfo.idle = idle.isAway
+ personalInfo.type = type
- for (var i = 0; i < onlineUsers.length; i++) {
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === personalInfo.id) {
onlineUsers[i] = personalInfo
}
}
- var userStatus = {
+ const userStatus = {
idle: idle.isAway,
type: type
}
@@ -2348,24 +2840,24 @@ function emitUserStatus (force) {
function checkCursorTag (coord, ele) {
if (!ele) return // return if element not exists
// set margin
- var tagRightMargin = 0
- var tagBottomMargin = 2
+ const tagRightMargin = 0
+ const tagBottomMargin = 2
// use sizer to get the real doc size (won't count status bar and gutters)
- var docWidth = ui.area.codemirrorSizer.width()
+ const docWidth = ui.area.codemirrorSizer.width()
// get editor size (status bar not count in)
- var editorHeight = ui.area.codemirror.height()
+ const editorHeight = ui.area.codemirror.height()
// get element size
- var width = ele.outerWidth()
- var height = ele.outerHeight()
- var padding = (ele.outerWidth() - ele.width()) / 2
+ const width = ele.outerWidth()
+ const height = ele.outerHeight()
+ const padding = (ele.outerWidth() - ele.width()) / 2
// get coord position
- var left = coord.left
- var top = coord.top
+ const left = coord.left
+ const top = coord.top
// get doc top offset (to workaround with viewport)
- var docTopOffset = ui.area.codemirrorSizerInner.position().top
+ const docTopOffset = ui.area.codemirrorSizerInner.position().top
// set offset
- var offsetLeft = -3
- var offsetTop = defaultTextHeight
+ let offsetLeft = -3
+ let offsetTop = defaultTextHeight
// only do when have width and height
if (width > 0 && height > 0) {
// flip x when element right bound larger than doc width
@@ -2374,8 +2866,12 @@ function checkCursorTag (coord, ele) {
}
// flip y when element bottom bound larger than doc height
// and element top position is larger than element height
- if (top + docTopOffset + height + offsetTop + tagBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + tagBottomMargin) {
- offsetTop = -(height)
+ if (
+ top + docTopOffset + height + offsetTop + tagBottomMargin >
+ Math.max(editor.doc.height, editorHeight) &&
+ top + docTopOffset > height + tagBottomMargin
+ ) {
+ offsetTop = -height
}
}
// set position
@@ -2386,10 +2882,10 @@ function checkCursorTag (coord, ele) {
function buildCursor (user) {
if (appState.currentMode === modeType.view) return
if (!user.cursor) return
- var coord = editor.charCoords(user.cursor, 'windows')
+ const coord = editor.charCoords(user.cursor, 'windows')
coord.left = coord.left < 4 ? 4 : coord.left
coord.top = coord.top < 0 ? 0 : coord.top
- var iconClass = 'fa-user'
+ let iconClass = 'fa-user'
switch (user.type) {
case 'xs':
iconClass = 'fa-mobile'
@@ -2405,19 +2901,29 @@ function buildCursor (user) {
break
}
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-ch', user.cursor.ch)
cursor.attr('data-offset-left', 0)
cursor.attr('data-offset-top', 0)
- let cursorbar = $('<div class="cursorbar">&nbsp;</div>')
+ const cursorbar = $('<div class="cursorbar">&nbsp;</div>')
cursorbar[0].style.height = defaultTextHeight + 'px'
cursorbar[0].style.borderLeft = '2px solid ' + user.color
- var icon = '<i class="fa ' + iconClass + '"></i>'
+ const icon = '<i class="fa ' + iconClass + '"></i>'
- let cursortag = $('<div class="cursortag">' + icon + '&nbsp;<span class="name">' + user.name + '</span></div>')
+ const cursortag = $(
+ '<div class="cursortag">' +
+ icon +
+ '&nbsp;<span class="name">' +
+ user.name +
+ '</span></div>'
+ )
// cursortag[0].style.background = color;
cursortag[0].style.color = user.color
@@ -2425,28 +2931,43 @@ function buildCursor (user) {
cursortag.delay(2000).fadeOut('fast')
cursor.hover(
function () {
- if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeIn('fast') }
+ if (cursor.attr('data-mode') === 'hover') {
+ cursortag.stop(true).fadeIn('fast')
+ }
},
function () {
- if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeOut('fast') }
- })
+ if (cursor.attr('data-mode') === 'hover') {
+ cursortag.stop(true).fadeOut('fast')
+ }
+ }
+ )
- var hideCursorTagDelay = 2000
- var hideCursorTagTimer = null
+ const hideCursorTagDelay = 2000
+ let hideCursorTagTimer = null
- var switchMode = function (ele) {
- if (ele.attr('data-mode') === 'state') { ele.attr('data-mode', 'hover') } else if (ele.attr('data-mode') === 'hover') { ele.attr('data-mode', 'state') }
+ const switchMode = function (ele) {
+ if (ele.attr('data-mode') === 'state') {
+ ele.attr('data-mode', 'hover')
+ } else if (ele.attr('data-mode') === 'hover') {
+ ele.attr('data-mode', 'state')
+ }
}
- var switchTag = function (ele) {
- if (ele.css('display') === 'none') { ele.stop(true).fadeIn('fast') } else { ele.stop(true).fadeOut('fast') }
+ const switchTag = function (ele) {
+ if (ele.css('display') === 'none') {
+ ele.stop(true).fadeIn('fast')
+ } else {
+ ele.stop(true).fadeOut('fast')
+ }
}
- var hideCursorTag = function () {
- if (cursor.attr('data-mode') === 'hover') { cursortag.fadeOut('fast') }
+ const hideCursorTag = function () {
+ if (cursor.attr('data-mode') === 'hover') {
+ cursortag.fadeOut('fast')
+ }
}
cursor.on('touchstart', function (e) {
- var display = cursortag.css('display')
+ const display = cursortag.css('display')
cursortag.stop(true).fadeIn('fast')
clearTimeout(hideCursorTagTimer)
hideCursorTagTimer = setTimeout(hideCursorTag, hideCursorTagDelay)
@@ -2456,7 +2977,9 @@ function buildCursor (user) {
}
})
cursortag.on('mousedown touchstart', function (e) {
- if (cursor.attr('data-mode') === 'state') { switchTag(cursortag) }
+ if (cursor.attr('data-mode') === 'state') {
+ switchTag(cursortag)
+ }
switchMode(cursor)
e.preventDefault()
e.stopPropagation()
@@ -2469,19 +2992,21 @@ function buildCursor (user) {
cursor[0].style.top = coord.top + 'px'
$('.CodeMirror-other-cursors').append(cursor)
- if (!user.idle) { cursor.stop(true).fadeIn() }
+ if (!user.idle) {
+ cursor.stop(true).fadeIn()
+ }
checkCursorTag(coord, cursortag)
} 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-ch', user.cursor.ch)
- let cursorbar = cursor.find('.cursorbar')
+ const cursorbar = cursor.find('.cursorbar')
cursorbar[0].style.height = defaultTextHeight + 'px'
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('.name').text(user.name)
@@ -2489,16 +3014,23 @@ function buildCursor (user) {
cursor[0].style.left = coord.left + 'px'
cursor[0].style.top = coord.top + 'px'
} else {
- cursor.animate({
- 'left': coord.left,
- 'top': coord.top
- }, {
- duration: cursorAnimatePeriod,
- queue: false
- })
+ cursor.animate(
+ {
+ left: coord.left,
+ top: coord.top
+ },
+ {
+ duration: cursorAnimatePeriod,
+ queue: false
+ }
+ )
}
- if (user.idle && cursor.css('display') !== 'none') { cursor.stop(true).fadeOut() } else if (!user.idle && cursor.css('display') === 'none') { cursor.stop(true).fadeIn() }
+ if (user.idle && cursor.css('display') !== 'none') {
+ cursor.stop(true).fadeOut()
+ } else if (!user.idle && cursor.css('display') === 'none') {
+ cursor.stop(true).fadeIn()
+ }
checkCursorTag(coord, cursortag)
}
@@ -2506,18 +3038,23 @@ function buildCursor (user) {
// editor actions
function removeNullByte (cm, change) {
- var str = change.text.join('\n')
+ const str = change.text.join('\n')
// eslint-disable-next-line no-control-regex
if (/\u0000/g.test(str) && change.update) {
- // eslint-disable-next-line no-control-regex
- change.update(change.from, change.to, str.replace(/\u0000/g, '').split('\n'))
+ change.update(
+ change.from,
+ change.to,
+ // eslint-disable-next-line no-control-regex
+ str.replace(/\u0000/g, '').split('\n')
+ )
}
}
function enforceMaxLength (cm, change) {
- var maxLength = cm.getOption('maxLength')
+ const maxLength = cm.getOption('maxLength')
if (maxLength && change.update) {
- var str = change.text.join('\n')
- var delta = str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from))
+ let str = change.text.join('\n')
+ let delta =
+ str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from))
if (delta <= 0) {
return false
}
@@ -2530,14 +3067,16 @@ function enforceMaxLength (cm, change) {
}
return false
}
-var ignoreEmitEvents = ['setValue', 'ignoreHistory']
+const ignoreEmitEvents = ['setValue', 'ignoreHistory']
editorInstance.on('beforeChange', function (cm, change) {
- if (debug) { console.debug(change) }
+ if (debug) {
+ console.debug(change)
+ }
removeNullByte(cm, change)
if (enforceMaxLength(cm, change)) {
$('.limit-modal').modal('show')
}
- var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(change.origin) !== -1)
+ const isIgnoreEmitEvent = ignoreEmitEvents.indexOf(change.origin) !== -1
if (!isIgnoreEmitEvent) {
if (!havePermission()) {
change.canceled = true
@@ -2557,7 +3096,9 @@ editorInstance.on('beforeChange', function (cm, change) {
updateTitleReminder()
}
}
- if (cmClient && !socket.connected) { cmClient.editorAdapter.ignoreNextChange = true }
+ if (cmClient && !socket.connected) {
+ cmClient.editorAdapter.ignoreNextChange = true
+ }
})
editorInstance.on('cut', function () {
// na
@@ -2567,9 +3108,9 @@ editorInstance.on('paste', function () {
})
editorInstance.on('changes', function (editor, changes) {
updateHistory()
- var docLength = editor.getValue().length
+ const docLength = editor.getValue().length
// workaround for big documents
- var newViewportMargin = 20
+ let newViewportMargin = 20
if (docLength > 20000) {
newViewportMargin = 1
} else if (docLength > 10000) {
@@ -2582,7 +3123,10 @@ editorInstance.on('changes', function (editor, changes) {
windowResize()
}
checkEditorScrollbar()
- if (ui.area.codemirrorScroll[0].scrollHeight > ui.area.view[0].scrollHeight && editorHasFocus()) {
+ if (
+ ui.area.codemirrorScroll[0].scrollHeight > ui.area.view[0].scrollHeight &&
+ editorHasFocus()
+ ) {
postUpdateEvent = function () {
syncScrollToView()
postUpdateEvent = null
@@ -2590,12 +3134,12 @@ editorInstance.on('changes', function (editor, changes) {
}
})
editorInstance.on('focus', function (editor) {
- for (var i = 0; i < onlineUsers.length; i++) {
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === personalInfo.id) {
onlineUsers[i].cursor = editor.getCursor()
}
}
- personalInfo['cursor'] = editor.getCursor()
+ personalInfo.cursor = editor.getCursor()
socket.emit('cursor focus', editor.getCursor())
})
@@ -2603,12 +3147,12 @@ const cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce)
function cursorActivityInner (editor) {
if (editorHasFocus() && !Visibility.hidden()) {
- for (var i = 0; i < onlineUsers.length; i++) {
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === personalInfo.id) {
onlineUsers[i].cursor = editor.getCursor()
}
}
- personalInfo['cursor'] = editor.getCursor()
+ personalInfo.cursor = editor.getCursor()
socket.emit('cursor activity', editor.getCursor())
}
}
@@ -2632,7 +3176,7 @@ editorInstance.on('beforeSelectionChange', function (doc, selections) {
// borrow from brackets EditorStatusBar.js
if (start.line !== end.line) {
- var lines = end.line - start.line + 1
+ let lines = end.line - start.line + 1
if (end.ch === 0) {
lines--
}
@@ -2650,19 +3194,19 @@ editorInstance.on('beforeSelectionChange', function (doc, selections) {
})
editorInstance.on('blur', function (cm) {
- for (var i = 0; i < onlineUsers.length; i++) {
+ for (let i = 0; i < onlineUsers.length; i++) {
if (onlineUsers[i].id === personalInfo.id) {
onlineUsers[i].cursor = null
}
}
- personalInfo['cursor'] = null
+ personalInfo.cursor = null
socket.emit('cursor blur')
})
function saveInfo () {
- var scrollbarStyle = editor.getOption('scrollbarStyle')
- var left = $(window).scrollLeft()
- var top = $(window).scrollTop()
+ const scrollbarStyle = editor.getOption('scrollbarStyle')
+ const left = $(window).scrollLeft()
+ const top = $(window).scrollTop()
switch (appState.currentMode) {
case modeType.edit:
if (scrollbarStyle === 'native') {
@@ -2688,10 +3232,10 @@ function saveInfo () {
}
function restoreInfo () {
- var scrollbarStyle = editor.getOption('scrollbarStyle')
+ const scrollbarStyle = editor.getOption('scrollbarStyle')
if (lastInfo.needRestore) {
- var line = lastInfo.edit.cursor.line
- var ch = lastInfo.edit.cursor.ch
+ const line = lastInfo.edit.cursor.line
+ const ch = lastInfo.edit.cursor.ch
editor.setCursor(line, ch)
editor.setSelections(lastInfo.edit.selections)
switch (appState.currentMode) {
@@ -2700,8 +3244,8 @@ function restoreInfo () {
$(window).scrollLeft(lastInfo.edit.scroll.left)
$(window).scrollTop(lastInfo.edit.scroll.top)
} else {
- let left = lastInfo.edit.scroll.left
- let top = lastInfo.edit.scroll.top
+ const left = lastInfo.edit.scroll.left
+ const top = lastInfo.edit.scroll.top
editor.scrollIntoView()
editor.scrollTo(left, top)
}
@@ -2711,10 +3255,8 @@ function restoreInfo () {
$(window).scrollTop(lastInfo.view.scroll.top)
break
case modeType.both:
- let left = lastInfo.edit.scroll.left
- let top = lastInfo.edit.scroll.top
editor.scrollIntoView()
- editor.scrollTo(left, top)
+ editor.scrollTo(lastInfo.edit.scroll.left, lastInfo.edit.scroll.top)
ui.area.view.scrollLeft(lastInfo.view.scroll.left)
ui.area.view.scrollTop(lastInfo.view.scroll.top)
break
@@ -2731,27 +3273,30 @@ function refreshView () {
updateViewInner()
}
-var updateView = _.debounce(function () {
+const updateView = _.debounce(function () {
editor.operation(updateViewInner)
}, updateViewDebounce)
-var lastResult = null
-var postUpdateEvent = null
+let lastResult = null
+let postUpdateEvent = null
function updateViewInner () {
if (appState.currentMode === modeType.edit || !isDirty) return
- var value = editor.getValue()
- var lastMeta = md.meta
+ const value = editor.getValue()
+ const lastMeta = md.meta
md.meta = {}
delete md.metaError
- var rendered = md.render(value)
+ let rendered = md.render(value)
if (md.meta.type && md.meta.type === 'slide') {
ui.area.view.addClass('black')
- var slideOptions = {
+ const slideOptions = {
separator: '^(\r\n?|\n)---(\r\n?|\n)$',
verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$'
}
- var slides = window.RevealMarkdown.slidify(editor.getValue(), slideOptions)
+ const slides = window.RevealMarkdown.slidify(
+ editor.getValue(),
+ slideOptions
+ )
ui.area.markdown.html(slides)
window.RevealMarkdown.initialize()
// prevent XSS
@@ -2769,14 +3314,22 @@ function updateViewInner () {
}
// only render again when meta changed
if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) {
- parseMeta(md, ui.area.codemirror, ui.area.markdown, $('#ui-toc'), $('#ui-toc-affix'))
+ parseMeta(
+ md,
+ ui.area.codemirror,
+ ui.area.markdown,
+ $('#ui-toc'),
+ $('#ui-toc-affix')
+ )
rendered = md.render(value)
}
// prevent XSS
rendered = preventXSS(rendered)
- var result = postProcess(rendered).children().toArray()
+ const result = postProcess(rendered).children().toArray()
partialUpdate(result, lastResult, ui.area.markdown.children().toArray())
- if (result && lastResult && result.length !== lastResult.length) { updateDataAttrs(result, ui.area.markdown.children().toArray()) }
+ if (result && lastResult && result.length !== lastResult.length) {
+ updateDataAttrs(result, ui.area.markdown.children().toArray())
+ }
lastResult = $(result).clone()
}
removeDOMEvents(ui.area.markdown)
@@ -2794,12 +3347,14 @@ function updateViewInner () {
clearMap()
// buildMap();
updateTitleReminder()
- if (postUpdateEvent && typeof postUpdateEvent === 'function') { postUpdateEvent() }
+ if (postUpdateEvent && typeof postUpdateEvent === 'function') {
+ postUpdateEvent()
+ }
}
-var updateHistoryDebounce = 600
+const updateHistoryDebounce = 600
-var updateHistory = _.debounce(updateHistoryInner, updateHistoryDebounce)
+const updateHistory = _.debounce(updateHistoryInner, updateHistoryDebounce)
function updateHistoryInner () {
writeHistory(renderFilename(ui.area.markdown), renderTags(ui.area.markdown))
@@ -2807,50 +3362,59 @@ function updateHistoryInner () {
function updateDataAttrs (src, des) {
// sync data attr startline and endline
- for (var 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-endline')
}
}
function partialUpdate (src, tar, des) {
- if (!src || src.length === 0 || !tar || tar.length === 0 || !des || des.length === 0) {
+ if (
+ !src ||
+ src.length === 0 ||
+ !tar ||
+ tar.length === 0 ||
+ !des ||
+ des.length === 0
+ ) {
ui.area.markdown.html(src)
return
}
- if (src.length === tar.length) { // same length
+ if (src.length === tar.length) {
+ // same length
for (let i = 0; i < src.length; i++) {
copyAttribute(src[i], des[i], 'data-startline')
copyAttribute(src[i], des[i], 'data-endline')
- var rawSrc = cloneAndRemoveDataAttr(src[i])
- var rawTar = cloneAndRemoveDataAttr(tar[i])
+ const rawSrc = cloneAndRemoveDataAttr(src[i])
+ const rawTar = cloneAndRemoveDataAttr(tar[i])
if (rawSrc.outerHTML !== rawTar.outerHTML) {
// console.debug(rawSrc);
// console.debug(rawTar);
$(des[i]).replaceWith(src[i])
}
}
- } else { // diff length
- var start = 0
+ } else {
+ // diff length
+ let start = 0
// find diff start position
for (let i = 0; i < tar.length; i++) {
// copyAttribute(src[i], des[i], 'data-startline');
// copyAttribute(src[i], des[i], 'data-endline');
- let rawSrc = cloneAndRemoveDataAttr(src[i])
- let rawTar = cloneAndRemoveDataAttr(tar[i])
+ const rawSrc = cloneAndRemoveDataAttr(src[i])
+ const rawTar = cloneAndRemoveDataAttr(tar[i])
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
start = i
break
}
}
// find diff end position
- var srcEnd = 0
- var tarEnd = 0
+ let srcEnd = 0
+ let tarEnd = 0
for (let i = 0; i < src.length; i++) {
// copyAttribute(src[i], des[i], 'data-startline');
// copyAttribute(src[i], des[i], 'data-endline');
- let rawSrc = cloneAndRemoveDataAttr(src[i])
- let rawTar = cloneAndRemoveDataAttr(tar[i])
+ const rawSrc = cloneAndRemoveDataAttr(src[i])
+ const rawTar = cloneAndRemoveDataAttr(tar[i])
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
start = i
break
@@ -2858,12 +3422,12 @@ function partialUpdate (src, tar, des) {
}
// tar end
for (let i = 1; i <= tar.length + 1; i++) {
- let srcLength = src.length
- let tarLength = tar.length
+ const srcLength = src.length
+ const tarLength = tar.length
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
- let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
- let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
+ const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
+ const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
tarEnd = tar.length - i
break
@@ -2871,25 +3435,35 @@ function partialUpdate (src, tar, des) {
}
// src end
for (let i = 1; i <= src.length + 1; i++) {
- let srcLength = src.length
- let tarLength = tar.length
+ const srcLength = src.length
+ const tarLength = tar.length
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
// copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
- let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
- let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
+ const rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
+ const rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
srcEnd = src.length - i
break
}
}
// check if tar end overlap tar start
- var overlap = 0
- for (var i = start; i >= 0; i--) {
- var rawTarStart = cloneAndRemoveDataAttr(tar[i - 1])
- var rawTarEnd = cloneAndRemoveDataAttr(tar[tarEnd + 1 + start - i])
- if (rawTarStart && rawTarEnd && rawTarStart.outerHTML === rawTarEnd.outerHTML) { overlap++ } else { break }
+ let overlap = 0
+ for (let i = start; i >= 0; i--) {
+ const rawTarStart = cloneAndRemoveDataAttr(tar[i - 1])
+ const rawTarEnd = cloneAndRemoveDataAttr(tar[tarEnd + 1 + start - i])
+ if (
+ rawTarStart &&
+ rawTarEnd &&
+ rawTarStart.outerHTML === rawTarEnd.outerHTML
+ ) {
+ overlap++
+ } else {
+ break
+ }
+ }
+ if (debug) {
+ console.debug('overlap:' + overlap)
}
- if (debug) { console.debug('overlap:' + overlap) }
// show diff content
if (debug) {
console.debug('start:' + start)
@@ -2898,10 +3472,10 @@ function partialUpdate (src, tar, des) {
}
tarEnd += overlap
srcEnd += overlap
- var repeatAdd = (start - srcEnd) < (start - tarEnd)
- var repeatDiff = Math.abs(srcEnd - tarEnd) - 1
+ const repeatAdd = start - srcEnd < start - tarEnd
+ const repeatDiff = Math.abs(srcEnd - tarEnd) - 1
// push new elements
- var newElements = []
+ const newElements = []
if (srcEnd >= start) {
for (let j = start; j <= srcEnd; j++) {
if (!src[j]) continue
@@ -2914,7 +3488,7 @@ function partialUpdate (src, tar, des) {
}
}
// push remove elements
- var removeElements = []
+ const removeElements = []
if (tarEnd >= start) {
for (let j = start; j <= tarEnd; j++) {
if (!des[j]) continue
@@ -2931,28 +3505,38 @@ function partialUpdate (src, tar, des) {
console.debug('ADD ELEMENTS')
console.debug(newElements.join('\n'))
}
- if (des[start]) { $(newElements.join('')).insertBefore(des[start]) } else { $(newElements.join('')).insertAfter(des[start - 1]) }
+ if (des[start]) {
+ $(newElements.join('')).insertBefore(des[start])
+ } else {
+ $(newElements.join('')).insertAfter(des[start - 1])
+ }
// remove elements
- if (debug) { console.debug('REMOVE ELEMENTS') }
+ if (debug) {
+ console.debug('REMOVE ELEMENTS')
+ }
for (let j = 0; j < removeElements.length; j++) {
if (debug) {
console.debug(removeElements[j].outerHTML)
}
- if (removeElements[j]) { $(removeElements[j]).remove() }
+ if (removeElements[j]) {
+ $(removeElements[j]).remove()
+ }
}
}
}
function cloneAndRemoveDataAttr (el) {
if (!el) return
- var rawEl = $(el).clone()
+ const rawEl = $(el).clone()
rawEl.removeAttr('data-startline data-endline')
rawEl.find('[data-startline]').removeAttr('data-startline data-endline')
return rawEl[0]
}
function copyAttribute (src, des, attr) {
- if (src && src.getAttribute(attr) && des) { des.setAttribute(attr, src.getAttribute(attr)) }
+ if (src && src.getAttribute(attr) && des) {
+ des.setAttribute(attr, src.getAttribute(attr))
+ }
}
if ($('.cursor-menu').length <= 0) {
@@ -2960,69 +3544,83 @@ if ($('.cursor-menu').length <= 0) {
}
function reverseSortCursorMenu (dropdown) {
- var items = dropdown.find('.textcomplete-item')
+ const items = dropdown.find('.textcomplete-item')
items.sort(function (a, b) {
return $(b).attr('data-index') - $(a).attr('data-index')
})
return items
}
-var checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle)
+const checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle)
function checkCursorMenuInner () {
// get element
- var dropdown = $('.cursor-menu > .dropdown-menu')
+ const dropdown = $('.cursor-menu > .dropdown-menu')
// return if not exists
if (dropdown.length <= 0) return
// set margin
- var menuRightMargin = 10
- var menuBottomMargin = 4
+ const menuRightMargin = 10
+ const menuBottomMargin = 4
// use sizer to get the real doc size (won't count status bar and gutters)
- var docWidth = ui.area.codemirrorSizer.width()
+ const docWidth = ui.area.codemirrorSizer.width()
// get editor size (status bar not count in)
- var editorHeight = ui.area.codemirror.height()
+ const editorHeight = ui.area.codemirror.height()
// get element size
- var width = dropdown.outerWidth()
- var height = dropdown.outerHeight()
+ const width = dropdown.outerWidth()
+ const height = dropdown.outerHeight()
// get cursor
- var cursor = editor.getCursor()
+ const cursor = editor.getCursor()
// set element cursor data
- if (!dropdown.hasClass('CodeMirror-other-cursor')) { dropdown.addClass('CodeMirror-other-cursor') }
+ if (!dropdown.hasClass('CodeMirror-other-cursor')) {
+ dropdown.addClass('CodeMirror-other-cursor')
+ }
dropdown.attr('data-line', cursor.line)
dropdown.attr('data-ch', cursor.ch)
// get coord position
- var coord = editor.charCoords({
- line: cursor.line,
- ch: cursor.ch
- }, 'windows')
- var left = coord.left
- var top = coord.top
+ const coord = editor.charCoords(
+ {
+ line: cursor.line,
+ ch: cursor.ch
+ },
+ 'windows'
+ )
+ const left = coord.left
+ const top = coord.top
// get doc top offset (to workaround with viewport)
- var docTopOffset = ui.area.codemirrorSizerInner.position().top
+ const docTopOffset = ui.area.codemirrorSizerInner.position().top
// set offset
- var offsetLeft = 0
- var offsetTop = defaultTextHeight
+ let offsetLeft = 0
+ let offsetTop = defaultTextHeight
// set up side down
window.upSideDown = false
- var lastUpSideDown = window.upSideDown = false
+ let lastUpSideDown = (window.upSideDown = false)
// only do when have width and height
if (width > 0 && height > 0) {
// make element right bound not larger than doc width
- if (left + width + offsetLeft + menuRightMargin > docWidth) { offsetLeft = -(left + width - docWidth + menuRightMargin) }
+ if (left + width + offsetLeft + menuRightMargin > docWidth) {
+ offsetLeft = -(left + width - docWidth + menuRightMargin)
+ }
// flip y when element bottom bound larger than doc height
// and element top position is larger than element height
- if (top + docTopOffset + height + offsetTop + menuBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + menuBottomMargin) {
+ if (
+ top + docTopOffset + height + offsetTop + menuBottomMargin >
+ Math.max(editor.doc.height, editorHeight) &&
+ top + docTopOffset > height + menuBottomMargin
+ ) {
offsetTop = -(height + menuBottomMargin)
// reverse sort menu because upSideDown
dropdown.html(reverseSortCursorMenu(dropdown))
window.upSideDown = true
}
- var textCompleteDropdown = $(editor.getInputField()).data('textComplete').dropdown
+ const textCompleteDropdown = $(editor.getInputField()).data('textComplete')
+ .dropdown
lastUpSideDown = textCompleteDropdown.upSideDown
textCompleteDropdown.upSideDown = window.upSideDown
}
// make menu scroll top only if upSideDown changed
- if (window.upSideDown !== lastUpSideDown) { dropdown.scrollTop(dropdown[0].scrollHeight) }
+ if (window.upSideDown !== lastUpSideDown) {
+ dropdown.scrollTop(dropdown[0].scrollHeight)
+ }
// set element offset data
dropdown.attr('data-offset-left', offsetLeft)
dropdown.attr('data-offset-top', offsetTop)
@@ -3033,33 +3631,37 @@ function checkCursorMenuInner () {
function checkInIndentCode () {
// if line starts with tab or four spaces is a code block
- var line = editor.getLine(editor.getCursor().line)
- var isIndentCode = ((line.substr(0, 4) === ' ') || (line.substr(0, 1) === '\t'))
+ const line = editor.getLine(editor.getCursor().line)
+ const isIndentCode =
+ line.substr(0, 4) === ' ' || line.substr(0, 1) === '\t'
return isIndentCode
}
-var isInCode = false
+let isInCode = false
function checkInCode () {
isInCode = checkAbove(matchInCode) || checkInIndentCode()
}
function checkAbove (method) {
- var cursor = editor.getCursor()
- var text = []
- for (var i = 0; i < cursor.line; i++) { // contain current line
+ const cursor = editor.getCursor()
+ let text = []
+ for (let i = 0; i < cursor.line; i++) {
+ // contain current line
text.push(editor.getLine(i))
}
- text = text.join('\n') + '\n' + editor.getLine(cursor.line).slice(0, cursor.ch)
+ text =
+ text.join('\n') + '\n' + editor.getLine(cursor.line).slice(0, cursor.ch)
// console.debug(text);
return method(text)
}
function checkBelow (method) {
- var cursor = editor.getCursor()
- var count = editor.lineCount()
- var text = []
- for (var i = cursor.line + 1; i < count; i++) { // contain current line
+ const cursor = editor.getCursor()
+ const count = editor.lineCount()
+ let text = []
+ for (let i = cursor.line + 1; i < count; i++) {
+ // contain current line
text.push(editor.getLine(i))
}
text = editor.getLine(cursor.line).slice(cursor.ch) + '\n' + text.join('\n')
@@ -3068,7 +3670,7 @@ function checkBelow (method) {
}
function matchInCode (text) {
- var match
+ let match
match = text.match(/`{3,}/g)
if (match && match.length % 2) {
return true
@@ -3082,8 +3684,8 @@ function matchInCode (text) {
}
}
-var isInContainer = false
-var isInContainerSyntax = false
+let isInContainer = false
+let isInContainerSyntax = false
function checkInContainer () {
isInContainer = checkAbove(matchInContainer) && !checkInIndentCode()
@@ -3091,13 +3693,12 @@ function checkInContainer () {
function checkInContainerSyntax () {
// if line starts with :::, it's in container syntax
- var line = editor.getLine(editor.getCursor().line)
- isInContainerSyntax = (line.substr(0, 3) === ':::')
+ const line = editor.getLine(editor.getCursor().line)
+ isInContainerSyntax = line.substr(0, 3) === ':::'
}
function matchInContainer (text) {
- var match
- match = text.match(/:{3,}/g)
+ const match = text.match(/:{3,}/g)
if (match && match.length % 2) {
return true
} else {
@@ -3106,194 +3707,244 @@ function matchInContainer (text) {
}
$(editor.getInputField())
- .textcomplete([
- { // emoji strategy
- match: /(^|\n|\s)\B:([-+\w]*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line)
- term = line.match(this.match)[2]
- var list = []
- $.map(window.emojify.emojiNames, function (emoji) {
- if (emoji.indexOf(term) === 0) { // match at first character
- list.push(emoji)
+ .textcomplete(
+ [
+ {
+ // emoji strategy
+ match: /(^|\n|\s)\B:([-+\w]*)$/,
+ search: function (term, callback) {
+ const line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[2]
+ const list = []
+ $.map(window.emojify.emojiNames, function (emoji) {
+ if (emoji.indexOf(term) === 0) {
+ // match at first character
+ list.push(emoji)
+ }
+ })
+ $.map(window.emojify.emojiNames, function (emoji) {
+ if (emoji.indexOf(term) !== -1) {
+ // match inside the word
+ list.push(emoji)
+ }
+ })
+ callback(list)
+ },
+ template: function (value) {
+ return (
+ '<img class="emoji" src="' +
+ serverurl +
+ '/build/emojify.js/dist/images/basic/' +
+ value +
+ '.png"></img> ' +
+ value
+ )
+ },
+ replace: function (value) {
+ return '$1:' + value + ': '
+ },
+ index: 1,
+ context: function (text) {
+ checkInCode()
+ checkInContainer()
+ checkInContainerSyntax()
+ return !isInCode && !isInContainerSyntax
+ }
+ },
+ {
+ // Code block language strategy
+ langs: supportCodeModes,
+ charts: supportCharts,
+ match: /(^|\n)```(\w+)$/,
+ search: function (term, callback) {
+ const line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[2]
+ const list = []
+ $.map(this.langs, function (lang) {
+ if (lang.indexOf(term) === 0 && lang !== term) {
+ list.push(lang)
+ }
+ })
+ $.map(this.charts, function (chart) {
+ if (chart.indexOf(term) === 0 && chart !== term) {
+ list.push(chart)
+ }
+ })
+ callback(list)
+ },
+ replace: function (lang) {
+ let ending = ''
+ if (!checkBelow(matchInCode)) {
+ ending = '\n\n```'
}
- })
- $.map(window.emojify.emojiNames, function (emoji) {
- if (emoji.indexOf(term) !== -1) { // match inside the word
- list.push(emoji)
+ if (this.langs.indexOf(lang) !== -1) {
+ return '$1```' + lang + '=' + ending
+ } else if (this.charts.indexOf(lang) !== -1) {
+ return '$1```' + lang + ending
}
- })
- callback(list)
- },
- template: function (value) {
- return '<img class="emoji" src="' + serverurl + '/build/emojify.js/dist/images/basic/' + value + '.png"></img> ' + value
- },
- replace: function (value) {
- return '$1:' + value + ': '
- },
- index: 1,
- context: function (text) {
- checkInCode()
- checkInContainer()
- checkInContainerSyntax()
- return !isInCode && !isInContainerSyntax
- }
- },
- { // Code block language strategy
- langs: supportCodeModes,
- charts: supportCharts,
- match: /(^|\n)```(\w+)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line)
- term = line.match(this.match)[2]
- var list = []
- $.map(this.langs, function (lang) {
- if (lang.indexOf(term) === 0 && lang !== term) { list.push(lang) }
- })
- $.map(this.charts, function (chart) {
- if (chart.indexOf(term) === 0 && chart !== term) { list.push(chart) }
- })
- callback(list)
- },
- replace: function (lang) {
- var ending = ''
- if (!checkBelow(matchInCode)) {
- ending = '\n\n```'
+ },
+ done: function () {
+ const cursor = editor.getCursor()
+ let text = []
+ text.push(editor.getLine(cursor.line - 1))
+ text.push(editor.getLine(cursor.line))
+ text = text.join('\n')
+ // console.debug(text);
+ if (text === '\n```') {
+ editor.doc.cm.execCommand('goLineUp')
+ }
+ },
+ context: function (text) {
+ return isInCode
}
- if (this.langs.indexOf(lang) !== -1) { return '$1```' + lang + '=' + ending } else if (this.charts.indexOf(lang) !== -1) { return '$1```' + lang + ending }
},
- done: function () {
- var cursor = editor.getCursor()
- var text = []
- text.push(editor.getLine(cursor.line - 1))
- text.push(editor.getLine(cursor.line))
- text = text.join('\n')
- // console.debug(text);
- if (text === '\n```') { editor.doc.cm.execCommand('goLineUp') }
- },
- context: function (text) {
- return isInCode
- }
- },
- { // Container strategy
- containers: supportContainers,
- match: /(^|\n):::(\s*)(\w*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line)
- term = line.match(this.match)[3].trim()
- var list = []
- $.map(this.containers, function (container) {
- if (container.indexOf(term) === 0 && container !== term) { list.push(container) }
- })
- callback(list)
- },
- replace: function (lang) {
- var ending = ''
- if (!checkBelow(matchInContainer)) {
- ending = '\n\n:::'
+ {
+ // Container strategy
+ containers: supportContainers,
+ match: /(^|\n):::(\s*)(\w*)$/,
+ search: function (term, callback) {
+ const line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[3].trim()
+ const list = []
+ $.map(this.containers, function (container) {
+ if (container.indexOf(term) === 0 && container !== term) {
+ list.push(container)
+ }
+ })
+ callback(list)
+ },
+ replace: function (lang) {
+ let ending = ''
+ if (!checkBelow(matchInContainer)) {
+ ending = '\n\n:::'
+ }
+ if (this.containers.indexOf(lang) !== -1) {
+ return '$1:::$2' + lang + ending
+ }
+ },
+ done: function () {
+ const cursor = editor.getCursor()
+ let text = []
+ text.push(editor.getLine(cursor.line - 1))
+ text.push(editor.getLine(cursor.line))
+ text = text.join('\n')
+ // console.debug(text);
+ if (text === '\n:::') {
+ editor.doc.cm.execCommand('goLineUp')
+ }
+ },
+ context: function (text) {
+ return !isInCode && isInContainer
}
- if (this.containers.indexOf(lang) !== -1) { return '$1:::$2' + lang + ending }
- },
- done: function () {
- var cursor = editor.getCursor()
- var text = []
- text.push(editor.getLine(cursor.line - 1))
- text.push(editor.getLine(cursor.line))
- text = text.join('\n')
- // console.debug(text);
- if (text === '\n:::') { editor.doc.cm.execCommand('goLineUp') }
- },
- context: function (text) {
- return !isInCode && isInContainer
- }
- },
- { // header
- match: /(?:^|\n)(\s{0,3})(#{1,6}\w*)$/,
- search: function (term, callback) {
- callback($.map(supportHeaders, function (header) {
- return header.search.indexOf(term) === 0 ? header.text : null
- }))
- },
- replace: function (value) {
- return '$1' + value
- },
- context: function (text) {
- return !isInCode
- }
- },
- { // extra tags for list
- match: /(^[>\s]*[-+*]\s(?:\[[x ]\]|.*))(\[\])(\w*)$/,
- search: function (term, callback) {
- var list = []
- $.map(supportExtraTags, function (extratag) {
- if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }
- })
- $.map(supportReferrals, function (referral) {
- if (referral.search.indexOf(term) === 0) { list.push(referral.text) }
- })
- callback(list)
},
- replace: function (value) {
- return '$1' + value
+ {
+ // header
+ match: /(?:^|\n)(\s{0,3})(#{1,6}\w*)$/,
+ search: function (term, callback) {
+ callback(
+ $.map(supportHeaders, function (header) {
+ return header.search.indexOf(term) === 0 ? header.text : null
+ })
+ )
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
},
- context: function (text) {
- return !isInCode
- }
- },
- { // extra tags for blockquote
- match: /(?:^|\n|\s)(>.*|\s|)((\^|)\[(\^|)\](\[\]|\(\)|:|)\s*\w*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line)
- var quote = line.match(this.match)[1].trim()
- var list = []
- if (quote.indexOf('>') === 0) {
+ {
+ // extra tags for list
+ match: /(^[>\s]*[-+*]\s(?:\[[x ]\]|.*))(\[\])(\w*)$/,
+ search: function (term, callback) {
+ const list = []
$.map(supportExtraTags, function (extratag) {
- if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }
+ if (extratag.search.indexOf(term) === 0) {
+ list.push(extratag.command())
+ }
})
+ $.map(supportReferrals, function (referral) {
+ if (referral.search.indexOf(term) === 0) {
+ list.push(referral.text)
+ }
+ })
+ callback(list)
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
}
- $.map(supportReferrals, function (referral) {
- if (referral.search.indexOf(term) === 0) { list.push(referral.text) }
- })
- callback(list)
- },
- replace: function (value) {
- return '$1' + value
- },
- context: function (text) {
- return !isInCode
- }
- },
- { // referral
- match: /(^\s*|\n|\s{2})((\[\]|\[\]\[\]|\[\]\(\)|!|!\[\]|!\[\]\[\]|!\[\]\(\))\s*\w*)$/,
- search: function (term, callback) {
- callback($.map(supportReferrals, function (referral) {
- return referral.search.indexOf(term) === 0 ? referral.text : null
- }))
- },
- replace: function (value) {
- return '$1' + value
},
- context: function (text) {
- return !isInCode
- }
- },
- { // externals
- match: /(^|\n|\s)\{\}(\w*)$/,
- search: function (term, callback) {
- callback($.map(supportExternals, function (external) {
- return external.search.indexOf(term) === 0 ? external.text : null
- }))
+ {
+ // extra tags for blockquote
+ match: /(?:^|\n|\s)(>.*|\s|)((\^|)\[(\^|)\](\[\]|\(\)|:|)\s*\w*)$/,
+ search: function (term, callback) {
+ const line = editor.getLine(editor.getCursor().line)
+ const quote = line.match(this.match)[1].trim()
+ const list = []
+ if (quote.indexOf('>') === 0) {
+ $.map(supportExtraTags, function (extratag) {
+ if (extratag.search.indexOf(term) === 0) {
+ list.push(extratag.command())
+ }
+ })
+ }
+ $.map(supportReferrals, function (referral) {
+ if (referral.search.indexOf(term) === 0) {
+ list.push(referral.text)
+ }
+ })
+ callback(list)
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
},
- replace: function (value) {
- return '$1' + value
+ {
+ // referral
+ match: /(^\s*|\n|\s{2})((\[\]|\[\]\[\]|\[\]\(\)|!|!\[\]|!\[\]\[\]|!\[\]\(\))\s*\w*)$/,
+ search: function (term, callback) {
+ callback(
+ $.map(supportReferrals, function (referral) {
+ return referral.search.indexOf(term) === 0 ? referral.text : null
+ })
+ )
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
},
- context: function (text) {
- return !isInCode
+ {
+ // externals
+ match: /(^|\n|\s)\{\}(\w*)$/,
+ search: function (term, callback) {
+ callback(
+ $.map(supportExternals, function (external) {
+ return external.search.indexOf(term) === 0 ? external.text : null
+ })
+ )
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
}
+ ],
+ {
+ appendTo: $('.cursor-menu')
}
- ], {
- appendTo: $('.cursor-menu')
- })
+ )
.on({
'textComplete:beforeSearch': function (e) {
// NA
@@ -3307,22 +3958,22 @@ $(editor.getInputField())
'textComplete:show': function (e) {
$(this).data('autocompleting', true)
editor.setOption('extraKeys', {
- 'Up': function () {
+ Up: function () {
return false
},
- 'Right': function () {
+ Right: function () {
editor.doc.cm.execCommand('goCharRight')
},
- 'Down': function () {
+ Down: function () {
return false
},
- 'Left': function () {
+ Left: function () {
editor.doc.cm.execCommand('goCharLeft')
},
- 'Enter': function () {
+ Enter: function () {
return false
},
- 'Backspace': function () {
+ Backspace: function () {
editor.doc.cm.execCommand('delCharBefore')
}
})
diff --git a/public/js/lib/appState.js b/public/js/lib/appState.js
index 87aaf737..f409908c 100644
--- a/public/js/lib/appState.js
+++ b/public/js/lib/appState.js
@@ -1,6 +1,6 @@
import modeType from './modeType'
-let state = {
+const state = {
syncscroll: true,
currentMode: modeType.view,
nightMode: false
diff --git a/public/js/lib/common/login.js b/public/js/lib/common/login.js
index 3f7a3e4d..88e8f8cf 100644
--- a/public/js/lib/common/login.js
+++ b/public/js/lib/common/login.js
@@ -7,7 +7,7 @@ let checkAuth = false
let profile = null
let lastLoginState = getLoginState()
let lastUserId = getUserId()
-var loginStateChangeEvent = null
+let loginStateChangeEvent = null
export function setloginStateChangeEvent (func) {
loginStateChangeEvent = func
diff --git a/public/js/lib/editor/config.js b/public/js/lib/editor/config.js
index 9508b847..338ef6dc 100644
--- a/public/js/lib/editor/config.js
+++ b/public/js/lib/editor/config.js
@@ -1,4 +1,4 @@
-let config = {
+const config = {
docmaxlength: null
}
diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js
index d86ebf3c..c84a3725 100644
--- a/public/js/lib/editor/index.js
+++ b/public/js/lib/editor/index.js
@@ -35,30 +35,30 @@ export default class Editor {
},
Enter: 'newlineAndIndentContinueMarkdownList',
Tab: function (cm) {
- var tab = '\t'
+ const tab = '\t'
// contruct x length spaces
- var spaces = Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ')
+ const spaces = Array(parseInt(cm.getOption('indentUnit')) + 1).join(' ')
// auto indent whole line when in list or blockquote
- var cursor = cm.getCursor()
- var line = cm.getLine(cursor.line)
+ const cursor = cm.getCursor()
+ const line = cm.getLine(cursor.line)
// this regex match the following patterns
// 1. blockquote starts with "> " or ">>"
// 2. unorder list starts with *+-
// 3. order list starts with "1." or "1)"
- var regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/
+ const regex = /^(\s*)(>[> ]*|[*+-]\s|(\d+)([.)]))/
- var match
- var multiple = cm.getSelection().split('\n').length > 1 ||
+ let match
+ const multiple = cm.getSelection().split('\n').length > 1 ||
cm.getSelections().length > 1
if (multiple) {
cm.execCommand('defaultTab')
} else if ((match = regex.exec(line)) !== null) {
- var ch = match[1].length
- var pos = {
+ const ch = match[1].length
+ const pos = {
line: cursor.line,
ch: ch
}
@@ -77,8 +77,8 @@ export default class Editor {
},
'Cmd-Left': 'goLineLeftSmart',
'Cmd-Right': 'goLineRight',
- 'Home': 'goLineLeftSmart',
- 'End': 'goLineRight',
+ Home: 'goLineLeftSmart',
+ End: 'goLineRight',
'Ctrl-C': function (cm) {
if (!isMac && cm.getOption('keyMap').substr(0, 3) === 'vim') {
document.execCommand('copy')
@@ -140,27 +140,27 @@ export default class Editor {
}
addToolBar () {
- var inlineAttach = inlineAttachment.editors.codemirror4.attach(this.editor)
+ const inlineAttach = inlineAttachment.editors.codemirror4.attach(this.editor)
this.toolBar = $(toolBarTemplate)
this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {
position: 'top'
})
- var makeBold = $('#makeBold')
- var makeItalic = $('#makeItalic')
- var makeStrike = $('#makeStrike')
- var makeHeader = $('#makeHeader')
- var makeCode = $('#makeCode')
- var makeQuote = $('#makeQuote')
- var makeGenericList = $('#makeGenericList')
- var makeOrderedList = $('#makeOrderedList')
- var makeCheckList = $('#makeCheckList')
- var makeLink = $('#makeLink')
- var makeImage = $('#makeImage')
- var makeTable = $('#makeTable')
- var makeLine = $('#makeLine')
- var makeComment = $('#makeComment')
- var uploadImage = $('#uploadImage')
+ const makeBold = $('#makeBold')
+ const makeItalic = $('#makeItalic')
+ const makeStrike = $('#makeStrike')
+ const makeHeader = $('#makeHeader')
+ const makeCode = $('#makeCode')
+ const makeQuote = $('#makeQuote')
+ const makeGenericList = $('#makeGenericList')
+ const makeOrderedList = $('#makeOrderedList')
+ const makeCheckList = $('#makeCheckList')
+ const makeLink = $('#makeLink')
+ const makeImage = $('#makeImage')
+ const makeTable = $('#makeTable')
+ const makeLine = $('#makeLine')
+ const makeComment = $('#makeComment')
+ const uploadImage = $('#uploadImage')
makeBold.click(() => {
utils.wrapTextWith(this.editor, this.editor, '**')
@@ -223,7 +223,7 @@ export default class Editor {
})
uploadImage.bind('change', function (e) {
- var files = e.target.files || e.dataTransfer.files
+ const files = e.target.files || e.dataTransfer.files
e.dataTransfer = {}
e.dataTransfer.files = files
inlineAttach.onDrop(e)
@@ -256,12 +256,12 @@ export default class Editor {
updateStatusBar () {
if (!this.statusBar) return
- var cursor = this.editor.getCursor()
- var cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1)
+ const cursor = this.editor.getCursor()
+ const cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1)
this.statusCursor.text(cursorText)
- var fileText = ' — ' + editor.lineCount() + ' Lines'
+ const fileText = ' — ' + editor.lineCount() + ' Lines'
this.statusFile.text(fileText)
- var docLength = editor.getValue().length
+ const docLength = editor.getValue().length
this.statusLength.text('Length ' + docLength)
if (docLength > (config.docmaxlength * 0.95)) {
this.statusLength.css('color', 'red')
@@ -276,9 +276,9 @@ export default class Editor {
}
setIndent () {
- var cookieIndentType = Cookies.get('indent_type')
- var cookieTabSize = parseInt(Cookies.get('tab_size'))
- var cookieSpaceUnits = parseInt(Cookies.get('space_units'))
+ const cookieIndentType = Cookies.get('indent_type')
+ let cookieTabSize = parseInt(Cookies.get('tab_size'))
+ let cookieSpaceUnits = parseInt(Cookies.get('space_units'))
if (cookieIndentType) {
if (cookieIndentType === 'tab') {
this.editor.setOption('indentWithTabs', true)
@@ -296,9 +296,9 @@ export default class Editor {
this.editor.setOption('tabSize', cookieTabSize)
}
- var type = this.statusIndicators.find('.indent-type')
- var widthLabel = this.statusIndicators.find('.indent-width-label')
- var widthInput = this.statusIndicators.find('.indent-width-input')
+ const type = this.statusIndicators.find('.indent-type')
+ const widthLabel = this.statusIndicators.find('.indent-width-label')
+ const widthInput = this.statusIndicators.find('.indent-width-input')
const setType = () => {
if (this.editor.getOption('indentWithTabs')) {
@@ -318,7 +318,7 @@ export default class Editor {
setType()
const setUnit = () => {
- var unit = this.editor.getOption('indentUnit')
+ const unit = this.editor.getOption('indentUnit')
if (this.editor.getOption('indentWithTabs')) {
Cookies.set('tab_size', unit, {
expires: 365,
@@ -364,7 +364,7 @@ export default class Editor {
}
})
widthInput.on('change', () => {
- var val = parseInt(widthInput.val())
+ let val = parseInt(widthInput.val())
if (!val) val = this.editor.getOption('indentUnit')
if (val < 1) val = 1
else if (val > 10) val = 10
@@ -382,18 +382,18 @@ export default class Editor {
}
setKeymap () {
- var cookieKeymap = Cookies.get('keymap')
+ const cookieKeymap = Cookies.get('keymap')
if (cookieKeymap) {
this.editor.setOption('keyMap', cookieKeymap)
}
- var label = this.statusIndicators.find('.ui-keymap-label')
- var sublime = this.statusIndicators.find('.ui-keymap-sublime')
- var emacs = this.statusIndicators.find('.ui-keymap-emacs')
- var vim = this.statusIndicators.find('.ui-keymap-vim')
+ const label = this.statusIndicators.find('.ui-keymap-label')
+ const sublime = this.statusIndicators.find('.ui-keymap-sublime')
+ const emacs = this.statusIndicators.find('.ui-keymap-emacs')
+ const vim = this.statusIndicators.find('.ui-keymap-vim')
const setKeymapLabel = () => {
- var keymap = this.editor.getOption('keyMap')
+ const keymap = this.editor.getOption('keyMap')
Cookies.set('keymap', keymap, {
expires: 365,
sameSite: window.cookiePolicy
@@ -419,15 +419,15 @@ export default class Editor {
}
setTheme () {
- var cookieTheme = Cookies.get('theme')
+ const cookieTheme = Cookies.get('theme')
if (cookieTheme) {
this.editor.setOption('theme', cookieTheme)
}
- var themeToggle = this.statusTheme.find('.ui-theme-toggle')
+ const themeToggle = this.statusTheme.find('.ui-theme-toggle')
const checkTheme = () => {
- var theme = this.editor.getOption('theme')
+ const theme = this.editor.getOption('theme')
if (theme === 'one-dark') {
themeToggle.removeClass('active')
} else {
@@ -436,7 +436,7 @@ export default class Editor {
}
themeToggle.click(() => {
- var theme = this.editor.getOption('theme')
+ let theme = this.editor.getOption('theme')
if (theme === 'one-dark') {
theme = 'default'
} else {
@@ -455,9 +455,9 @@ export default class Editor {
}
setSpellcheck () {
- var cookieSpellcheck = Cookies.get('spellcheck')
+ const cookieSpellcheck = Cookies.get('spellcheck')
if (cookieSpellcheck) {
- var mode = null
+ let mode = null
if (cookieSpellcheck === 'true' || cookieSpellcheck === true) {
mode = 'spell-checker'
} else {
@@ -468,10 +468,10 @@ export default class Editor {
}
}
- var spellcheckToggle = this.statusSpellcheck.find('.ui-spellcheck-toggle')
+ const spellcheckToggle = this.statusSpellcheck.find('.ui-spellcheck-toggle')
const checkSpellcheck = () => {
- var mode = this.editor.getOption('mode')
+ const mode = this.editor.getOption('mode')
if (mode === defaultEditorMode) {
spellcheckToggle.removeClass('active')
} else {
@@ -480,7 +480,7 @@ export default class Editor {
}
spellcheckToggle.click(() => {
- var mode = this.editor.getOption('mode')
+ let mode = this.editor.getOption('mode')
if (mode === defaultEditorMode) {
mode = 'spell-checker'
} else {
@@ -501,7 +501,7 @@ export default class Editor {
// workaround spellcheck might not activate beacuse the ajax loading
if (window.num_loaded < 2) {
- var spellcheckTimer = setInterval(
+ const spellcheckTimer = setInterval(
() => {
if (window.num_loaded >= 2) {
if (this.editor.getOption('mode') === 'spell-checker') {
@@ -516,7 +516,7 @@ export default class Editor {
}
resetEditorKeymapToBrowserKeymap () {
- var keymap = this.editor.getOption('keyMap')
+ const keymap = this.editor.getOption('keyMap')
if (!this.jumpToAddressBarKeymapValue) {
this.jumpToAddressBarKeymapValue = CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]
delete CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName]
@@ -524,14 +524,15 @@ export default class Editor {
}
restoreOverrideEditorKeymap () {
- var keymap = this.editor.getOption('keyMap')
+ const keymap = this.editor.getOption('keyMap')
if (this.jumpToAddressBarKeymapValue) {
CodeMirror.keyMap[keymap][jumpToAddressBarKeymapName] = this.jumpToAddressBarKeymapValue
this.jumpToAddressBarKeymapValue = null
}
}
+
setOverrideBrowserKeymap () {
- var overrideBrowserKeymap = $(
+ const overrideBrowserKeymap = $(
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
)
if (overrideBrowserKeymap.is(':checked')) {
@@ -547,10 +548,10 @@ export default class Editor {
}
setPreferences () {
- var overrideBrowserKeymap = $(
+ const overrideBrowserKeymap = $(
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
)
- var cookieOverrideBrowserKeymap = Cookies.get(
+ const cookieOverrideBrowserKeymap = Cookies.get(
'preferences-override-browser-keymap'
)
if (cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true') {
diff --git a/public/js/lib/editor/utils.js b/public/js/lib/editor/utils.js
index d87c7e41..70428b28 100644
--- a/public/js/lib/editor/utils.js
+++ b/public/js/lib/editor/utils.js
@@ -3,17 +3,17 @@ export function wrapTextWith (editor, cm, symbol) {
if (!cm.getSelection()) {
return CodeMirror.Pass
} else {
- let ranges = cm.listSelections()
+ const ranges = cm.listSelections()
for (let i = 0; i < ranges.length; i++) {
- let range = ranges[i]
+ const range = ranges[i]
if (!range.empty()) {
const from = range.from()
const to = range.to()
if (symbol !== 'Backspace') {
- let selection = cm.getRange(from, to)
- let anchorIndex = editor.indexFromPos(ranges[i].anchor)
- let headIndex = editor.indexFromPos(ranges[i].head)
+ const selection = cm.getRange(from, to)
+ const anchorIndex = editor.indexFromPos(ranges[i].anchor)
+ const headIndex = editor.indexFromPos(ranges[i].head)
cm.replaceRange(symbol + selection + symbol, from, to, '+input')
if (anchorIndex > headIndex) {
ranges[i].anchor.ch += symbol.length
@@ -24,18 +24,18 @@ export function wrapTextWith (editor, cm, symbol) {
}
cm.setSelections(ranges)
} else {
- let preEndPos = {
+ const preEndPos = {
line: to.line,
ch: to.ch + symbol.length
}
- let preText = cm.getRange(to, preEndPos)
- let preIndex = wrapSymbols.indexOf(preText)
- let postEndPos = {
+ const preText = cm.getRange(to, preEndPos)
+ const preIndex = wrapSymbols.indexOf(preText)
+ const postEndPos = {
line: from.line,
ch: from.ch - symbol.length
}
- let postText = cm.getRange(postEndPos, from)
- let postIndex = wrapSymbols.indexOf(postText)
+ const postText = cm.getRange(postEndPos, from)
+ const postIndex = wrapSymbols.indexOf(postText)
// check if surround symbol are list in array and matched
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
cm.replaceRange('', to, preEndPos, '+delete')
@@ -48,25 +48,25 @@ export function wrapTextWith (editor, cm, symbol) {
}
export function insertText (cm, text, cursorEnd = 0) {
- let cursor = cm.getCursor()
+ const cursor = cm.getCursor()
cm.replaceSelection(text, cursor, cursor)
cm.focus()
cm.setCursor({ line: cursor.line, ch: cursor.ch + cursorEnd })
}
export function insertLink (cm, isImage) {
- let cursor = cm.getCursor()
- let ranges = cm.listSelections()
+ const cursor = cm.getCursor()
+ const ranges = cm.listSelections()
const linkEnd = '](https://)'
const symbol = (isImage) ? '![' : '['
for (let i = 0; i < ranges.length; i++) {
- let range = ranges[i]
+ const range = ranges[i]
if (!range.empty()) {
const from = range.from()
const to = range.to()
- let anchorIndex = editor.indexFromPos(ranges[i].anchor)
- let headIndex = editor.indexFromPos(ranges[i].head)
+ const anchorIndex = editor.indexFromPos(ranges[i].anchor)
+ const headIndex = editor.indexFromPos(ranges[i].head)
let selection = cm.getRange(from, to)
selection = symbol + selection + linkEnd
cm.replaceRange(selection, from, to)
@@ -87,9 +87,9 @@ export function insertLink (cm, isImage) {
}
export function insertHeader (cm) {
- let cursor = cm.getCursor()
- let startOfLine = { line: cursor.line, ch: 0 }
- let startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
+ const cursor = cm.getCursor()
+ const startOfLine = { line: cursor.line, ch: 0 }
+ const startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
// See if it is already a header
if (startOfLineText === '#') {
cm.replaceRange('#', startOfLine, startOfLine)
@@ -100,11 +100,11 @@ export function insertHeader (cm) {
}
export function insertOnStartOfLines (cm, symbol) {
- let cursor = cm.getCursor()
- let ranges = cm.listSelections()
+ const cursor = cm.getCursor()
+ const ranges = cm.listSelections()
for (let i = 0; i < ranges.length; i++) {
- let range = ranges[i]
+ const range = ranges[i]
if (!range.empty()) {
const from = range.from()
const to = range.to()
diff --git a/public/js/lib/syncscroll.js b/public/js/lib/syncscroll.js
index d492fbc9..f033d00d 100644
--- a/public/js/lib/syncscroll.js
+++ b/public/js/lib/syncscroll.js
@@ -155,12 +155,12 @@ const buildMap = _.throttle(buildMapInner, buildMapThrottle)
// Optimizations are required only for big texts.
function buildMapInner (callback) {
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
- _scrollMap = []
- nonEmptyList = []
- _lineHeightMap = []
+ const offset = viewArea.scrollTop() - viewArea.offset().top
+ const _scrollMap = []
+ const nonEmptyList = []
+ const _lineHeightMap = []
viewTop = 0
viewBottom = viewArea[0].scrollHeight - viewArea.height()
@@ -181,7 +181,7 @@ function buildMapInner (callback) {
acc += Math.round(h / lineHeight)
}
_lineHeightMap.push(acc)
- linesCount = acc
+ const linesCount = acc
for (i = 0; i < linesCount; i++) {
_scrollMap.push(-1)
@@ -290,11 +290,12 @@ export function syncScrollToEdit (event, preventAnimate) {
posTo += Math.ceil(posToNextDiff)
}
+ let duration = 0
if (preventAnimate) {
editArea.scrollTop(posTo)
} else {
const posDiff = Math.abs(scrollInfo.top - posTo)
- var duration = posDiff / 50
+ duration = posDiff / 50
duration = duration >= 100 ? duration : 100
editArea.stop(true, true).animate({
scrollTop: posTo
@@ -331,11 +332,11 @@ export function syncScrollToView (event, preventAnimate) {
}
if (viewScrolling) return
- let lineNo, posTo
+ let posTo
let topDiffPercent, posToNextDiff
const scrollInfo = editor.getScrollInfo()
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
const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
@@ -350,11 +351,12 @@ export function syncScrollToView (event, preventAnimate) {
posTo += Math.floor(posToNextDiff)
}
+ let duration = 0
if (preventAnimate) {
viewArea.scrollTop(posTo)
} else {
const posDiff = Math.abs(viewArea.scrollTop() - posTo)
- var duration = posDiff / 50
+ duration = posDiff / 50
duration = duration >= 100 ? duration : 100
viewArea.stop(true, true).animate({
scrollTop: posTo
diff --git a/public/js/render.js b/public/js/render.js
index ebda2984..af6fb3d4 100644
--- a/public/js/render.js
+++ b/public/js/render.js
@@ -1,40 +1,40 @@
/* eslint-env browser, jquery */
// allow some attributes
-var filterXSS = require('xss')
+const filterXSS = require('xss')
-var whiteListAttr = ['id', 'class', 'style']
+const whiteListAttr = ['id', 'class', 'style']
window.whiteListAttr = whiteListAttr
// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://
-var linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
+const linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
// allow data uri, from https://gist.github.com/bgrins/6194623
-var dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
+const dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
// custom white list
-var whiteList = filterXSS.whiteList
+const whiteList = filterXSS.whiteList
// allow ol specify start number
-whiteList['ol'] = ['start']
+whiteList.ol = ['start']
// allow li specify value number
-whiteList['li'] = ['value']
+whiteList.li = ['value']
// allow style tag
-whiteList['style'] = []
+whiteList.style = []
// allow kbd tag
-whiteList['kbd'] = []
+whiteList.kbd = []
// allow ifram tag with some safe attributes
-whiteList['iframe'] = ['allowfullscreen', 'name', 'referrerpolicy', 'src', 'width', 'height']
+whiteList.iframe = ['allowfullscreen', 'name', 'referrerpolicy', 'src', 'width', 'height']
// allow summary tag
-whiteList['summary'] = []
+whiteList.summary = []
// allow ruby tag
-whiteList['ruby'] = []
+whiteList.ruby = []
// allow rp tag for ruby
-whiteList['rp'] = []
+whiteList.rp = []
// allow rt tag for ruby
-whiteList['rt'] = []
+whiteList.rt = []
// allow figure tag
-whiteList['figure'] = []
+whiteList.figure = []
// allow figcaption tag
-whiteList['figcaption'] = []
+whiteList.figcaption = []
-var filterXSSOptions = {
+const filterXSSOptions = {
allowCommentTag: true,
whiteList: whiteList,
escapeHtml: function (html) {
diff --git a/public/js/reveal-markdown.js b/public/js/reveal-markdown.js
index c49bb9a2..89cd0887 100644
--- a/public/js/reveal-markdown.js
+++ b/public/js/reveal-markdown.js
@@ -17,28 +17,28 @@ import { md } from './extra'
root.RevealMarkdown.initialize()
}
}(this, function () {
- var DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$'
- var DEFAULT_NOTES_SEPARATOR = '^note:'
- var DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\.element\\s*?(.+?)$'
- var DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\.slide:\\s*?(\\S.+?)$'
+ const DEFAULT_SLIDE_SEPARATOR = '^\r?\n---\r?\n$'
+ const DEFAULT_NOTES_SEPARATOR = '^note:'
+ const DEFAULT_ELEMENT_ATTRIBUTES_SEPARATOR = '\\.element\\s*?(.+?)$'
+ const DEFAULT_SLIDE_ATTRIBUTES_SEPARATOR = '\\.slide:\\s*?(\\S.+?)$'
- var SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__'
+ const SCRIPT_END_PLACEHOLDER = '__SCRIPT_END__'
/**
* Retrieves the markdown contents of a slide section
* element. Normalizes leading tabs/whitespace.
*/
function getMarkdownFromSlide (section) {
- var template = section.querySelector('script')
+ const template = section.querySelector('script')
// strip leading whitespace so it isn't evaluated as code
- var text = (template || section).textContent
+ let text = (template || section).textContent
// restore script end tags
text = text.replace(new RegExp(SCRIPT_END_PLACEHOLDER, 'g'), '</script>')
- var leadingWs = text.match(/^\n?(\s*)/)[1].length
- var leadingTabs = text.match(/^\n?(\t*)/)[1].length
+ const leadingWs = text.match(/^\n?(\s*)/)[1].length
+ const leadingTabs = text.match(/^\n?(\t*)/)[1].length
if (leadingTabs > 0) {
text = text.replace(new RegExp('\\n?\\t{' + leadingTabs + '}', 'g'), '\n')
@@ -56,12 +56,12 @@ import { md } from './extra'
* to the output markdown slide.
*/
function getForwardedAttributes (section) {
- var attributes = section.attributes
- var result = []
+ const attributes = section.attributes
+ const result = []
- for (var i = 0, len = attributes.length; i < len; i++) {
- var name = attributes[i].name
- var value = attributes[i].value
+ for (let i = 0, len = attributes.length; i < len; i++) {
+ const name = attributes[i].name
+ const value = attributes[i].value
// disregard attributes that are used for markdown loading/parsing
if (/data-(markdown|separator|vertical|notes)/gi.test(name)) continue
@@ -95,7 +95,7 @@ import { md } from './extra'
function createMarkdownSlide (content, options) {
options = getSlidifyOptions(options)
- var notesMatch = content.split(new RegExp(options.notesSeparator, 'mgi'))
+ const notesMatch = content.split(new RegExp(options.notesSeparator, 'mgi'))
if (notesMatch.length === 2) {
content = notesMatch[0] + '<aside class="notes" data-markdown>' + notesMatch[1].trim() + '</aside>'
@@ -115,15 +115,15 @@ import { md } from './extra'
function slidify (markdown, options) {
options = getSlidifyOptions(options)
- var separatorRegex = new RegExp(options.separator + (options.verticalSeparator ? '|' + options.verticalSeparator : ''), 'mg')
- var horizontalSeparatorRegex = new RegExp(options.separator)
+ const separatorRegex = new RegExp(options.separator + (options.verticalSeparator ? '|' + options.verticalSeparator : ''), 'mg')
+ const horizontalSeparatorRegex = new RegExp(options.separator)
- var matches
- var lastIndex = 0
- var isHorizontal
- var wasHorizontal = true
- var content
- var sectionStack = []
+ let matches
+ let lastIndex = 0
+ let isHorizontal
+ let wasHorizontal = true
+ let content
+ const sectionStack = []
// iterate until all blocks between separators are stacked up
while ((matches = separatorRegex.exec(markdown)) !== null) {
@@ -153,10 +153,10 @@ import { md } from './extra'
// add the remaining slide
(wasHorizontal ? sectionStack : sectionStack[sectionStack.length - 1]).push(markdown.substring(lastIndex))
- var markdownSections = ''
+ let markdownSections = ''
// flatten the hierarchical stack, and insert <section data-markdown> tags
- for (var i = 0, len = sectionStack.length; i < len; i++) {
+ for (let i = 0, len = sectionStack.length; i < len; i++) {
// vertical
if (sectionStack[i] instanceof Array) {
markdownSections += '<section ' + options.attributes + '>'
@@ -180,17 +180,17 @@ import { md } from './extra'
* handles loading of external markdown.
*/
function processSlides () {
- var sections = document.querySelectorAll('[data-markdown]')
- var section
+ const sections = document.querySelectorAll('[data-markdown]')
+ let section
- for (var i = 0, len = sections.length; i < len; i++) {
+ for (let i = 0, len = sections.length; i < len; i++) {
section = sections[i]
if (section.getAttribute('data-markdown').length) {
- var xhr = new XMLHttpRequest()
- var url = section.getAttribute('data-markdown')
+ const xhr = new XMLHttpRequest()
+ const url = section.getAttribute('data-markdown')
- var datacharset = section.getAttribute('data-charset')
+ const datacharset = section.getAttribute('data-charset')
// see https://developer.mozilla.org/en-US/docs/Web/API/element.getAttribute#Notes
if (datacharset !== null && datacharset !== '') {
@@ -247,18 +247,18 @@ import { md } from './extra'
* http://stackoverflow.com/questions/5690269/disabling-chrome-cache-for-website-development/7000899#answer-11786277
*/
function addAttributeInElement (node, elementTarget, separator) {
- var mardownClassesInElementsRegex = new RegExp(separator, 'mg')
- var mardownClassRegex = new RegExp('([^"= ]+?)="([^"=]+?)"', 'mg')
- var nodeValue = node.nodeValue
- var matches
- var matchesClass
+ const mardownClassesInElementsRegex = new RegExp(separator, 'mg')
+ const mardownClassRegex = /([^"= ]+?)="([^"=]+?)"/mg
+ let nodeValue = node.nodeValue
+ let matches
+ let matchesClass
if ((matches = mardownClassesInElementsRegex.exec(nodeValue))) {
- var classes = matches[1]
+ const classes = matches[1]
nodeValue = nodeValue.substring(0, matches.index) + nodeValue.substring(mardownClassesInElementsRegex.lastIndex)
node.nodeValue = nodeValue
while ((matchesClass = mardownClassRegex.exec(classes))) {
- var name = matchesClass[1]
- var value = matchesClass[2]
+ const name = matchesClass[1]
+ const value = matchesClass[2]
if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) { elementTarget.setAttribute(name, escapeAttrValue(value)) }
}
return true
@@ -272,13 +272,13 @@ import { md } from './extra'
*/
function addAttributes (section, element, previousElement, separatorElementAttributes, separatorSectionAttributes) {
if (element != null && element.childNodes !== undefined && element.childNodes.length > 0) {
- var previousParentElement = element
- for (var i = 0; i < element.childNodes.length; i++) {
- var childElement = element.childNodes[i]
+ let previousParentElement = element
+ for (let i = 0; i < element.childNodes.length; i++) {
+ const childElement = element.childNodes[i]
if (i > 0) {
let j = i - 1
while (j >= 0) {
- var aPreviousChildElement = element.childNodes[j]
+ const aPreviousChildElement = element.childNodes[j]
if (typeof aPreviousChildElement.setAttribute === 'function' && aPreviousChildElement.tagName !== 'BR') {
previousParentElement = aPreviousChildElement
break
@@ -286,7 +286,7 @@ import { md } from './extra'
j = j - 1
}
}
- var parentSection = section
+ let parentSection = section
if (childElement.nodeName === 'section') {
parentSection = childElement
previousParentElement = childElement
@@ -309,21 +309,21 @@ import { md } from './extra'
* DOM to HTML.
*/
function convertSlides () {
- var sections = document.querySelectorAll('[data-markdown]')
+ const sections = document.querySelectorAll('[data-markdown]')
- for (var i = 0, len = sections.length; i < len; i++) {
- var section = sections[i]
+ for (let i = 0, len = sections.length; i < len; i++) {
+ const section = sections[i]
// Only parse the same slide once
if (!section.getAttribute('data-markdown-parsed')) {
section.setAttribute('data-markdown-parsed', true)
- var notes = section.querySelector('aside.notes')
- var markdown = getMarkdownFromSlide(section)
+ const notes = section.querySelector('aside.notes')
+ let markdown = getMarkdownFromSlide(section)
markdown = markdown.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
- var rendered = md.render(markdown)
+ let rendered = md.render(markdown)
rendered = preventXSS(rendered)
- var result = window.postProcess(rendered)
+ const result = window.postProcess(rendered)
section.innerHTML = result[0].outerHTML
addAttributes(section, section, null, section.getAttribute('data-element-attributes') ||
section.parentNode.getAttribute('data-element-attributes') ||
diff --git a/public/js/slide.js b/public/js/slide.js
index b8374cbb..5a28993f 100644
--- a/public/js/slide.js
+++ b/public/js/slide.js
@@ -26,7 +26,7 @@ function extend () {
for (const source of arguments) {
for (const key in source) {
- if (source.hasOwnProperty(key)) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key]
}
}
@@ -36,18 +36,21 @@ function extend () {
}
// Optional libraries used to extend on reveal.js
-const deps = [{
- src: `${serverurl}/build/reveal.js/lib/js/classList.js`,
- condition () {
- return !document.body.classList
- }
-}, {
- src: `${serverurl}/build/reveal.js/plugin/notes/notes.js`,
- async: true,
- condition () {
- return !!document.body.classList
+const deps = [
+ {
+ src: `${serverurl}/build/reveal.js/lib/js/classList.js`,
+ condition () {
+ return !document.body.classList
+ }
+ },
+ {
+ src: `${serverurl}/build/reveal.js/plugin/notes/notes.js`,
+ async: true,
+ condition () {
+ return !!document.body.classList
+ }
}
-}]
+]
const slideOptions = {
separator: '^(\r\n?|\n)---(\r\n?|\n)$',
@@ -73,60 +76,64 @@ const defaultOptions = {
// options from yaml meta
const meta = JSON.parse($('#meta').text())
const metaSlideOptions = !!meta && !!meta.slideOptions ? meta.slideOptions : {}
-var options = {
- autoPlayMedia: metaSlideOptions.autoPlayMedia,
- autoSlide: metaSlideOptions.autoSlide,
- autoSlideStoppable: metaSlideOptions.autoSlideStoppable,
- backgroundTransition: metaSlideOptions.backgroundTransition,
- center: metaSlideOptions.center,
- controls: metaSlideOptions.controls,
- controlsBackArrows: metaSlideOptions.controlsBackArrows,
- controlsLayout: metaSlideOptions.controlsLayout,
- controlsTutorial: metaSlideOptions.controlsTutorial,
- defaultTiming: metaSlideOptions.defaultTiming,
- display: metaSlideOptions.display,
- embedded: metaSlideOptions.embedded,
- fragmentInURL: metaSlideOptions.fragmentInURL,
- fragments: metaSlideOptions.fragments,
- hash: metaSlideOptions.hash,
- height: metaSlideOptions.height,
- help: metaSlideOptions.help,
- hideAddressBar: metaSlideOptions.hideAddressBar,
- hideCursorTime: metaSlideOptions.hideCursorTime,
- hideInactiveCursor: metaSlideOptions.hideInactiveCursor,
- history: metaSlideOptions.history,
- keyboard: metaSlideOptions.keyboard,
- loop: metaSlideOptions.loop,
- margin: metaSlideOptions.margin,
- maxScale: metaSlideOptions.maxScale,
- minScale: metaSlideOptions.minScale,
- minimumTimePerSlide: metaSlideOptions.minimumTimePerSlide,
- mobileViewDistance: metaSlideOptions.mobileViewDistance,
- mouseWheel: metaSlideOptions.mouseWheel,
- navigationMode: metaSlideOptions.navigationMode,
- overview: metaSlideOptions.overview,
- parallaxBackgroundHorizontal: metaSlideOptions.parallaxBackgroundHorizontal,
- parallaxBackgroundImage: metaSlideOptions.parallaxBackgroundImage,
- parallaxBackgroundSize: metaSlideOptions.parallaxBackgroundSize,
- parallaxBackgroundVertical: metaSlideOptions.parallaxBackgroundVertical,
- preloadIframes: metaSlideOptions.preloadIframes,
- previewLinks: metaSlideOptions.previewLinks,
- progress: metaSlideOptions.progress,
- rtl: metaSlideOptions.rtl,
- showNotes: metaSlideOptions.showNotes,
- shuffle: metaSlideOptions.shuffle,
- slideNumber: metaSlideOptions.slideNumber,
- theme: metaSlideOptions.theme,
- totalTime: metaSlideOptions.totalTime,
- touch: metaSlideOptions.touch,
- transition: metaSlideOptions.transition,
- transitionSpeed: metaSlideOptions.transitionSpeed,
- viewDistance: metaSlideOptions.viewDistance,
- width: metaSlideOptions.width
-} || {}
+let options =
+ {
+ autoPlayMedia: metaSlideOptions.autoPlayMedia,
+ autoSlide: metaSlideOptions.autoSlide,
+ autoSlideStoppable: metaSlideOptions.autoSlideStoppable,
+ backgroundTransition: metaSlideOptions.backgroundTransition,
+ center: metaSlideOptions.center,
+ controls: metaSlideOptions.controls,
+ controlsBackArrows: metaSlideOptions.controlsBackArrows,
+ controlsLayout: metaSlideOptions.controlsLayout,
+ controlsTutorial: metaSlideOptions.controlsTutorial,
+ defaultTiming: metaSlideOptions.defaultTiming,
+ display: metaSlideOptions.display,
+ embedded: metaSlideOptions.embedded,
+ fragmentInURL: metaSlideOptions.fragmentInURL,
+ fragments: metaSlideOptions.fragments,
+ hash: metaSlideOptions.hash,
+ height: metaSlideOptions.height,
+ help: metaSlideOptions.help,
+ hideAddressBar: metaSlideOptions.hideAddressBar,
+ hideCursorTime: metaSlideOptions.hideCursorTime,
+ hideInactiveCursor: metaSlideOptions.hideInactiveCursor,
+ history: metaSlideOptions.history,
+ keyboard: metaSlideOptions.keyboard,
+ loop: metaSlideOptions.loop,
+ margin: metaSlideOptions.margin,
+ maxScale: metaSlideOptions.maxScale,
+ minScale: metaSlideOptions.minScale,
+ minimumTimePerSlide: metaSlideOptions.minimumTimePerSlide,
+ mobileViewDistance: metaSlideOptions.mobileViewDistance,
+ mouseWheel: metaSlideOptions.mouseWheel,
+ navigationMode: metaSlideOptions.navigationMode,
+ overview: metaSlideOptions.overview,
+ parallaxBackgroundHorizontal: metaSlideOptions.parallaxBackgroundHorizontal,
+ parallaxBackgroundImage: metaSlideOptions.parallaxBackgroundImage,
+ parallaxBackgroundSize: metaSlideOptions.parallaxBackgroundSize,
+ parallaxBackgroundVertical: metaSlideOptions.parallaxBackgroundVertical,
+ preloadIframes: metaSlideOptions.preloadIframes,
+ previewLinks: metaSlideOptions.previewLinks,
+ progress: metaSlideOptions.progress,
+ rtl: metaSlideOptions.rtl,
+ showNotes: metaSlideOptions.showNotes,
+ shuffle: metaSlideOptions.shuffle,
+ slideNumber: metaSlideOptions.slideNumber,
+ theme: metaSlideOptions.theme,
+ totalTime: metaSlideOptions.totalTime,
+ touch: metaSlideOptions.touch,
+ transition: metaSlideOptions.transition,
+ transitionSpeed: metaSlideOptions.transitionSpeed,
+ viewDistance: metaSlideOptions.viewDistance,
+ width: metaSlideOptions.width
+ } || {}
for (const key in options) {
- if (options.hasOwnProperty(key) && options[key] === undefined) {
+ if (
+ Object.prototype.hasOwnProperty.call(options, key) &&
+ options[key] === undefined
+ ) {
delete options[key]
}
}
@@ -165,14 +172,14 @@ window.viewAjaxCallback = () => {
function renderSlide (event) {
if (window.location.search.match(/print-pdf/gi)) {
const slides = $('.slides')
- let title = document.title
+ const title = document.title
finishView(slides)
document.title = title
Reveal.layout()
} else {
const markdown = $(event.currentSlide)
if (!markdown.attr('data-rendered')) {
- let title = document.title
+ const title = document.title
finishView(markdown)
markdown.attr('data-rendered', 'true')
document.title = title
@@ -181,7 +188,7 @@ function renderSlide (event) {
}
}
-Reveal.addEventListener('ready', event => {
+Reveal.addEventListener('ready', (event) => {
renderSlide(event)
const markdown = $(event.currentSlide)
// force browser redraw
diff --git a/public/js/utils.js b/public/js/utils.js
index 91e7f133..d42a18e7 100644
--- a/public/js/utils.js
+++ b/public/js/utils.js
@@ -1,9 +1,9 @@
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) {
- let result = id.match(uuidRegex)
+ const result = id.match(uuidRegex)
if (result && result.length === 1) {
return true
} else {
@@ -13,16 +13,16 @@ export function checkNoteIdValid (id) {
export function encodeNoteId (id) {
// remove dashes in UUID and encode in url-safe base64
- let str = id.replace(/-/g, '')
- let hexStr = Buffer.from(str, 'hex')
+ const str = id.replace(/-/g, '')
+ const hexStr = Buffer.from(str, 'hex')
return base64url.encode(hexStr)
}
export function decodeNoteId (encodedId) {
// 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
- let idParts = []
+ const idParts = []
idParts.push(id.substr(0, 8))
idParts.push(id.substr(8, 4))
idParts.push(id.substr(12, 4))
diff --git a/test/csp.js b/test/csp.js
index d081cef0..70598156 100644
--- a/test/csp.js
+++ b/test/csp.js
@@ -46,7 +46,7 @@ describe('Content security policies', function () {
// beginnging Tests
it('Disable CDN', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
testconfig.useCDN = false
mock('../lib/config', testconfig)
csp = mock.reRequire('../lib/csp')
@@ -60,7 +60,7 @@ describe('Content security policies', function () {
})
it('Disable Google Analytics', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
testconfig.csp.addGoogleAnalytics = false
mock('../lib/config', testconfig)
csp = mock.reRequire('../lib/csp')
@@ -69,7 +69,7 @@ describe('Content security policies', function () {
})
it('Disable Disqus', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
testconfig.csp.addDisqus = false
mock('../lib/config', testconfig)
csp = mock.reRequire('../lib/csp')
@@ -82,7 +82,7 @@ describe('Content security policies', function () {
})
it('Include dropbox if configured', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
testconfig.dropbox.appKey = 'hedgedoc'
mock('../lib/config', testconfig)
csp = mock.reRequire('../lib/csp')
@@ -92,7 +92,7 @@ describe('Content security policies', function () {
})
it('Set ReportURI', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
testconfig.csp.reportURI = 'https://example.com/reportURI'
mock('../lib/config', testconfig)
csp = mock.reRequire('../lib/csp')
@@ -101,7 +101,7 @@ describe('Content security policies', function () {
})
it('Set own directives', function () {
- let testconfig = defaultConfig
+ const testconfig = defaultConfig
mock('../lib/config', defaultConfig)
csp = mock.reRequire('../lib/csp')
const unextendedCSP = csp.computeDirectives()
diff --git a/test/letter-avatars.js b/test/letter-avatars.js
index 8cc32d8b..0645ef87 100644
--- a/test/letter-avatars.js
+++ b/test/letter-avatars.js
@@ -9,7 +9,7 @@ describe('generateAvatarURL() gravatar enabled', function () {
let avatars
beforeEach(function () {
// Reset config to make sure we don't influence other tests
- let testconfig = {
+ const testconfig = {
allowGravatar: true,
serverURL: 'http://localhost:3000',
port: 3000
@@ -32,7 +32,7 @@ describe('generateAvatarURL() gravatar disabled', function () {
let avatars
beforeEach(function () {
// Reset config to make sure we don't influence other tests
- let testconfig = {
+ const testconfig = {
allowGravatar: false,
serverURL: 'http://localhost:3000',
port: 3000