Fix eslint warnings

Since we are about to release it's time to finally fix our linting. This
patch basically runs eslint --fix and does some further manual fixes.
Also it sets up eslint to fail on every warning on order to make
warnings visable in the CI process.

There should no functional change be introduced.

Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
This commit is contained in:
Sheogorath 2019-05-31 00:27:56 +02:00
parent 3eca0a74ae
commit 4da68597f7
No known key found for this signature in database
GPG Key ID: 1F05CC3635CDDFFD
50 changed files with 1055 additions and 1042 deletions

View File

@ -1,6 +1,6 @@
'use strict' 'use strict'
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils') const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
module.exports = { module.exports = {
sourceURL: process.env.CMD_SOURCE_URL, sourceURL: process.env.CMD_SOURCE_URL,

View File

@ -1,6 +1,6 @@
'use strict' 'use strict'
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils') const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
module.exports = { module.exports = {
domain: process.env.HMD_DOMAIN, domain: process.env.HMD_DOMAIN,

View File

@ -4,11 +4,11 @@
const crypto = require('crypto') const crypto = require('crypto')
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const {merge} = require('lodash') const { merge } = require('lodash')
const deepFreeze = require('deep-freeze') const deepFreeze = require('deep-freeze')
const {Environment, Permission} = require('./enum') const { Environment, Permission } = require('./enum')
const logger = require('../logger') const logger = require('../logger')
const {getGitCommit, getGitHubURL} = require('./utils') const { getGitCommit, getGitHubURL } = require('./utils')
const appRootPath = path.resolve(__dirname, '../../') const appRootPath = path.resolve(__dirname, '../../')
const env = process.env.NODE_ENV || Environment.development const env = process.env.NODE_ENV || Environment.development
@ -17,7 +17,7 @@ const debugConfig = {
} }
// Get version string from package.json // Get version string from package.json
const {version, repository} = require(path.join(appRootPath, 'package.json')) const { version, repository } = require(path.join(appRootPath, 'package.json'))
const commitID = getGitCommit(appRootPath) const commitID = getGitCommit(appRootPath)
const sourceURL = getGitHubURL(repository.url, commitID || version) const sourceURL = getGitHubURL(repository.url, commitID || version)
@ -159,8 +159,8 @@ if (Object.keys(process.env).toString().indexOf('HMD_') !== -1) {
if (config.sessionSecret === 'secret') { if (config.sessionSecret === 'secret') {
logger.warn('Session secret not set. Using random generated one. Please set `sessionSecret` in your config.js file. All users will be logged out.') logger.warn('Session secret not set. Using random generated one. Please set `sessionSecret` in your config.js file. All users will be logged out.')
config.sessionSecret = crypto.randomBytes(Math.ceil(config.sessionSecretLen / 2)) // generate crypto graphic random number config.sessionSecret = crypto.randomBytes(Math.ceil(config.sessionSecretLen / 2)) // generate crypto graphic random number
.toString('hex') // convert to hexadecimal format .toString('hex') // convert to hexadecimal format
.slice(0, config.sessionSecretLen) // return required number of characters .slice(0, config.sessionSecretLen) // return required number of characters
} }
// Validate upload upload providers // Validate upload upload providers

View File

@ -1,6 +1,6 @@
'use strict' 'use strict'
const {toBooleanConfig} = require('./utils') const { toBooleanConfig } = require('./utils')
module.exports = { module.exports = {
debug: toBooleanConfig(process.env.DEBUG), debug: toBooleanConfig(process.env.DEBUG),

View File

@ -30,14 +30,14 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
if (typeof email !== 'string') { if (typeof email !== 'string') {
email = '' + name + '@example.com' email = '' + name + '@example.com'
} }
name=encodeURIComponent(name) name = encodeURIComponent(name)
let hash = crypto.createHash('md5') let hash = crypto.createHash('md5')
hash.update(email.toLowerCase()) hash.update(email.toLowerCase())
let hexDigest = hash.digest('hex') let hexDigest = hash.digest('hex')
if (email !== '' && config.allowGravatar) { if (email !== '' && config.allowGravatar) {
photo = 'https://cdn.libravatar.org/avatar/' + hexDigest; photo = 'https://cdn.libravatar.org/avatar/' + hexDigest
if (big) { if (big) {
photo += '?s=400' photo += '?s=400'
} else { } else {

View File

@ -1,5 +1,5 @@
'use strict' 'use strict'
const {createLogger, format, transports} = require('winston') const { createLogger, format, transports } = require('winston')
const logger = createLogger({ const logger = createLogger({
level: 'debug', level: 'debug',

View File

@ -22,6 +22,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: shortid' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'shortid'" || error.message === 'column "shortid" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: shortid' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'shortid'" || error.message === 'column "shortid" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -9,6 +9,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: lastchangeuserId' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'" || error.message === 'column "lastchangeuserId" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: lastchangeuserId' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'" || error.message === 'column "lastchangeuserId" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error
@ -18,8 +19,8 @@ module.exports = {
down: function (queryInterface, Sequelize) { down: function (queryInterface, Sequelize) {
return queryInterface.removeColumn('Notes', 'lastchangeAt') return queryInterface.removeColumn('Notes', 'lastchangeAt')
.then(function () { .then(function () {
return queryInterface.removeColumn('Notes', 'lastchangeuserId') return queryInterface.removeColumn('Notes', 'lastchangeuserId')
}) })
} }
} }

View File

@ -9,6 +9,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: alias' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'alias'" || error.message === 'column "alias" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: alias' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'alias'" || error.message === 'column "alias" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -5,6 +5,7 @@ module.exports = {
return queryInterface.addColumn('Users', 'refreshToken', Sequelize.STRING) return queryInterface.addColumn('Users', 'refreshToken', Sequelize.STRING)
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: accessToken' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'accessToken'" || error.message === 'column "accessToken" of relation "Users" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: accessToken' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'accessToken'" || error.message === 'column "accessToken" of relation "Users" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -17,6 +17,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: savedAt' | error.message === "ER_DUP_FIELDNAME: Duplicate column name 'savedAt'" || error.message === 'column "savedAt" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: savedAt' | error.message === "ER_DUP_FIELDNAME: Duplicate column name 'savedAt'" || error.message === 'column "savedAt" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -18,6 +18,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: authorship' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'authorship'" || error.message === 'column "authorship" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: authorship' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'authorship'" || error.message === 'column "authorship" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -3,6 +3,7 @@ module.exports = {
up: function (queryInterface, Sequelize) { up: function (queryInterface, Sequelize) {
return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE).catch(function (error) { return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: deletedAt' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'" || error.message === 'column "deletedAt" of relation "Notes" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: deletedAt' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'" || error.message === 'column "deletedAt" of relation "Notes" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -4,6 +4,7 @@ module.exports = {
return queryInterface.addColumn('Users', 'email', Sequelize.TEXT).then(function () { return queryInterface.addColumn('Users', 'email', Sequelize.TEXT).then(function () {
return queryInterface.addColumn('Users', 'password', Sequelize.TEXT).catch(function (error) { return queryInterface.addColumn('Users', 'password', Sequelize.TEXT).catch(function (error) {
if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'password'" || error.message === 'column "password" of relation "Users" already exists') { if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'password'" || error.message === 'column "password" of relation "Users" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error
@ -11,6 +12,7 @@ module.exports = {
}) })
}).catch(function (error) { }).catch(function (error) {
if (error.message === 'SQLITE_ERROR: duplicate column name: email' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'email'" || error.message === 'column "email" of relation "Users" already exists') { if (error.message === 'SQLITE_ERROR: duplicate column name: email' || error.message === "ER_DUP_FIELDNAME: Duplicate column name 'email'" || error.message === 'column "email" of relation "Users" already exists') {
// eslint-disable-next-line no-console
console.log('Migration has already run… ignoring.') console.log('Migration has already run… ignoring.')
} else { } else {
throw error throw error

View File

@ -1,16 +1,16 @@
'use strict' 'use strict'
module.exports = { module.exports = {
up: function (queryInterface, Sequelize) { up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT('long') })
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT('long') })
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT('long') })
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT('long') })
}, },
down: function (queryInterface, Sequelize) { down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT}) queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT })
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT}) queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT })
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT}) queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT })
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT}) queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT })
} }
} }

View File

@ -2,12 +2,12 @@
module.exports = { module.exports = {
up: function (queryInterface, Sequelize) { up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT('long') })
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT('long')}) queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT('long') })
}, },
down: function (queryInterface, Sequelize) { down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT}) queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT })
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT}) queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT })
} }
} }

View File

@ -2,10 +2,10 @@
module.exports = { module.exports = {
up: function (queryInterface, Sequelize) { up: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'permission', {type: Sequelize.ENUM('freely', 'editable', 'limited', 'locked', 'protected', 'private')}) queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'limited', 'locked', 'protected', 'private') })
}, },
down: function (queryInterface, Sequelize) { down: function (queryInterface, Sequelize) {
queryInterface.changeColumn('Notes', 'permission', {type: Sequelize.ENUM('freely', 'editable', 'locked', 'private')}) queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'locked', 'private') })
} }
} }

