Merge pull request #97 from SISheogorath/fix/linting

Fix eslint warnings
This commit is contained in:
Sheogorath 2019-06-04 16:09:46 +02:00 committed by GitHub
commit 6462968e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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)