View File

@ -3,7 +3,7 @@
var fs = require('fs') var fs = require('fs')
var path = require('path') var path = require('path')
var Sequelize = require('sequelize') var Sequelize = require('sequelize')
const {cloneDeep} = require('lodash') const { cloneDeep } = require('lodash')
// core // core
var config = require('../config') var config = require('../config')
@ -39,13 +39,13 @@ sequelize.processData = processData
var db = {} var db = {}
fs.readdirSync(__dirname) fs.readdirSync(__dirname)
.filter(function (file) { .filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js') return (file.indexOf('.') !== 0) && (file !== 'index.js')
}) })
.forEach(function (file) { .forEach(function (file) {
var model = sequelize.import(path.join(__dirname, file)) var model = sequelize.import(path.join(__dirname, file))
db[model.name] = model db[model.name] = model
}) })
Object.keys(db).forEach(function (modelName) { Object.keys(db).forEach(function (modelName) {
if ('associate' in db[modelName]) { if ('associate' in db[modelName]) {

View File

@ -18,7 +18,7 @@ var utils = require('./utils')
// public // public
var response = { var response = {
errorForbidden: function (res) { errorForbidden: function (res) {
const {req} = res const { req } = res
if (req.user) { if (req.user) {
responseError(res, '403', 'Forbidden', 'oh no.') responseError(res, '403', 'Forbidden', 'oh no.')
} else { } else {
@ -549,16 +549,16 @@ function gitlabActionProjects (req, res, note) {
ret.accesstoken = user.accessToken ret.accesstoken = user.accessToken
ret.profileid = user.profileid ret.profileid = user.profileid
request( request(
config.gitlab.baseURL + '/api/' + config.gitlab.version + '/projects?membership=yes&per_page=100&access_token=' + user.accessToken, config.gitlab.baseURL + '/api/' + config.gitlab.version + '/projects?membership=yes&per_page=100&access_token=' + user.accessToken,
function (error, httpResponse, body) { function (error, httpResponse, body) {
if (!error && httpResponse.statusCode === 200) { if (!error && httpResponse.statusCode === 200) {
ret.projects = JSON.parse(body) ret.projects = JSON.parse(body)
return res.send(ret) return res.send(ret)
} else { } else {
return res.send(ret) return res.send(ret)
} }
} }
) )
}).catch(function (err) { }).catch(function (err) {
logger.error('gitlab action projects failed: ' + err) logger.error('gitlab action projects failed: ' + err)
return response.errorInternalError(res) return response.errorInternalError(res)

View File

@ -4,7 +4,7 @@ const Router = require('express').Router
const passport = require('passport') const passport = require('passport')
const DropboxStrategy = require('passport-dropbox-oauth2').Strategy const DropboxStrategy = require('passport-dropbox-oauth2').Strategy
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let dropboxAuth = module.exports = Router() let dropboxAuth = module.exports = Router()

View File

@ -7,8 +7,8 @@ const LocalStrategy = require('passport-local').Strategy
const config = require('../../../config') const config = require('../../../config')
const models = require('../../../models') const models = require('../../../models')
const logger = require('../../../logger') const logger = require('../../../logger')
const {setReturnToFromReferer} = require('../utils') const { setReturnToFromReferer } = require('../utils')
const {urlencodedParser} = require('../../utils') const { urlencodedParser } = require('../../utils')
const response = require('../../../response') const response = require('../../../response')
let emailAuth = module.exports = Router() let emailAuth = module.exports = Router()

View File

@ -5,7 +5,7 @@ const passport = require('passport')
const FacebookStrategy = require('passport-facebook').Strategy const FacebookStrategy = require('passport-facebook').Strategy
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let facebookAuth = module.exports = Router() let facebookAuth = module.exports = Router()

View File

@ -5,7 +5,7 @@ const passport = require('passport')
const GithubStrategy = require('passport-github').Strategy const GithubStrategy = require('passport-github').Strategy
const config = require('../../../config') const config = require('../../../config')
const response = require('../../../response') const response = require('../../../response')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let githubAuth = module.exports = Router() let githubAuth = module.exports = Router()

View File

@ -5,7 +5,7 @@ const passport = require('passport')
const GitlabStrategy = require('passport-gitlab2').Strategy const GitlabStrategy = require('passport-gitlab2').Strategy
const config = require('../../../config') const config = require('../../../config')
const response = require('../../../response') const response = require('../../../response')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let gitlabAuth = module.exports = Router() let gitlabAuth = module.exports = Router()

View File

@ -4,7 +4,7 @@ const Router = require('express').Router
const passport = require('passport') const passport = require('passport')
var GoogleStrategy = require('passport-google-oauth20').Strategy var GoogleStrategy = require('passport-google-oauth20').Strategy
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let googleAuth = module.exports = Router() let googleAuth = module.exports = Router()
@ -12,14 +12,14 @@ passport.use(new GoogleStrategy({
clientID: config.google.clientID, clientID: config.google.clientID,
clientSecret: config.google.clientSecret, clientSecret: config.google.clientSecret,
callbackURL: config.serverURL + '/auth/google/callback', callbackURL: config.serverURL + '/auth/google/callback',
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo" userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo'
}, passportGeneralCallback)) }, passportGeneralCallback))
googleAuth.get('/auth/google', function (req, res, next) { googleAuth.get('/auth/google', function (req, res, next) {
setReturnToFromReferer(req) setReturnToFromReferer(req)
passport.authenticate('google', { scope: ['profile'] })(req, res, next) passport.authenticate('google', { scope: ['profile'] })(req, res, next)
}) })
// google auth callback // google auth callback
googleAuth.get('/auth/google/callback', googleAuth.get('/auth/google/callback',
passport.authenticate('google', { passport.authenticate('google', {
successReturnToOrRedirect: config.serverURL + '/', successReturnToOrRedirect: config.serverURL + '/',

View File

@ -6,8 +6,8 @@ const LDAPStrategy = require('passport-ldapauth')
const config = require('../../../config') const config = require('../../../config')
const models = require('../../../models') const models = require('../../../models')
const logger = require('../../../logger') const logger = require('../../../logger')
const {setReturnToFromReferer} = require('../utils') const { setReturnToFromReferer } = require('../utils')
const {urlencodedParser} = require('../../utils') const { urlencodedParser } = require('../../utils')
const response = require('../../../response') const response = require('../../../response')
let ldapAuth = module.exports = Router() let ldapAuth = module.exports = Router()

View File

@ -5,7 +5,7 @@ const passport = require('passport')
const Mattermost = require('mattermost') const Mattermost = require('mattermost')
const OAuthStrategy = require('passport-oauth2').Strategy const OAuthStrategy = require('passport-oauth2').Strategy
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
const mattermost = new Mattermost.Client() const mattermost = new Mattermost.Client()
@ -24,12 +24,12 @@ mattermostStrategy.userProfile = (accessToken, done) => {
mattermost.token = accessToken mattermost.token = accessToken
mattermost.useHeaderToken() mattermost.useHeaderToken()
mattermost.getMe( mattermost.getMe(
(data) => { (data) => {
done(null, data) done(null, data)
}, },
(err) => { (err) => {
done(err) done(err)
} }
) )
} }

View File

@ -4,7 +4,7 @@ const Router = require('express').Router
const passport = require('passport') const passport = require('passport')
const { Strategy, InternalOAuthError } = require('passport-oauth2') const { Strategy, InternalOAuthError } = require('passport-oauth2')
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let oauth2Auth = module.exports = Router() let oauth2Auth = module.exports = Router()

View File

@ -6,8 +6,8 @@ const OpenIDStrategy = require('@passport-next/passport-openid').Strategy
const config = require('../../../config') const config = require('../../../config')
const models = require('../../../models') const models = require('../../../models')
const logger = require('../../../logger') const logger = require('../../../logger')
const {urlencodedParser} = require('../../utils') const { urlencodedParser } = require('../../utils')
const {setReturnToFromReferer} = require('../utils') const { setReturnToFromReferer } = require('../utils')
let openIDAuth = module.exports = Router() let openIDAuth = module.exports = Router()

View File

@ -6,7 +6,7 @@ const SamlStrategy = require('passport-saml').Strategy
const config = require('../../../config') const config = require('../../../config')
const models = require('../../../models') const models = require('../../../models')
const logger = require('../../../logger') const logger = require('../../../logger')
const {urlencodedParser} = require('../../utils') const { urlencodedParser } = require('../../utils')
const fs = require('fs') const fs = require('fs')
const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) } const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) }

View File

@ -5,7 +5,7 @@ const passport = require('passport')
const TwitterStrategy = require('passport-twitter').Strategy const TwitterStrategy = require('passport-twitter').Strategy
const config = require('../../../config') const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils') const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
let twitterAuth = module.exports = Router() let twitterAuth = module.exports = Router()

View File

@ -2,7 +2,7 @@
const Router = require('express').Router const Router = require('express').Router
const {urlencodedParser} = require('./utils') const { urlencodedParser } = require('./utils')
const history = require('../history') const history = require('../history')
const historyRouter = module.exports = Router() const historyRouter = module.exports = Router()

View File

@ -17,12 +17,12 @@ exports.uploadImage = function (imagePath, callback) {
imgur.setClientId(config.imgur.clientID) imgur.setClientId(config.imgur.clientID)
imgur.uploadFile(imagePath) imgur.uploadFile(imagePath)
.then(function (json) { .then(function (json) {
if (config.debug) { if (config.debug) {
logger.info('SERVER uploadimage success: ' + JSON.stringify(json)) logger.info('SERVER uploadimage success: ' + JSON.stringify(json))
} }
callback(null, json.data.link.replace(/^http:\/\//i, 'https://')) callback(null, json.data.link.replace(/^http:\/\//i, 'https://'))
}).catch(function (err) { }).catch(function (err) {
callback(new Error(err), null) callback(new Error(err), null)
}) })
} }

View File

@ -3,7 +3,7 @@ const fs = require('fs')
const path = require('path') const path = require('path')
const config = require('../../config') const config = require('../../config')
const {getImageMimeType} = require('../../utils') const { getImageMimeType } = require('../../utils')
const logger = require('../../logger') const logger = require('../../logger')
const Minio = require('minio') const Minio = require('minio')

View File

@ -3,7 +3,7 @@ const fs = require('fs')
const path = require('path') const path = require('path')
const config = require('../../config') const config = require('../../config')
const {getImageMimeType} = require('../../utils') const { getImageMimeType } = require('../../utils')
const logger = require('../../logger') const logger = require('../../logger')
const AWS = require('aws-sdk') const AWS = require('aws-sdk')

View File

@ -2,7 +2,6 @@
const toobusy = require('toobusy-js') const toobusy = require('toobusy-js')
const response = require('../../response') const response = require('../../response')
const config = require('../../config') const config = require('../../config')

View File

@ -4,7 +4,7 @@ const Router = require('express').Router
const response = require('../response') const response = require('../response')
const {markdownParser} = require('./utils') const { markdownParser } = require('./utils')
const noteRouter = module.exports = Router() const noteRouter = module.exports = Router()

View File

@ -8,7 +8,7 @@ const config = require('../config')
const models = require('../models') const models = require('../models')
const logger = require('../logger') const logger = require('../logger')
const {urlencodedParser} = require('./utils') const { urlencodedParser } = require('./utils')
const statusRouter = module.exports = Router() const statusRouter = module.exports = Router()

View File

@ -8,7 +8,7 @@ const response = require('../response')
const config = require('../config') const config = require('../config')
const models = require('../models') const models = require('../models')
const logger = require('../logger') const logger = require('../logger')
const {generateAvatar} = require('../letter-avatars') const { generateAvatar } = require('../letter-avatars')
const UserRouter = module.exports = Router() const UserRouter = module.exports = Router()

View File

@ -6,7 +6,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {
"test": "npm run-script eslint && npm run-script jsonlint && npm run-script mocha-suite", "test": "npm run-script eslint && npm run-script jsonlint && npm run-script mocha-suite",
"eslint": "node_modules/.bin/eslint lib public test app.js", "eslint": "node_modules/.bin/eslint --max-warnings 0 lib public test app.js",
"jsonlint": "find . -not -path './node_modules/*' -type f -name '*.json' -o -type f -name '*.json.example' | while read json; do echo $json ; jq . $json; done", "jsonlint": "find . -not -path './node_modules/*' -type f -name '*.json' -o -type f -name '*.json.example' | while read json; do echo $json ; jq . $json; done",
"mocha-suite": "NODE_ENV=test CMD_DB_URL=\"sqlite::memory:\" mocha --exit", "mocha-suite": "NODE_ENV=test CMD_DB_URL=\"sqlite::memory:\" mocha --exit",
"standard": "echo 'standard is no longer being used, use `npm run eslint` instead!' && exit 1", "standard": "echo 'standard is no longer being used, use `npm run eslint` instead!' && exit 1",

View File

@ -1,37 +1,37 @@
/* eslint-env browser, jquery */ /* eslint-env browser, jquery */
/* global moment, serverurl */ /* global moment, serverurl */
require('./locale')
require('../css/cover.css')
require('../css/site.css')
import { import {
checkIfAuth, checkIfAuth,
clearLoginState, clearLoginState,
getLoginState, getLoginState,
resetCheckAuth, resetCheckAuth,
setloginStateChangeEvent setloginStateChangeEvent
} from './lib/common/login' } from './lib/common/login'
import { import {
clearDuplicatedHistory, clearDuplicatedHistory,
deleteServerHistory, deleteServerHistory,
getHistory, getHistory,
getStorageHistory, getStorageHistory,
parseHistory, parseHistory,
parseServerToHistory, parseServerToHistory,
parseStorageToHistory, parseStorageToHistory,
postHistoryToServer, postHistoryToServer,
removeHistory, removeHistory,
saveHistory, saveHistory,
saveStorageHistoryToServer saveStorageHistoryToServer
} from './history' } from './history'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import List from 'list.js' import List from 'list.js'
import S from 'string' import S from 'string'
require('./locale')
require('../css/cover.css')
require('../css/site.css')
const options = { const options = {
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'], valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
item: `<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4"> item: `<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
@ -67,27 +67,27 @@ pageInit()
function pageInit () { function pageInit () {
checkIfAuth( checkIfAuth(
data => { data => {
$('.ui-signin').hide() $('.ui-signin').hide()
$('.ui-or').hide() $('.ui-or').hide()
$('.ui-welcome').show() $('.ui-welcome').show()
if (data.photo) $('.ui-avatar').prop('src', data.photo).show() if (data.photo) $('.ui-avatar').prop('src', data.photo).show()
else $('.ui-avatar').prop('src', '').hide() else $('.ui-avatar').prop('src', '').hide()
$('.ui-name').html(data.name) $('.ui-name').html(data.name)
$('.ui-signout').show() $('.ui-signout').show()
$('.ui-history').click() $('.ui-history').click()
parseServerToHistory(historyList, parseHistoryCallback) parseServerToHistory(historyList, parseHistoryCallback)
}, },
() => { () => {
$('.ui-signin').show() $('.ui-signin').show()
$('.ui-or').show() $('.ui-or').show()
$('.ui-welcome').hide() $('.ui-welcome').hide()
$('.ui-avatar').prop('src', '').hide() $('.ui-avatar').prop('src', '').hide()
$('.ui-name').html('') $('.ui-name').html('')
$('.ui-signout').hide() $('.ui-signout').hide()
parseStorageToHistory(historyList, parseHistoryCallback) parseStorageToHistory(historyList, parseHistoryCallback)
} }
) )
} }
$('.masthead-nav li').click(function () { $('.masthead-nav li').click(function () {
@ -132,7 +132,7 @@ function checkHistoryList () {
function parseHistoryCallback (list, notehistory) { function parseHistoryCallback (list, notehistory) {
checkHistoryList() checkHistoryList()
// sort by pinned then timestamp // sort by pinned then timestamp
list.sort('', { list.sort('', {
sortFunction (a, b) { sortFunction (a, b) {
const notea = a.values() const notea = a.values()
@ -152,13 +152,13 @@ function parseHistoryCallback (list, notehistory) {
} }
} }
}) })
// parse filter tags // parse filter tags
const filtertags = [] const filtertags = []
for (let i = 0, l = list.items.length; i < l; i++) { for (let i = 0, l = list.items.length; i < l; i++) {
const tags = list.items[i]._values.tags const tags = list.items[i]._values.tags
if (tags && tags.length > 0) { if (tags && tags.length > 0) {
for (let j = 0; j < tags.length; j++) { for (let j = 0; j < tags.length; j++) {
// push info filtertags if not found // push info filtertags if not found
let found = false let found = false
if (filtertags.includes(tags[j])) { found = true } if (filtertags.includes(tags[j])) { found = true }
if (!found) { filtertags.push(tags[j]) } if (!found) { filtertags.push(tags[j]) }
@ -178,20 +178,20 @@ historyList.on('updated', e => {
const a = itemEl.find('a') const a = itemEl.find('a')
const pin = itemEl.find('.ui-history-pin') const pin = itemEl.find('.ui-history-pin')
const tagsEl = itemEl.find('.tags') const tagsEl = itemEl.find('.tags')
// parse link to element a // parse link to element a
a.attr('href', `${serverurl}/${values.id}`) a.attr('href', `${serverurl}/${values.id}`)
// parse pinned // parse pinned
if (values.pinned) { if (values.pinned) {
pin.addClass('active') pin.addClass('active')
} else { } else {
pin.removeClass('active') pin.removeClass('active')
} }
// parse tags // parse tags
const tags = values.tags const tags = values.tags
if (tags && tags.length > 0 && tagsEl.children().length <= 0) { if (tags && tags.length > 0 && tagsEl.children().length <= 0) {
const labels = [] const labels = []
for (let j = 0; j < tags.length; j++) { for (let j = 0; j < tags.length; j++) {
// push into the item label // push into the item label
labels.push(`<span class='label label-default'>${tags[j]}</span>`) labels.push(`<span class='label label-default'>${tags[j]}</span>`)
} }
tagsEl.html(labels.join(' ')) tagsEl.html(labels.join(' '))
@ -328,7 +328,7 @@ $('.ui-open-history').bind('change', e => {
const reader = new FileReader() const reader = new FileReader()
reader.onload = () => { reader.onload = () => {
const notehistory = JSON.parse(reader.result) const notehistory = JSON.parse(reader.result)
// console.log(notehistory); // console.log(notehistory);
if (!reader.result) return if (!reader.result) return
getHistory(data => { getHistory(data => {
let mergedata = data.concat(notehistory) let mergedata = data.concat(notehistory)

View File

@ -1,6 +1,22 @@
/* eslint-env browser, jquery */ /* eslint-env browser, jquery */
/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
/* global moment, serverurl */ /* global moment, serverurl */
import Prism from 'prismjs'
import hljs from 'highlight.js'
import PDFObject from 'pdfobject'
import S from 'string'
import { saveAs } from 'file-saver'
import escapeHTML from 'escape-html'
import getUIElements from './lib/editor/ui-elements'
import markdownit from 'markdown-it'
import markdownitContainer from 'markdown-it-container'
/* Defined regex markdown it plugins */
import Plugin from 'markdown-it-regexp'
require('prismjs/themes/prism.css') require('prismjs/themes/prism.css')
require('prismjs/components/prism-wiki') require('prismjs/components/prism-wiki')
require('prismjs/components/prism-haskell') require('prismjs/components/prism-haskell')
@ -10,18 +26,9 @@ require('prismjs/components/prism-jsx')
require('prismjs/components/prism-makefile') require('prismjs/components/prism-makefile')
require('prismjs/components/prism-gherkin') require('prismjs/components/prism-gherkin')
import Prism from 'prismjs'
import hljs from 'highlight.js'
import PDFObject from 'pdfobject'
import S from 'string'
import { saveAs } from 'file-saver'
import escapeHTML from 'escape-html'
require('./lib/common/login') require('./lib/common/login')
require('../vendor/md-toc') require('../vendor/md-toc')
var Viz = require('viz.js') var Viz = require('viz.js')
import getUIElements from './lib/editor/ui-elements'
const ui = getUIElements() const ui = getUIElements()
// auto update last change // auto update last change
@ -191,7 +198,7 @@ export function parseMeta (md, edit, view, toc, tocAffix) {
dir = meta.dir dir = meta.dir
breaks = meta.breaks breaks = meta.breaks
} }
// text language // text language
if (lang && typeof lang === 'string') { if (lang && typeof lang === 'string') {
view.attr('lang', lang) view.attr('lang', lang)
toc.attr('lang', lang) toc.attr('lang', lang)
@ -203,7 +210,7 @@ export function parseMeta (md, edit, view, toc, tocAffix) {
tocAffix.removeAttr('lang') tocAffix.removeAttr('lang')
if (edit) { edit.removeAttr('lang', lang) } if (edit) { edit.removeAttr('lang', lang) }
} }
// text direction // text direction
if (dir && typeof dir === 'string') { if (dir && typeof dir === 'string') {
view.attr('dir', dir) view.attr('dir', dir)
toc.attr('dir', dir) toc.attr('dir', dir)
@ -213,7 +220,7 @@ export function parseMeta (md, edit, view, toc, tocAffix) {
toc.removeAttr('dir') toc.removeAttr('dir')
tocAffix.removeAttr('dir') tocAffix.removeAttr('dir')
} }
// breaks // breaks
if (typeof breaks === 'boolean' && !breaks) { if (typeof breaks === 'boolean' && !breaks) {
md.options.breaks = false md.options.breaks = false
} else { } else {
@ -246,7 +253,7 @@ if (typeof window.mermaid !== 'undefined' && window.mermaid) window.mermaid.star
// dynamic event or object binding here // dynamic event or object binding here
export function finishView (view) { export function finishView (view) {
// todo list // todo list
const lis = view.find('li.raw').removeClass('raw').sortByDepth().toArray() const lis = view.find('li.raw').removeClass('raw').sortByDepth().toArray()
for (let li of lis) { for (let li of lis) {
@ -262,7 +269,7 @@ export function finishView (view) {
if (typeof editor !== 'undefined' && window.havePermission()) { disabled = '' } if (typeof editor !== 'undefined' && window.havePermission()) { disabled = '' }
if (/^\s*\[[x ]\]\s*/.test(html)) { if (/^\s*\[[x ]\]\s*/.test(html)) {
li.innerHTML = html.replace(/^\s*\[ \]\s*/, `<input type="checkbox" class="task-list-item-checkbox "${disabled}><label></label>`) li.innerHTML = html.replace(/^\s*\[ \]\s*/, `<input type="checkbox" class="task-list-item-checkbox "${disabled}><label></label>`)
.replace(/^\s*\[x\]\s*/, `<input type="checkbox" class="task-list-item-checkbox" checked ${disabled}><label></label>`) .replace(/^\s*\[x\]\s*/, `<input type="checkbox" class="task-list-item-checkbox" checked ${disabled}><label></label>`)
if (li.tagName.toLowerCase() !== 'li') { if (li.tagName.toLowerCase() !== 'li') {
li.parentElement.setAttribute('class', 'task-list-item') li.parentElement.setAttribute('class', 'task-list-item')
} else { } else {
@ -270,42 +277,42 @@ export function finishView (view) {
} }
} }
if (typeof editor !== 'undefined' && window.havePermission()) { $(li).find('input').change(toggleTodoEvent) } if (typeof editor !== 'undefined' && window.havePermission()) { $(li).find('input').change(toggleTodoEvent) }
// color tag in list will convert it to tag icon with color // color tag in list will convert it to tag icon with color
const tagColor = $(li).closest('ul').find('.color') const tagColor = $(li).closest('ul').find('.color')
tagColor.each((key, value) => { tagColor.each((key, value) => {
$(value).addClass('fa fa-tag').css('color', $(value).attr('data-color')) $(value).addClass('fa fa-tag').css('color', $(value).attr('data-color'))
}) })
} }
// youtube // youtube
view.find('div.youtube.raw').removeClass('raw') view.find('div.youtube.raw').removeClass('raw')
.click(function () { .click(function () {
imgPlayiframe(this, '//www.youtube.com/embed/') imgPlayiframe(this, '//www.youtube.com/embed/')
}) })
// vimeo // vimeo
view.find('div.vimeo.raw').removeClass('raw') view.find('div.vimeo.raw').removeClass('raw')
.click(function () { .click(function () {
imgPlayiframe(this, '//player.vimeo.com/video/') imgPlayiframe(this, '//player.vimeo.com/video/')
}) })
.each((key, value) => { .each((key, value) => {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: `//vimeo.com/api/v2/video/${$(value).attr('data-videoid')}.json`, url: `//vimeo.com/api/v2/video/${$(value).attr('data-videoid')}.json`,
jsonp: 'callback', jsonp: 'callback',
dataType: 'jsonp', dataType: 'jsonp',
success (data) { success (data) {
const thumbnailSrc = data[0].thumbnail_large const thumbnailSrc = data[0].thumbnail_large
const image = `<img src="${thumbnailSrc}" />` const image = `<img src="${thumbnailSrc}" />`
$(value).prepend(image) $(value).prepend(image)
if (window.viewAjaxCallback) window.viewAjaxCallback() if (window.viewAjaxCallback) window.viewAjaxCallback()
} }
}) })
}) })
// gist // gist
view.find('code[data-gist-id]').each((key, value) => { view.find('code[data-gist-id]').each((key, value) => {
if ($(value).children().length === 0) { $(value).gist(window.viewAjaxCallback) } if ($(value).children().length === 0) { $(value).gist(window.viewAjaxCallback) }
}) })
// sequence diagram // sequence diagram
const sequences = view.find('div.sequence-diagram.raw').removeClass('raw') const sequences = view.find('div.sequence-diagram.raw').removeClass('raw')
sequences.each((key, value) => { sequences.each((key, value) => {
try { try {
@ -328,7 +335,7 @@ export function finishView (view) {
console.warn(err) console.warn(err)
} }
}) })
// flowchart // flowchart
const flow = view.find('div.flow-chart.raw').removeClass('raw') const flow = view.find('div.flow-chart.raw').removeClass('raw')
flow.each((key, value) => { flow.each((key, value) => {
try { try {
@ -352,7 +359,7 @@ export function finishView (view) {
console.warn(err) console.warn(err)
} }
}) })
// graphviz // graphviz
var graphvizs = view.find('div.graphviz.raw').removeClass('raw') var graphvizs = view.find('div.graphviz.raw').removeClass('raw')
graphvizs.each(function (key, value) { graphvizs.each(function (key, value) {
try { try {
@ -371,7 +378,7 @@ export function finishView (view) {
console.warn(err) console.warn(err)
} }
}) })
// mermaid // mermaid
const mermaids = view.find('div.mermaid.raw').removeClass('raw') const mermaids = view.find('div.mermaid.raw').removeClass('raw')
mermaids.each((key, value) => { mermaids.each((key, value) => {
try { try {
@ -413,16 +420,16 @@ export function finishView (view) {
console.warn(err) console.warn(err)
} }
}) })
// image href new window(emoji not included) // image href new window(emoji not included)
const images = view.find('img.raw[src]').removeClass('raw') const images = view.find('img.raw[src]').removeClass('raw')
images.each((key, value) => { images.each((key, value) => {
// if it's already wrapped by link, then ignore // if it's already wrapped by link, then ignore
const $value = $(value) const $value = $(value)
$value[0].onload = e => { $value[0].onload = e => {
if (window.viewAjaxCallback) window.viewAjaxCallback() if (window.viewAjaxCallback) window.viewAjaxCallback()
} }
}) })
// blockquote // blockquote
const blockquote = view.find('blockquote.raw').removeClass('raw') const blockquote = view.find('blockquote.raw').removeClass('raw')
const blockquoteP = blockquote.find('p') const blockquoteP = blockquote.find('p')
blockquoteP.each((key, value) => { blockquoteP.each((key, value) => {
@ -430,96 +437,96 @@ export function finishView (view) {
html = replaceExtraTags(html) html = replaceExtraTags(html)
$(value).html(html) $(value).html(html)
}) })
// color tag in blockquote will change its left border color // color tag in blockquote will change its left border color
const blockquoteColor = blockquote.find('.color') const blockquoteColor = blockquote.find('.color')
blockquoteColor.each((key, value) => { blockquoteColor.each((key, value) => {
$(value).closest('blockquote').css('border-left-color', $(value).attr('data-color')) $(value).closest('blockquote').css('border-left-color', $(value).attr('data-color'))
}) })
// slideshare // slideshare
view.find('div.slideshare.raw').removeClass('raw') view.find('div.slideshare.raw').removeClass('raw')
.each((key, value) => { .each((key, value) => {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: `//www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/${$(value).attr('data-slideshareid')}&format=json`, url: `//www.slideshare.net/api/oembed/2?url=http://www.slideshare.net/${$(value).attr('data-slideshareid')}&format=json`,
jsonp: 'callback', jsonp: 'callback',
dataType: 'jsonp', dataType: 'jsonp',
success (data) { success (data) {
const $html = $(data.html) const $html = $(data.html)
const iframe = $html.closest('iframe') const iframe = $html.closest('iframe')
const caption = $html.closest('div') const caption = $html.closest('div')
const inner = $('<div class="inner"></div>').append(iframe) const inner = $('<div class="inner"></div>').append(iframe)
const height = iframe.attr('height') const height = iframe.attr('height')
const width = iframe.attr('width') const width = iframe.attr('width')
const ratio = (height / width) * 100 const ratio = (height / width) * 100
inner.css('padding-bottom', `${ratio}%`) inner.css('padding-bottom', `${ratio}%`)
$(value).html(inner).append(caption) $(value).html(inner).append(caption)
if (window.viewAjaxCallback) window.viewAjaxCallback() if (window.viewAjaxCallback) window.viewAjaxCallback()
} }
}) })
}) })
// speakerdeck // speakerdeck
view.find('div.speakerdeck.raw').removeClass('raw') view.find('div.speakerdeck.raw').removeClass('raw')
.each((key, value) => { .each((key, value) => {
const url = `https://speakerdeck.com/${$(value).attr('data-speakerdeckid')}` const url = `https://speakerdeck.com/${$(value).attr('data-speakerdeckid')}`
const inner = $('<a>Speakerdeck</a>') const inner = $('<a>Speakerdeck</a>')
inner.attr('href', url) inner.attr('href', url)
inner.attr('rel', 'noopener noreferrer') inner.attr('rel', 'noopener noreferrer')
inner.attr('target', '_blank') inner.attr('target', '_blank')
$(value).append(inner) $(value).append(inner)
}) })
// pdf // pdf
view.find('div.pdf.raw').removeClass('raw') view.find('div.pdf.raw').removeClass('raw')
.each(function (key, value) { .each(function (key, value) {
const url = $(value).attr('data-pdfurl') const url = $(value).attr('data-pdfurl')
const inner = $('<div></div>') const inner = $('<div></div>')
$(this).append(inner) $(this).append(inner)
PDFObject.embed(url, inner, { PDFObject.embed(url, inner, {
height: '400px' height: '400px'
}) })
}) })
// syntax highlighting // syntax highlighting
view.find('code.raw').removeClass('raw') view.find('code.raw').removeClass('raw')
.each((key, value) => { .each((key, value) => {
const langDiv = $(value) const langDiv = $(value)
if (langDiv.length > 0) { if (langDiv.length > 0) {
const reallang = langDiv[0].className.replace(/hljs|wrap/g, '').trim() const reallang = langDiv[0].className.replace(/hljs|wrap/g, '').trim()
const codeDiv = langDiv.find('.code') const codeDiv = langDiv.find('.code')
let code = '' let code = ''
if (codeDiv.length > 0) code = codeDiv.html() if (codeDiv.length > 0) code = codeDiv.html()
else code = langDiv.html() else code = langDiv.html()
var result var result
if (!reallang) { if (!reallang) {
result = { result = {
value: code value: code
}
} else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages[reallang])
}
} else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages.wiki)
}
} else if (reallang === 'cmake') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages.makefile)
}
} else {
code = S(code).unescapeHTML().s
const languages = hljs.listLanguages()
if (!languages.includes(reallang)) {
result = hljs.highlightAuto(code)
} else {
result = hljs.highlight(reallang, code)
}
}
if (codeDiv.length > 0) codeDiv.html(result.value)
else langDiv.html(result.value)
} }
}) } else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages[reallang])
}
} else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages.wiki)
}
} else if (reallang === 'cmake') {
code = S(code).unescapeHTML().s
result = {
value: Prism.highlight(code, Prism.languages.makefile)
}
} else {
code = S(code).unescapeHTML().s
const languages = hljs.listLanguages()
if (!languages.includes(reallang)) {
result = hljs.highlightAuto(code)
} else {
result = hljs.highlight(reallang, code)
}
}
if (codeDiv.length > 0) codeDiv.html(result.value)
else langDiv.html(result.value)
}
})
// mathjax // mathjax
const mathjaxdivs = view.find('span.mathjax.raw').removeClass('raw').toArray() const mathjaxdivs = view.find('span.mathjax.raw').removeClass('raw').toArray()
try { try {
@ -533,7 +540,7 @@ export function finishView (view) {
} catch (err) { } catch (err) {
console.warn(err) console.warn(err)
} }
// render title // render title
document.title = renderTitle(view) document.title = renderTitle(view)
} }
@ -593,23 +600,23 @@ window.removeDOMEvents = removeDOMEvents
function generateCleanHTML (view) { function generateCleanHTML (view) {
const src = view.clone() const src = view.clone()
const eles = src.find('*') const eles = src.find('*')
// remove syncscroll parts // remove syncscroll parts
eles.removeClass('part') eles.removeClass('part')
src.find('*[class=""]').removeAttr('class') src.find('*[class=""]').removeAttr('class')
eles.removeAttr('data-startline data-endline') eles.removeAttr('data-startline data-endline')
src.find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll') src.find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll')
// remove gist content // remove gist content
src.find('code[data-gist-id]').children().remove() src.find('code[data-gist-id]').children().remove()
// disable todo list // disable todo list
src.find('input.task-list-item-checkbox').attr('disabled', '') src.find('input.task-list-item-checkbox').attr('disabled', '')
// replace emoji image path // replace emoji image path
src.find('img.emoji').each((key, value) => { src.find('img.emoji').each((key, value) => {
let name = $(value).attr('alt') let name = $(value).attr('alt')
name = name.substr(1) name = name.substr(1)
name = name.slice(0, name.length - 1) name = name.slice(0, name.length - 1)
$(value).attr('src', `https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/images/basic/${name}.png`) $(value).attr('src', `https://cdnjs.cloudflare.com/ajax/libs/emojify.js/1.1.0/images/basic/${name}.png`)
}) })
// replace video to iframe // replace video to iframe
src.find('div[data-videoid]').each((key, value) => { src.find('div[data-videoid]').each((key, value) => {
const id = $(value).attr('data-videoid') const id = $(value).attr('data-videoid')
const style = $(value).attr('style') const style = $(value).attr('style')
@ -645,12 +652,12 @@ export function exportToHTML (view) {
const title = renderTitle(ui.area.markdown) const title = renderTitle(ui.area.markdown)
const filename = `${renderFilename(ui.area.markdown)}.html` const filename = `${renderFilename(ui.area.markdown)}.html`
const src = generateCleanHTML(view) const src = generateCleanHTML(view)
// generate toc // generate toc
const toc = $('#ui-toc').clone() const toc = $('#ui-toc').clone()
toc.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll') toc.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll')
const tocAffix = $('#ui-toc-affix').clone() const tocAffix = $('#ui-toc-affix').clone()
tocAffix.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll') tocAffix.find('*').removeClass('active').find("a[href^='#'][smoothhashscroll]").removeAttr('smoothhashscroll')
// generate html via template // generate html via template
$.get(`${serverurl}/build/html.min.css`, css => { $.get(`${serverurl}/build/html.min.css`, css => {
$.get(`${serverurl}/views/html.hbs`, data => { $.get(`${serverurl}/views/html.hbs`, data => {
const template = window.Handlebars.compile(data) const template = window.Handlebars.compile(data)
@ -665,7 +672,6 @@ export function exportToHTML (view) {
dir: (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : null dir: (md && md.meta && md.meta.dir) ? `dir="${md.meta.dir}"` : null
} }
const html = template(context) const html = template(context)
// console.log(html);
const blob = new Blob([html], { const blob = new Blob([html], {
type: 'text/html;charset=utf-8' type: 'text/html;charset=utf-8'
}) })
@ -780,20 +786,20 @@ export function smoothHashScroll () {
const hash = element.hash const hash = element.hash
if (hash) { if (hash) {
$element.on('click', function (e) { $element.on('click', function (e) {
// store hash // store hash
const hash = decodeURIComponent(this.hash) const hash = decodeURIComponent(this.hash)
// escape special characters in jquery selector // escape special characters in jquery selector
const $hash = $(hash.replace(/(:|\.|\[|\]|,)/g, '\\$1')) const $hash = $(hash.replace(/(:|\.|\[|\]|,)/g, '\\$1'))
// return if no element been selected // return if no element been selected
if ($hash.length <= 0) return if ($hash.length <= 0) return
// prevent default anchor click behavior // prevent default anchor click behavior
e.preventDefault() e.preventDefault()
// animate // animate
$('body, html').stop(true, true).animate({ $('body, html').stop(true, true).animate({
scrollTop: $hash.offset().top scrollTop: $hash.offset().top
}, 100, 'linear', () => { }, 100, 'linear', () => {
// when done, add hash to url // when done, add hash to url
// (default click behaviour) // (default click behaviour)
window.location.hash = hash window.location.hash = hash
}) })
}) })
@ -935,9 +941,6 @@ function highlightRender (code, lang) {
return result.value return result.value
} }
import markdownit from 'markdown-it'
import markdownitContainer from 'markdown-it-container'
export let md = markdownit('default', { export let md = markdownit('default', {
html: true, html: true,
breaks: true, breaks: true,
@ -1035,109 +1038,106 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\n` return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\n`
} }
/* Defined regex markdown it plugins */
import Plugin from 'markdown-it-regexp'
// youtube // youtube
const youtubePlugin = new Plugin( const youtubePlugin = new Plugin(
// regexp to match // regexp to match
/{%youtube\s*([\d\D]*?)\s*%}/, /{%youtube\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const videoid = match[1] const videoid = match[1]
if (!videoid) return if (!videoid) return
const div = $('<div class="youtube raw"></div>') const div = $('<div class="youtube raw"></div>')
div.attr('data-videoid', videoid) div.attr('data-videoid', videoid)
const thumbnailSrc = `//img.youtube.com/vi/${videoid}/hqdefault.jpg` const thumbnailSrc = `//img.youtube.com/vi/${videoid}/hqdefault.jpg`
const image = `<img src="${thumbnailSrc}" />` const image = `<img src="${thumbnailSrc}" />`
div.append(image) div.append(image)
const icon = '<i class="icon fa fa-youtube-play fa-5x"></i>' const icon = '<i class="icon fa fa-youtube-play fa-5x"></i>'
div.append(icon) div.append(icon)
return div[0].outerHTML return div[0].outerHTML
} }
) )
// vimeo // vimeo
const vimeoPlugin = new Plugin( const vimeoPlugin = new Plugin(
// regexp to match // regexp to match
/{%vimeo\s*([\d\D]*?)\s*%}/, /{%vimeo\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const videoid = match[1] const videoid = match[1]
if (!videoid) return if (!videoid) return
const div = $('<div class="vimeo raw"></div>') const div = $('<div class="vimeo raw"></div>')
div.attr('data-videoid', videoid) div.attr('data-videoid', videoid)
const icon = '<i class="icon fa fa-vimeo-square fa-5x"></i>' const icon = '<i class="icon fa fa-vimeo-square fa-5x"></i>'
div.append(icon) div.append(icon)
return div[0].outerHTML return div[0].outerHTML
} }
) )
// gist // gist
const gistPlugin = new Plugin( const gistPlugin = new Plugin(
// regexp to match // regexp to match
/{%gist\s*([\d\D]*?)\s*%}/, /{%gist\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const gistid = match[1] const gistid = match[1]
const code = `<code data-gist-id="${gistid}"></code>` const code = `<code data-gist-id="${gistid}"></code>`
return code return code
} }
) )
// TOC // TOC
const tocPlugin = new Plugin( const tocPlugin = new Plugin(
// regexp to match // regexp to match
/^\[TOC\]$/i, /^\[TOC\]$/i,
(match, utils) => '<div class="toc"></div>' (match, utils) => '<div class="toc"></div>'
) )
// slideshare // slideshare
const slidesharePlugin = new Plugin( const slidesharePlugin = new Plugin(
// regexp to match // regexp to match
/{%slideshare\s*([\d\D]*?)\s*%}/, /{%slideshare\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const slideshareid = match[1] const slideshareid = match[1]
const div = $('<div class="slideshare raw"></div>') const div = $('<div class="slideshare raw"></div>')
div.attr('data-slideshareid', slideshareid) div.attr('data-slideshareid', slideshareid)
return div[0].outerHTML return div[0].outerHTML
} }
) )
// speakerdeck // speakerdeck
const speakerdeckPlugin = new Plugin( const speakerdeckPlugin = new Plugin(
// regexp to match // regexp to match
/{%speakerdeck\s*([\d\D]*?)\s*%}/, /{%speakerdeck\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const speakerdeckid = match[1] const speakerdeckid = match[1]
const div = $('<div class="speakerdeck raw"></div>') const div = $('<div class="speakerdeck raw"></div>')
div.attr('data-speakerdeckid', speakerdeckid) div.attr('data-speakerdeckid', speakerdeckid)
return div[0].outerHTML return div[0].outerHTML
} }
) )
// pdf // pdf
const pdfPlugin = new Plugin( const pdfPlugin = new Plugin(
// regexp to match // regexp to match
/{%pdf\s*([\d\D]*?)\s*%}/, /{%pdf\s*([\d\D]*?)\s*%}/,
(match, utils) => { (match, utils) => {
const pdfurl = match[1] const pdfurl = match[1]
if (!isValidURL(pdfurl)) return match[0] if (!isValidURL(pdfurl)) return match[0]
const div = $('<div class="pdf raw"></div>') const div = $('<div class="pdf raw"></div>')
div.attr('data-pdfurl', pdfurl) div.attr('data-pdfurl', pdfurl)
return div[0].outerHTML return div[0].outerHTML
} }
) )
const emojijsPlugin = new Plugin( const emojijsPlugin = new Plugin(
// regexp to match emoji shortcodes :something: // regexp to match emoji shortcodes :something:
// We generate an universal regex that guaranteed only contains the // We generate an universal regex that guaranteed only contains the
// emojies we have available. This should prevent all false-positives // emojies we have available. This should prevent all false-positives
new RegExp(':(' + window.emojify.emojiNames.map((item) => { return RegExp.escape(item) }).join('|') + '):', 'i'), new RegExp(':(' + window.emojify.emojiNames.map((item) => { return RegExp.escape(item) }).join('|') + '):', 'i'),
(match, utils) => { (match, utils) => {
const emoji = match[1].toLowerCase() const emoji = match[1].toLowerCase()
const div = $(`<img class="emoji" alt=":${emoji}:" src="${serverurl}/build/emojify.js/dist/images/basic/${emoji}.png"></img>`) const div = $(`<img class="emoji" alt=":${emoji}:" src="${serverurl}/build/emojify.js/dist/images/basic/${emoji}.png"></img>`)
return div[0].outerHTML return div[0].outerHTML
} }
) )
// yaml meta, from https://github.com/eugeneware/remarkable-meta // yaml meta, from https://github.com/eugeneware/remarkable-meta

View File

@ -1,4 +1,5 @@
/* eslint-env browser, jquery */ /* eslint-env browser, jquery */
/* eslint no-console: ["error", { allow: ["warn", "error", "debug"] }] */
/* global serverurl, moment */ /* global serverurl, moment */
import store from 'store' import store from 'store'
@ -12,11 +13,11 @@ import {
} from './utils' } from './utils'
import { import {
checkIfAuth checkIfAuth
} from './lib/common/login' } from './lib/common/login'
import { import {
urlpath urlpath
} from './lib/config' } from './lib/config'
window.migrateHistoryFromTempCallback = null window.migrateHistoryFromTempCallback = null
@ -28,40 +29,40 @@ function migrateHistoryFromTemp () {
$.get(`${serverurl}/temp`, { $.get(`${serverurl}/temp`, {
tempid: url('#tempid') tempid: url('#tempid')
}) })
.done(data => { .done(data => {
if (data && data.temp) { if (data && data.temp) {
getStorageHistory(olddata => { getStorageHistory(olddata => {
if (!olddata || olddata.length === 0) { if (!olddata || olddata.length === 0) {
saveHistoryToStorage(JSON.parse(data.temp)) saveHistoryToStorage(JSON.parse(data.temp))
} }
}) })
}
})
.always(() => {
let hash = location.hash.split('#')[1]
hash = hash.split('&')
for (let i = 0; i < hash.length; i++) {
if (hash[i].indexOf('tempid') === 0) {
hash.splice(i, 1)
i--
} }
} })
hash = hash.join('&') .always(() => {
location.hash = hash let hash = location.hash.split('#')[1]
if (window.migrateHistoryFromTempCallback) { window.migrateHistoryFromTempCallback() } hash = hash.split('&')
}) for (let i = 0; i < hash.length; i++) {
if (hash[i].indexOf('tempid') === 0) {
hash.splice(i, 1)
i--
}
}
hash = hash.join('&')
location.hash = hash
if (window.migrateHistoryFromTempCallback) { window.migrateHistoryFromTempCallback() }
})
} }
} }
export function saveHistory (notehistory) { export function saveHistory (notehistory) {
checkIfAuth( checkIfAuth(
() => { () => {
saveHistoryToServer(notehistory) saveHistoryToServer(notehistory)
}, },
() => { () => {
saveHistoryToStorage(notehistory) saveHistoryToStorage(notehistory)
} }
) )
} }
function saveHistoryToStorage (notehistory) { function saveHistoryToStorage (notehistory) {
@ -80,9 +81,9 @@ export function saveStorageHistoryToServer (callback) {
$.post(`${serverurl}/history`, { $.post(`${serverurl}/history`, {
history: data history: data
}) })
.done(data => { .done(data => {
callback(data) callback(data)
}) })
} }
} }
@ -109,7 +110,7 @@ export function clearDuplicatedHistory (notehistory) {
} }
function addHistory (id, text, time, tags, pinned, notehistory) { function addHistory (id, text, time, tags, pinned, notehistory) {
// only add when note id exists // only add when note id exists
if (id) { if (id) {
notehistory.push({ notehistory.push({
id, id,
@ -135,14 +136,14 @@ export function removeHistory (id, notehistory) {
// used for inner // used for inner
export function writeHistory (title, tags) { export function writeHistory (title, tags) {
checkIfAuth( checkIfAuth(
() => { () => {
// no need to do this anymore, this will count from server-side // no need to do this anymore, this will count from server-side
// writeHistoryToServer(title, tags); // writeHistoryToServer(title, tags);
}, },
() => { () => {
writeHistoryToStorage(title, tags) writeHistoryToStorage(title, tags)
} }
) )
} }
function writeHistoryToStorage (title, tags) { function writeHistoryToStorage (title, tags) {
@ -163,7 +164,7 @@ if (!Array.isArray) {
} }
function renderHistory (title, tags) { function renderHistory (title, tags) {
// console.debug(tags); // console.debug(tags);
const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1] const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]
return { return {
id, id,
@ -175,7 +176,7 @@ function renderHistory (title, tags) {
function generateHistory (title, tags, notehistory) { function generateHistory (title, tags, notehistory) {
const info = renderHistory(title, tags) const info = renderHistory(title, tags)
// keep any pinned data // keep any pinned data
let pinned = false let pinned = false
for (let i = 0; i < notehistory.length; i++) { for (let i = 0; i < notehistory.length; i++) {
if (notehistory[i].id === info.id && notehistory[i].pinned) { if (notehistory[i].id === info.id && notehistory[i].pinned) {
@ -192,25 +193,25 @@ function generateHistory (title, tags, notehistory) {
// used for outer // used for outer
export function getHistory (callback) { export function getHistory (callback) {
checkIfAuth( checkIfAuth(
() => { () => {
getServerHistory(callback) getServerHistory(callback)
}, },
() => { () => {
getStorageHistory(callback) getStorageHistory(callback)
} }
) )
} }
function getServerHistory (callback) { function getServerHistory (callback) {
$.get(`${serverurl}/history`) $.get(`${serverurl}/history`)
.done(data => { .done(data => {
if (data.history) { if (data.history) {
callback(data.history) callback(data.history)
} }
}) })
.fail((xhr, status, error) => { .fail((xhr, status, error) => {
console.error(xhr.responseText) console.error(xhr.responseText)
}) })
} }
export function getStorageHistory (callback) { export function getStorageHistory (callback) {
@ -225,25 +226,25 @@ export function getStorageHistory (callback) {
export function parseHistory (list, callback) { export function parseHistory (list, callback) {
checkIfAuth( checkIfAuth(
() => { () => {
parseServerToHistory(list, callback) parseServerToHistory(list, callback)
}, },
() => { () => {
parseStorageToHistory(list, callback) parseStorageToHistory(list, callback)
} }
) )
} }
export function parseServerToHistory (list, callback) { export function parseServerToHistory (list, callback) {
$.get(`${serverurl}/history`) $.get(`${serverurl}/history`)
.done(data => { .done(data => {
if (data.history) { if (data.history) {
parseToHistory(list, data.history, callback) parseToHistory(list, data.history, callback)
} }
}) })
.fail((xhr, status, error) => { .fail((xhr, status, error) => {
console.error(xhr.responseText) console.error(xhr.responseText)
}) })
} }
export function parseStorageToHistory (list, callback) { export function parseStorageToHistory (list, callback) {
@ -269,15 +270,15 @@ function parseToHistory (list, notehistory, callback) {
} catch (err) { } catch (err) {
console.error(err) console.error(err)
} }
// parse time to timestamp and fromNow // parse time to timestamp and fromNow
const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a')) const timestamp = (typeof notehistory[i].time === 'number' ? moment(notehistory[i].time) : moment(notehistory[i].time, 'MMMM Do YYYY, h:mm:ss a'))
notehistory[i].timestamp = timestamp.valueOf() notehistory[i].timestamp = timestamp.valueOf()
notehistory[i].fromNow = timestamp.fromNow() notehistory[i].fromNow = timestamp.fromNow()
notehistory[i].time = timestamp.format('llll') notehistory[i].time = timestamp.format('llll')
// prevent XSS // prevent XSS
notehistory[i].text = S(notehistory[i].text).escapeHTML().s notehistory[i].text = S(notehistory[i].text).escapeHTML().s
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? S(notehistory[i].tags).escapeHTML().s.split(',') : [] notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? S(notehistory[i].tags).escapeHTML().s.split(',') : []
// add to list // add to list
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) } if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -60,22 +60,22 @@ export function checkIfAuth (yesCallback, noCallback) {
if (checkLoginStateChanged()) checkAuth = false if (checkLoginStateChanged()) checkAuth = false
if (!checkAuth || typeof cookieLoginState === 'undefined') { if (!checkAuth || typeof cookieLoginState === 'undefined') {
$.get(`${serverurl}/me`) $.get(`${serverurl}/me`)
.done(data => { .done(data => {
if (data && data.status === 'ok') { if (data && data.status === 'ok') {
profile = data profile = data
yesCallback(profile) yesCallback(profile)
setLoginState(true, data.id) setLoginState(true, data.id)
} else { } else {
noCallback() noCallback()
setLoginState(false) setLoginState(false)
} }
}) })
.fail(() => { .fail(() => {
noCallback() noCallback()
}) })
.always(() => { .always(() => {
checkAuth = true checkAuth = true
}) })
} else if (cookieLoginState) { } else if (cookieLoginState) {
yesCallback(profile) yesCallback(profile)
} else { } else {

View File

@ -51,7 +51,7 @@ export function insertText (cm, text, cursorEnd = 0) {
let cursor = cm.getCursor() let cursor = cm.getCursor()
cm.replaceSelection(text, cursor, cursor) cm.replaceSelection(text, cursor, cursor)
cm.focus() cm.focus()
cm.setCursor({line: cursor.line, ch: cursor.ch + cursorEnd}) cm.setCursor({ line: cursor.line, ch: cursor.ch + cursorEnd })
} }
export function insertLink (cm, isImage) { export function insertLink (cm, isImage) {
@ -80,7 +80,7 @@ export function insertLink (cm, isImage) {
cm.setSelections(ranges) cm.setSelections(ranges)
} else { } else {
cm.replaceRange(symbol + linkEnd, cursor, cursor) cm.replaceRange(symbol + linkEnd, cursor, cursor)
cm.setCursor({line: cursor.line, ch: cursor.ch + symbol.length + linkEnd.length}) cm.setCursor({ line: cursor.line, ch: cursor.ch + symbol.length + linkEnd.length })
} }
} }
cm.focus() cm.focus()
@ -88,8 +88,8 @@ export function insertLink (cm, isImage) {
export function insertHeader (cm) { export function insertHeader (cm) {
let cursor = cm.getCursor() let cursor = cm.getCursor()
let startOfLine = {line: cursor.line, ch: 0} let startOfLine = { line: cursor.line, ch: 0 }
let startOfLineText = cm.getRange(startOfLine, {line: cursor.line, ch: 1}) let startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
// See if it is already a header // See if it is already a header
if (startOfLineText === '#') { if (startOfLineText === '#') {
cm.replaceRange('#', startOfLine, startOfLine) cm.replaceRange('#', startOfLine, startOfLine)
@ -108,14 +108,14 @@ export function insertOnStartOfLines (cm, symbol) {
if (!range.empty()) { if (!range.empty()) {
const from = range.from() const from = range.from()
const to = range.to() const to = range.to()
let selection = cm.getRange({line: from.line, ch: 0}, to) let selection = cm.getRange({ line: from.line, ch: 0 }, to)
selection = selection.replace(/\n/g, '\n' + symbol) selection = selection.replace(/\n/g, '\n' + symbol)
selection = symbol + selection selection = symbol + selection
cm.replaceRange(selection, from, to) cm.replaceRange(selection, from, to)
} else { } else {
cm.replaceRange(symbol, {line: cursor.line, ch: 0}, {line: cursor.line, ch: 0}) cm.replaceRange(symbol, { line: cursor.line, ch: 0 }, { line: cursor.line, ch: 0 })
} }
} }
cm.setCursor({line: cursor.line, ch: cursor.ch + symbol.length}) cm.setCursor({ line: cursor.line, ch: cursor.ch + symbol.length })
cm.focus() cm.focus()
} }

View File

@ -188,7 +188,7 @@ function buildMapInner (callback) {
} }
nonEmptyList.push(0) nonEmptyList.push(0)
// make the first line go top // make the first line go top
_scrollMap[0] = viewTop _scrollMap[0] = viewTop
const parts = markdownArea.find('.part').toArray() const parts = markdownArea.find('.part').toArray()
@ -336,7 +336,7 @@ export function syncScrollToView (event, preventAnimate) {
const scrollInfo = editor.getScrollInfo() const scrollInfo = editor.getScrollInfo()
const textHeight = editor.defaultTextHeight() const textHeight = editor.defaultTextHeight()
lineNo = Math.floor(scrollInfo.top / textHeight) lineNo = Math.floor(scrollInfo.top / textHeight)
// if reach the last line, will start lerp to the bottom // if reach the last line, will start lerp to the bottom
const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight) const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) { if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
topDiffPercent = diffToBottom / textHeight topDiffPercent = diffToBottom / textHeight

View File

@ -1,29 +1,29 @@
/* eslint-env browser, jquery */ /* eslint-env browser, jquery */
/* global refreshView */ /* global refreshView */
import {
autoLinkify,
deduplicatedHeaderId,
removeDOMEvents,
finishView,
generateToc,
md,
parseMeta,
postProcess,
renderTOC,
scrollToHash,
smoothHashScroll,
updateLastChange
} from './extra'
import { preventXSS } from './render'
require('../css/extra.css') require('../css/extra.css')
require('../css/slide-preview.css') require('../css/slide-preview.css')
require('../css/site.css') require('../css/site.css')
require('highlight.js/styles/github-gist.css') require('highlight.js/styles/github-gist.css')
import {
autoLinkify,
deduplicatedHeaderId,
removeDOMEvents,
finishView,
generateToc,
md,
parseMeta,
postProcess,
renderTOC,
scrollToHash,
smoothHashScroll,
updateLastChange
} from './extra'
import { preventXSS } from './render'
const markdown = $('#doc.markdown-body') const markdown = $('#doc.markdown-body')
const text = markdown.text() const text = markdown.text()
const lastMeta = md.meta const lastMeta = md.meta
@ -38,7 +38,7 @@ if (md.meta.type && md.meta.type === 'slide') {
const slides = window.RevealMarkdown.slidify(text, slideOptions) const slides = window.RevealMarkdown.slidify(text, slideOptions)
markdown.html(slides) markdown.html(slides)
window.RevealMarkdown.initialize() window.RevealMarkdown.initialize()
// prevent XSS // prevent XSS
markdown.html(preventXSS(markdown.html())) markdown.html(preventXSS(markdown.html()))
markdown.addClass('slides') markdown.addClass('slides')
} else { } else {
@ -46,12 +46,12 @@ if (md.meta.type && md.meta.type === 'slide') {
refreshView() refreshView()
markdown.removeClass('slides') markdown.removeClass('slides')
} }
// only render again when meta changed // only render again when meta changed
if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) { if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) {
parseMeta(md, null, markdown, $('#ui-toc'), $('#ui-toc-affix')) parseMeta(md, null, markdown, $('#ui-toc'), $('#ui-toc-affix'))
rendered = md.render(text) rendered = md.render(text)
} }
// prevent XSS // prevent XSS
rendered = preventXSS(rendered) rendered = preventXSS(rendered)
const result = postProcess(rendered) const result = postProcess(rendered)
markdown.html(result.html()) markdown.html(result.html())
@ -98,14 +98,14 @@ function generateScrollspy () {
} }
function windowResize () { function windowResize () {
// toc right // toc right
const paddingRight = parseFloat(markdown.css('padding-right')) const paddingRight = parseFloat(markdown.css('padding-right'))
const right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight)) const right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight))
toc.css('right', `${right}px`) toc.css('right', `${right}px`)
// affix toc left // affix toc left
let newbool let newbool
const rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2 const rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2
// for ipad or wider device // for ipad or wider device
if (rightMargin >= 133) { if (rightMargin >= 133) {
newbool = true newbool = true
const affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2 const affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2
@ -126,7 +126,7 @@ $(document).ready(() => {
windowResize() windowResize()
generateScrollspy() generateScrollspy()
setTimeout(scrollToHash, 0) setTimeout(scrollToHash, 0)
// tooltip // tooltip
$('[data-toggle="tooltip"]').tooltip() $('[data-toggle="tooltip"]').tooltip()
}) })

View File

@ -44,7 +44,7 @@ var filterXSSOptions = {
onIgnoreTag: function (tag, html, options) { onIgnoreTag: function (tag, html, options) {
// allow comment tag // allow comment tag
if (tag === '!--') { if (tag === '!--') {
// do not filter its attributes // do not filter its attributes
return html.replace(/<(?!!--)/g, '&lt;').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '&gt;').replace(/__HTML_COMMENT_END__/g, '-->') return html.replace(/<(?!!--)/g, '&lt;').replace(/-->/g, '__HTML_COMMENT_END__').replace(/>/g, '&gt;').replace(/__HTML_COMMENT_END__/g, '-->')
} }
}, },

View File

@ -1,12 +1,12 @@
/* eslint-env browser, jquery */ /* eslint-env browser, jquery */
/* global serverurl, Reveal, RevealMarkdown */ /* global serverurl, Reveal, RevealMarkdown */
require('../css/extra.css')
require('../css/site.css')
import { preventXSS } from './render' import { preventXSS } from './render'
import { md, updateLastChange, removeDOMEvents, finishView } from './extra' import { md, updateLastChange, removeDOMEvents, finishView } from './extra'
require('../css/extra.css')
require('../css/site.css')
const body = preventXSS($('.slides').text()) const body = preventXSS($('.slides').text())
window.createtime = window.lastchangeui.time.attr('data-createtime') window.createtime = window.lastchangeui.time.attr('data-createtime')
@ -17,7 +17,7 @@ $('.ui-edit').attr('href', `${url}/edit`)
$('.ui-print').attr('href', `${url}?print-pdf`) $('.ui-print').attr('href', `${url}?print-pdf`)
$(document).ready(() => { $(document).ready(() => {
// tooltip // tooltip
$('[data-toggle="tooltip"]').tooltip() $('[data-toggle="tooltip"]').tooltip()
}) })
@ -127,7 +127,7 @@ function renderSlide (event) {
Reveal.addEventListener('ready', event => { Reveal.addEventListener('ready', event => {
renderSlide(event) renderSlide(event)
const markdown = $(event.currentSlide) const markdown = $(event.currentSlide)
// force browser redraw // force browser redraw
setTimeout(() => { setTimeout(() => {
markdown.hide().show(0) markdown.hide().show(0)
}, 0) }, 0)