mirror of https://github.com/status-im/codimd.git
Merge pull request #1190 from hackmdio/refactor
replace package with npm published version
This commit is contained in:
commit
1434cdb6b2
|
@ -8,12 +8,6 @@ env:
|
|||
|
||||
jobs:
|
||||
include:
|
||||
- env: task=npm-test
|
||||
node_js:
|
||||
- 6
|
||||
before_install:
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version "$YARN_VERSION"
|
||||
- export PATH="$HOME/.yarn/bin:$PATH"
|
||||
- env: task=npm-test
|
||||
node_js:
|
||||
- 8
|
||||
|
|
118
bin/manage_users
118
bin/manage_users
|
@ -1,119 +1,117 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
// First configure the logger so it does not spam the console
|
||||
const logger = require("../lib/logger");
|
||||
logger.transports.forEach((transport) => transport.level = "warning")
|
||||
const logger = require('../lib/logger')
|
||||
logger.transports.forEach((transport) => {
|
||||
transport.level = 'warning'
|
||||
})
|
||||
|
||||
const models = require("../lib/models/");
|
||||
const readline = require("readline-sync");
|
||||
const minimist = require("minimist");
|
||||
const models = require('../lib/models/')
|
||||
const readline = require('readline-sync')
|
||||
const minimist = require('minimist')
|
||||
|
||||
function showUsage(tips) {
|
||||
function showUsage (tips) {
|
||||
console.log(`${tips}
|
||||
|
||||
Command-line utility to create users for email-signin.
|
||||
|
||||
Usage: bin/manage_users [--pass password] (--add | --del) user-email
|
||||
Options:
|
||||
--add Add user with the specified user-email
|
||||
--del Delete user with specified user-email
|
||||
--reset Reset user password with specified user-email
|
||||
--pass Use password from cmdline rather than prompting
|
||||
`);
|
||||
process.exit(1);
|
||||
--add\tAdd user with the specified user-email
|
||||
--del\tDelete user with specified user-email
|
||||
--reset\tReset user password with specified user-email
|
||||
--pass\tUse password from cmdline rather than prompting
|
||||
`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function getPass(argv, action) {
|
||||
function getPass (argv, action) {
|
||||
// Find whether we use cmdline or prompt password
|
||||
if(typeof argv["pass"] !== 'string') {
|
||||
return readline.question(`Password for ${argv[action]}:`, {hideEchoBack: true});
|
||||
if (typeof argv['pass'] !== 'string') {
|
||||
return readline.question(`Password for ${argv[action]}:`, { hideEchoBack: true })
|
||||
}
|
||||
console.log("Using password from commandline...");
|
||||
return argv["pass"];
|
||||
console.log('Using password from commandline...')
|
||||
return argv['pass']
|
||||
}
|
||||
|
||||
// Using an async function to be able to use await inside
|
||||
async function createUser(argv) {
|
||||
const existing_user = await models.User.findOne({where: {email: argv["add"]}});
|
||||
async function createUser (argv) {
|
||||
const existingUser = await models.User.findOne({ where: { email: argv['add'] } })
|
||||
// Cannot create already-existing users
|
||||
if(existing_user != undefined) {
|
||||
console.log(`User with e-mail ${existing_user.email} already exists! Aborting ...`);
|
||||
process.exit(1);
|
||||
if (existingUser !== undefined) {
|
||||
console.log(`User with e-mail ${existingUser.email} already exists! Aborting ...`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const pass = getPass(argv, "add");
|
||||
|
||||
const pass = getPass(argv, 'add')
|
||||
|
||||
// Lets try to create, and check success
|
||||
const ref = await models.User.create({email: argv["add"], password: pass});
|
||||
if(ref == undefined) {
|
||||
console.log(`Could not create user with email ${argv["add"]}`);
|
||||
process.exit(1);
|
||||
} else
|
||||
console.log(`Created user with email ${argv["add"]}`);
|
||||
const ref = await models.User.create({ email: argv['add'], password: pass })
|
||||
if (ref === undefined) {
|
||||
console.log(`Could not create user with email ${argv['add']}`)
|
||||
process.exit(1)
|
||||
} else { console.log(`Created user with email ${argv['add']}`) }
|
||||
}
|
||||
|
||||
// Using an async function to be able to use await inside
|
||||
async function deleteUser(argv) {
|
||||
async function deleteUser (argv) {
|
||||
// Cannot delete non-existing users
|
||||
const existing_user = await models.User.findOne({where: {email: argv["del"]}});
|
||||
if(existing_user === undefined) {
|
||||
console.log(`User with e-mail ${argv["del"]} does not exist, cannot delete`);
|
||||
process.exit(1);
|
||||
const existingUser = await models.User.findOne({ where: { email: argv['del'] } })
|
||||
if (existingUser === undefined) {
|
||||
console.log(`User with e-mail ${argv['del']} does not exist, cannot delete`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Sadly .destroy() does not return any success value with all
|
||||
// backends. See sequelize #4124
|
||||
await existing_user.destroy();
|
||||
console.log(`Deleted user ${argv["del"]} ...`);
|
||||
await existingUser.destroy()
|
||||
console.log(`Deleted user ${argv['del']} ...`)
|
||||
}
|
||||
|
||||
|
||||
// Using an async function to be able to use await inside
|
||||
async function resetUser(argv) {
|
||||
const existing_user = await models.User.findOne({where: {email: argv["reset"]}});
|
||||
async function resetUser (argv) {
|
||||
const existingUser = await models.User.findOne({ where: { email: argv['reset'] } })
|
||||
// Cannot reset non-existing users
|
||||
if(existing_user == undefined) {
|
||||
console.log(`User with e-mail ${argv["reset"]} does not exist, cannot reset`);
|
||||
process.exit(1);
|
||||
if (existingUser === undefined) {
|
||||
console.log(`User with e-mail ${argv['reset']} does not exist, cannot reset`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const pass = getPass(argv, "reset");
|
||||
const pass = getPass(argv, 'reset')
|
||||
|
||||
// set password and save
|
||||
existing_user.password = pass;
|
||||
await existing_user.save();
|
||||
console.log(`User with email ${argv["reset"]} password has been reset`);
|
||||
existingUser.password = pass
|
||||
await existingUser.save()
|
||||
console.log(`User with email ${argv['reset']} password has been reset`)
|
||||
}
|
||||
|
||||
const options = {
|
||||
add: createUser,
|
||||
del: deleteUser,
|
||||
reset: resetUser,
|
||||
};
|
||||
reset: resetUser
|
||||
}
|
||||
|
||||
// Perform commandline-parsing
|
||||
const argv = minimist(process.argv.slice(2));
|
||||
const argv = minimist(process.argv.slice(2))
|
||||
|
||||
const keys = Object.keys(options);
|
||||
const opts = keys.filter((key) => argv[key] !== undefined);
|
||||
const action = opts[0];
|
||||
const keys = Object.keys(options)
|
||||
const opts = keys.filter((key) => argv[key] !== undefined)
|
||||
const action = opts[0]
|
||||
|
||||
// Check for options missing
|
||||
if (opts.length === 0) {
|
||||
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`);
|
||||
showUsage(`You did not specify either ${keys.map((key) => `--${key}`).join(' or ')}!`)
|
||||
}
|
||||
|
||||
// Check if both are specified
|
||||
if (opts.length > 1) {
|
||||
showUsage(`You cannot ${action.join(' and ')} at the same time!`);
|
||||
showUsage(`You cannot ${action.join(' and ')} at the same time!`)
|
||||
}
|
||||
// Check if not string
|
||||
if (typeof argv[action] !== 'string') {
|
||||
showUsage(`You must follow an email after --${action}`);
|
||||
showUsage(`You must follow an email after --${action}`)
|
||||
}
|
||||
|
||||
// Call respective processing functions
|
||||
options[action](argv).then(function() {
|
||||
process.exit(0);
|
||||
});
|
||||
options[action](argv).then(function () {
|
||||
process.exit(0)
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils')
|
||||
const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
|
||||
|
||||
module.exports = {
|
||||
sourceURL: process.env.CMD_SOURCE_URL,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils')
|
||||
const { toBooleanConfig, toArrayConfig, toIntegerConfig } = require('./utils')
|
||||
|
||||
module.exports = {
|
||||
domain: process.env.HMD_DOMAIN,
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
const crypto = require('crypto')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const {merge} = require('lodash')
|
||||
const { merge } = require('lodash')
|
||||
const deepFreeze = require('deep-freeze')
|
||||
const {Environment, Permission} = require('./enum')
|
||||
const { Environment, Permission } = require('./enum')
|
||||
const logger = require('../logger')
|
||||
const {getGitCommit, getGitHubURL} = require('./utils')
|
||||
const { getGitCommit, getGitHubURL } = require('./utils')
|
||||
|
||||
const appRootPath = path.resolve(__dirname, '../../')
|
||||
const env = process.env.NODE_ENV || Environment.development
|
||||
|
@ -17,7 +17,7 @@ const debugConfig = {
|
|||
}
|
||||
|
||||
// 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 sourceURL = getGitHubURL(repository.url, commitID || version)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
|
||||
const {toBooleanConfig} = require('./utils')
|
||||
const { toBooleanConfig } = require('./utils')
|
||||
|
||||
module.exports = {
|
||||
debug: toBooleanConfig(process.env.DEBUG),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict'
|
||||
// history
|
||||
// external modules
|
||||
var LZString = require('lz-string')
|
||||
var LZString = require('@hackmd/lz-string')
|
||||
|
||||
// core
|
||||
var config = require('./config')
|
||||
|
|
|
@ -30,14 +30,14 @@ exports.generateAvatarURL = function (name, email = '', big = true) {
|
|||
if (typeof email !== 'string') {
|
||||
email = '' + name + '@example.com'
|
||||
}
|
||||
name=encodeURIComponent(name)
|
||||
name = encodeURIComponent(name)
|
||||
|
||||
let hash = crypto.createHash('md5')
|
||||
hash.update(email.toLowerCase())
|
||||
let hexDigest = hash.digest('hex')
|
||||
|
||||
if (email !== '' && config.allowGravatar) {
|
||||
photo = 'https://www.gravatar.com/avatar/' + hexDigest;
|
||||
photo = 'https://www.gravatar.com/avatar/' + hexDigest
|
||||
if (big) {
|
||||
photo += '?s=400'
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
'use strict'
|
||||
const {createLogger, format, transports} = require('winston')
|
||||
const { createLogger, format, transports } = require('winston')
|
||||
|
||||
const logger = createLogger({
|
||||
level: 'debug',
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
'use strict'
|
||||
module.exports = {
|
||||
up: function (queryInterface, Sequelize) {
|
||||
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT('long') })
|
||||
queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT('long') })
|
||||
queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT('long') })
|
||||
queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT('long') })
|
||||
},
|
||||
|
||||
down: function (queryInterface, Sequelize) {
|
||||
queryInterface.changeColumn('Notes', 'content', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Revisions', 'patch', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Revisions', 'content', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Revisions', 'lastContent', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Notes', 'content', { type: Sequelize.TEXT })
|
||||
queryInterface.changeColumn('Revisions', 'patch', { type: Sequelize.TEXT })
|
||||
queryInterface.changeColumn('Revisions', 'content', { type: Sequelize.TEXT })
|
||||
queryInterface.changeColumn('Revisions', 'lastContent', { type: Sequelize.TEXT })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
module.exports = {
|
||||
up: function (queryInterface, Sequelize) {
|
||||
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT('long')})
|
||||
queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT('long') })
|
||||
queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT('long') })
|
||||
},
|
||||
|
||||
down: function (queryInterface, Sequelize) {
|
||||
queryInterface.changeColumn('Notes', 'authorship', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Revisions', 'authorship', {type: Sequelize.TEXT})
|
||||
queryInterface.changeColumn('Notes', 'authorship', { type: Sequelize.TEXT })
|
||||
queryInterface.changeColumn('Revisions', 'authorship', { type: Sequelize.TEXT })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
module.exports = {
|
||||
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) {
|
||||
queryInterface.changeColumn('Notes', 'permission', {type: Sequelize.ENUM('freely', 'editable', 'locked', 'private')})
|
||||
queryInterface.changeColumn('Notes', 'permission', { type: Sequelize.ENUM('freely', 'editable', 'locked', 'private') })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@ module.exports = function (sequelize, DataTypes) {
|
|||
unique: true,
|
||||
fields: ['noteId', 'userId']
|
||||
}
|
||||
],
|
||||
classMethods: {
|
||||
associate: function (models) {
|
||||
]
|
||||
})
|
||||
|
||||
Author.associate = function (models) {
|
||||
Author.belongsTo(models.Note, {
|
||||
foreignKey: 'noteId',
|
||||
as: 'note',
|
||||
|
@ -36,7 +37,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||
hooks: true
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return Author
|
||||
}
|
||||
|
|
|
@ -3,14 +3,16 @@
|
|||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var Sequelize = require('sequelize')
|
||||
const {cloneDeep} = require('lodash')
|
||||
const { cloneDeep } = require('lodash')
|
||||
|
||||
// core
|
||||
var config = require('../config')
|
||||
var logger = require('../logger')
|
||||
|
||||
var dbconfig = cloneDeep(config.db)
|
||||
dbconfig.logging = config.debug ? logger.info : false
|
||||
dbconfig.logging = config.debug ? (data) => {
|
||||
logger.info(data)
|
||||
} : false
|
||||
|
||||
var sequelize = null
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// external modules
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
var LZString = require('lz-string')
|
||||
var LZString = require('@hackmd/lz-string')
|
||||
var base64url = require('base64url')
|
||||
var md = require('markdown-it')()
|
||||
var metaMarked = require('meta-marked')
|
||||
|
@ -11,9 +11,10 @@ var shortId = require('shortid')
|
|||
var Sequelize = require('sequelize')
|
||||
var async = require('async')
|
||||
var moment = require('moment')
|
||||
var DiffMatchPatch = require('diff-match-patch')
|
||||
var DiffMatchPatch = require('@hackmd/diff-match-patch')
|
||||
var dmp = new DiffMatchPatch()
|
||||
var S = require('string')
|
||||
|
||||
const { stripTags } = require('../../utils/string')
|
||||
|
||||
// core
|
||||
var config = require('../config')
|
||||
|
@ -86,8 +87,53 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
}, {
|
||||
paranoid: false,
|
||||
classMethods: {
|
||||
associate: function (models) {
|
||||
hooks: {
|
||||
beforeCreate: function (note, options) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
// if no content specified then use default note
|
||||
if (!note.content) {
|
||||
var body = null
|
||||
let filePath = null
|
||||
if (!note.alias) {
|
||||
filePath = config.defaultNotePath
|
||||
} else {
|
||||
filePath = path.join(config.docsPath, note.alias + '.md')
|
||||
}
|
||||
if (Note.checkFileExist(filePath)) {
|
||||
var fsCreatedTime = moment(fs.statSync(filePath).ctime)
|
||||
body = fs.readFileSync(filePath, 'utf8')
|
||||
note.title = Note.parseNoteTitle(body)
|
||||
note.content = body
|
||||
if (filePath !== config.defaultNotePath) {
|
||||
note.createdAt = fsCreatedTime
|
||||
}
|
||||
}
|
||||
}
|
||||
// if no permission specified and have owner then give default permission in config, else default permission is freely
|
||||
if (!note.permission) {
|
||||
if (note.ownerId) {
|
||||
note.permission = config.defaultPermission
|
||||
} else {
|
||||
note.permission = 'freely'
|
||||
}
|
||||
}
|
||||
return resolve(note)
|
||||
})
|
||||
},
|
||||
afterCreate: function (note, options, callback) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
sequelize.models.Revision.saveNoteRevision(note, function (err, revision) {
|
||||
if (err) {
|
||||
return reject(err)
|
||||
}
|
||||
return resolve(note)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Note.associate = function (models) {
|
||||
Note.belongsTo(models.User, {
|
||||
foreignKey: 'ownerId',
|
||||
as: 'owner',
|
||||
|
@ -109,21 +155,21 @@ module.exports = function (sequelize, DataTypes) {
|
|||
as: 'authors',
|
||||
constraints: false
|
||||
})
|
||||
},
|
||||
checkFileExist: function (filePath) {
|
||||
}
|
||||
Note.checkFileExist = function (filePath) {
|
||||
try {
|
||||
return fs.statSync(filePath).isFile()
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
encodeNoteId: function (id) {
|
||||
}
|
||||
Note.encodeNoteId = function (id) {
|
||||
// remove dashes in UUID and encode in url-safe base64
|
||||
let str = id.replace(/-/g, '')
|
||||
let hexStr = Buffer.from(str, 'hex')
|
||||
return base64url.encode(hexStr)
|
||||
},
|
||||
decodeNoteId: function (encodedId) {
|
||||
}
|
||||
Note.decodeNoteId = function (encodedId) {
|
||||
// decode from url-safe base64
|
||||
let id = base64url.toBuffer(encodedId).toString('hex')
|
||||
// add dashes between the UUID string parts
|
||||
|
@ -134,13 +180,13 @@ module.exports = function (sequelize, DataTypes) {
|
|||
idParts.push(id.substr(16, 4))
|
||||
idParts.push(id.substr(20, 12))
|
||||
return idParts.join('-')
|
||||
},
|
||||
checkNoteIdValid: function (id) {
|
||||
}
|
||||
Note.checkNoteIdValid = function (id) {
|
||||
var uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||
var result = id.match(uuidRegex)
|
||||
if (result && result.length === 1) { return true } else { return false }
|
||||
},
|
||||
parseNoteId: function (noteId, callback) {
|
||||
}
|
||||
Note.parseNoteId = function (noteId, callback) {
|
||||
async.series({
|
||||
parseNoteIdByAlias: function (_callback) {
|
||||
// try to parse note id by alias (e.g. doc)
|
||||
|
@ -273,42 +319,42 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
return callback(null, null)
|
||||
})
|
||||
},
|
||||
parseNoteInfo: function (body) {
|
||||
}
|
||||
Note.parseNoteInfo = function (body) {
|
||||
var parsed = Note.extractMeta(body)
|
||||
var $ = cheerio.load(md.render(parsed.markdown))
|
||||
return {
|
||||
title: Note.extractNoteTitle(parsed.meta, $),
|
||||
tags: Note.extractNoteTags(parsed.meta, $)
|
||||
}
|
||||
},
|
||||
parseNoteTitle: function (body) {
|
||||
}
|
||||
Note.parseNoteTitle = function (body) {
|
||||
var parsed = Note.extractMeta(body)
|
||||
var $ = cheerio.load(md.render(parsed.markdown))
|
||||
return Note.extractNoteTitle(parsed.meta, $)
|
||||
},
|
||||
extractNoteTitle: function (meta, $) {
|
||||
}
|
||||
Note.extractNoteTitle = function (meta, $) {
|
||||
var title = ''
|
||||
if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) {
|
||||
title = meta.title
|
||||
} else {
|
||||
var h1s = $('h1')
|
||||
if (h1s.length > 0 && h1s.first().text().split('\n').length === 1) { title = S(h1s.first().text()).stripTags().s }
|
||||
if (h1s.length > 0 && h1s.first().text().split('\n').length === 1) { title = stripTags(h1s.first().text()) }
|
||||
}
|
||||
if (!title) title = 'Untitled'
|
||||
return title
|
||||
},
|
||||
generateDescription: function (markdown) {
|
||||
}
|
||||
Note.generateDescription = function (markdown) {
|
||||
return markdown.substr(0, 100).replace(/(?:\r\n|\r|\n)/g, ' ')
|
||||
},
|
||||
decodeTitle: function (title) {
|
||||
}
|
||||
Note.decodeTitle = function (title) {
|
||||
return title || 'Untitled'
|
||||
},
|
||||
generateWebTitle: function (title) {
|
||||
}
|
||||
Note.generateWebTitle = function (title) {
|
||||
title = !title || title === 'Untitled' ? 'CodiMD - Collaborative markdown notes' : title + ' - CodiMD'
|
||||
return title
|
||||
},
|
||||
extractNoteTags: function (meta, $) {
|
||||
}
|
||||
Note.extractNoteTags = function (meta, $) {
|
||||
var tags = []
|
||||
var rawtags = []
|
||||
if (meta.tags && (typeof meta.tags === 'string' || typeof meta.tags === 'number')) {
|
||||
|
@ -323,7 +369,7 @@ module.exports = function (sequelize, DataTypes) {
|
|||
if (/^tags/gmi.test($(value).text())) {
|
||||
var codes = $(value).find('code')
|
||||
for (let i = 0; i < codes.length; i++) {
|
||||
var text = S($(codes[i]).text().trim()).stripTags().s
|
||||
var text = stripTags($(codes[i]).text().trim())
|
||||
if (text) rawtags.push(text)
|
||||
}
|
||||
}
|
||||
|
@ -340,8 +386,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
if (!found) { tags.push(rawtags[i]) }
|
||||
}
|
||||
return tags
|
||||
},
|
||||
extractMeta: function (content) {
|
||||
}
|
||||
Note.extractMeta = function (content) {
|
||||
var obj = null
|
||||
try {
|
||||
obj = metaMarked(content)
|
||||
|
@ -354,8 +400,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
}
|
||||
return obj
|
||||
},
|
||||
parseMeta: function (meta) {
|
||||
}
|
||||
Note.parseMeta = function (meta) {
|
||||
var _meta = {}
|
||||
if (meta) {
|
||||
if (meta.title && (typeof meta.title === 'string' || typeof meta.title === 'number')) { _meta.title = meta.title }
|
||||
|
@ -366,8 +412,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
if (meta.slideOptions && (typeof meta.slideOptions === 'object')) { _meta.slideOptions = meta.slideOptions }
|
||||
}
|
||||
return _meta
|
||||
},
|
||||
updateAuthorshipByOperation: function (operation, userId, authorships) {
|
||||
}
|
||||
Note.updateAuthorshipByOperation = function (operation, userId, authorships) {
|
||||
var index = 0
|
||||
var timestamp = Date.now()
|
||||
for (let i = 0; i < operation.length; i++) {
|
||||
|
@ -467,8 +513,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
}
|
||||
return authorships
|
||||
},
|
||||
transformPatchToOperations: function (patch, contentLength) {
|
||||
}
|
||||
Note.transformPatchToOperations = function (patch, contentLength) {
|
||||
var operations = []
|
||||
if (patch.length > 0) {
|
||||
// calculate original content length
|
||||
|
@ -527,45 +573,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
return operations
|
||||
}
|
||||
},
|
||||
hooks: {
|
||||
beforeCreate: function (note, options, callback) {
|
||||
// if no content specified then use default note
|
||||
if (!note.content) {
|
||||
var body = null
|
||||
let filePath = null
|
||||
if (!note.alias) {
|
||||
filePath = config.defaultNotePath
|
||||
} else {
|
||||
filePath = path.join(config.docsPath, note.alias + '.md')
|
||||
}
|
||||
if (Note.checkFileExist(filePath)) {
|
||||
var fsCreatedTime = moment(fs.statSync(filePath).ctime)
|
||||
body = fs.readFileSync(filePath, 'utf8')
|
||||
note.title = Note.parseNoteTitle(body)
|
||||
note.content = body
|
||||
if (filePath !== config.defaultNotePath) {
|
||||
note.createdAt = fsCreatedTime
|
||||
}
|
||||
}
|
||||
}
|
||||
// if no permission specified and have owner then give default permission in config, else default permission is freely
|
||||
if (!note.permission) {
|
||||
if (note.ownerId) {
|
||||
note.permission = config.defaultPermission
|
||||
} else {
|
||||
note.permission = 'freely'
|
||||
}
|
||||
}
|
||||
return callback(null, note)
|
||||
},
|
||||
afterCreate: function (note, options, callback) {
|
||||
sequelize.models.Revision.saveNoteRevision(note, function (err, revision) {
|
||||
callback(err, note)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return Note
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ var childProcess = require('child_process')
|
|||
var shortId = require('shortid')
|
||||
var path = require('path')
|
||||
|
||||
var Op = Sequelize.Op
|
||||
|
||||
// core
|
||||
var config = require('../config')
|
||||
var logger = require('../logger')
|
||||
|
@ -97,9 +99,9 @@ module.exports = function (sequelize, DataTypes) {
|
|||
this.setDataValue('authorship', value ? JSON.stringify(value) : value)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
classMethods: {
|
||||
associate: function (models) {
|
||||
})
|
||||
|
||||
Revision.associate = function (models) {
|
||||
Revision.belongsTo(models.Note, {
|
||||
foreignKey: 'noteId',
|
||||
as: 'note',
|
||||
|
@ -107,8 +109,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
onDelete: 'CASCADE',
|
||||
hooks: true
|
||||
})
|
||||
},
|
||||
getNoteRevisions: function (note, callback) {
|
||||
}
|
||||
Revision.getNoteRevisions = function (note, callback) {
|
||||
Revision.findAll({
|
||||
where: {
|
||||
noteId: note.id
|
||||
|
@ -127,8 +129,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}).catch(function (err) {
|
||||
callback(err, null)
|
||||
})
|
||||
},
|
||||
getPatchedNoteRevisionByTime: function (note, time, callback) {
|
||||
}
|
||||
Revision.getPatchedNoteRevisionByTime = function (note, time, callback) {
|
||||
// find all revisions to prepare for all possible calculation
|
||||
Revision.findAll({
|
||||
where: {
|
||||
|
@ -142,7 +144,7 @@ module.exports = function (sequelize, DataTypes) {
|
|||
where: {
|
||||
noteId: note.id,
|
||||
createdAt: {
|
||||
$gte: time
|
||||
[Op.gte]: time
|
||||
}
|
||||
},
|
||||
order: [['createdAt', 'DESC']]
|
||||
|
@ -159,8 +161,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}).catch(function (err) {
|
||||
return callback(err, null)
|
||||
})
|
||||
},
|
||||
checkAllNotesRevision: function (callback) {
|
||||
}
|
||||
Revision.checkAllNotesRevision = function (callback) {
|
||||
Revision.saveAllNotesRevision(function (err, notes) {
|
||||
if (err) return callback(err, null)
|
||||
if (!notes || notes.length <= 0) {
|
||||
|
@ -169,28 +171,28 @@ module.exports = function (sequelize, DataTypes) {
|
|||
Revision.checkAllNotesRevision(callback)
|
||||
}
|
||||
})
|
||||
},
|
||||
saveAllNotesRevision: function (callback) {
|
||||
}
|
||||
Revision.saveAllNotesRevision = function (callback) {
|
||||
sequelize.models.Note.findAll({
|
||||
// query all notes that need to save for revision
|
||||
where: {
|
||||
$and: [
|
||||
[Op.and]: [
|
||||
{
|
||||
lastchangeAt: {
|
||||
$or: {
|
||||
$eq: null,
|
||||
$and: {
|
||||
$ne: null,
|
||||
$gt: sequelize.col('createdAt')
|
||||
[Op.or]: {
|
||||
[Op.eq]: null,
|
||||
[Op.and]: {
|
||||
[Op.ne]: null,
|
||||
[Op.gt]: sequelize.col('createdAt')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
savedAt: {
|
||||
$or: {
|
||||
$eq: null,
|
||||
$lt: sequelize.col('lastchangeAt')
|
||||
[Op.or]: {
|
||||
[Op.eq]: null,
|
||||
[Op.lt]: sequelize.col('lastchangeAt')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,8 +230,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}).catch(function (err) {
|
||||
return callback(err, null)
|
||||
})
|
||||
},
|
||||
saveNoteRevision: function (note, callback) {
|
||||
}
|
||||
Revision.saveNoteRevision = function (note, callback) {
|
||||
Revision.findAll({
|
||||
where: {
|
||||
noteId: note.id
|
||||
|
@ -293,8 +295,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}).catch(function (err) {
|
||||
return callback(err, null)
|
||||
})
|
||||
},
|
||||
finishSaveNoteRevision: function (note, revision, callback) {
|
||||
}
|
||||
Revision.finishSaveNoteRevision = function (note, revision, callback) {
|
||||
note.update({
|
||||
savedAt: revision.updatedAt
|
||||
}).then(function () {
|
||||
|
@ -303,8 +305,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||
return callback(err, null)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return Revision
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ var scrypt = require('scrypt')
|
|||
|
||||
// core
|
||||
var logger = require('../logger')
|
||||
var {generateAvatarURL} = require('../letter-avatars')
|
||||
var { generateAvatarURL } = require('../letter-avatars')
|
||||
|
||||
module.exports = function (sequelize, DataTypes) {
|
||||
var User = sequelize.define('User', {
|
||||
|
@ -47,18 +47,17 @@ module.exports = function (sequelize, DataTypes) {
|
|||
this.setDataValue('password', hash)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
instanceMethods: {
|
||||
verifyPassword: function (attempt) {
|
||||
})
|
||||
|
||||
User.prototype.verifyPassword = function (attempt) {
|
||||
if (scrypt.verifyKdfSync(Buffer.from(this.password, 'hex'), attempt)) {
|
||||
return this
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
classMethods: {
|
||||
associate: function (models) {
|
||||
|
||||
User.associate = function (models) {
|
||||
User.hasMany(models.Note, {
|
||||
foreignKey: 'ownerId',
|
||||
constraints: false
|
||||
|
@ -67,14 +66,14 @@ module.exports = function (sequelize, DataTypes) {
|
|||
foreignKey: 'lastchangeuserId',
|
||||
constraints: false
|
||||
})
|
||||
},
|
||||
getProfile: function (user) {
|
||||
}
|
||||
User.getProfile = function (user) {
|
||||
if (!user) {
|
||||
return null
|
||||
}
|
||||
return user.profile ? User.parseProfile(user.profile) : (user.email ? User.parseProfileByEmail(user.email) : null)
|
||||
},
|
||||
parseProfile: function (profile) {
|
||||
}
|
||||
User.parseProfile = function (profile) {
|
||||
try {
|
||||
profile = JSON.parse(profile)
|
||||
} catch (err) {
|
||||
|
@ -89,8 +88,8 @@ module.exports = function (sequelize, DataTypes) {
|
|||
}
|
||||
}
|
||||
return profile
|
||||
},
|
||||
parsePhotoByProfile: function (profile, bigger) {
|
||||
}
|
||||
User.parsePhotoByProfile = function (profile, bigger) {
|
||||
var photo = null
|
||||
switch (profile.provider) {
|
||||
case 'facebook':
|
||||
|
@ -142,16 +141,14 @@ module.exports = function (sequelize, DataTypes) {
|
|||
break
|
||||
}
|
||||
return photo
|
||||
},
|
||||
parseProfileByEmail: function (email) {
|
||||
}
|
||||
User.parseProfileByEmail = function (email) {
|
||||
return {
|
||||
name: email.substring(0, email.lastIndexOf('@')),
|
||||
photo: generateAvatarURL('', email, false),
|
||||
biggerphoto: generateAvatarURL('', email, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return User
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ var utils = require('./utils')
|
|||
// public
|
||||
var response = {
|
||||
errorForbidden: function (res) {
|
||||
const {req} = res
|
||||
const { req } = res
|
||||
if (req.user) {
|
||||
responseError(res, '403', 'Forbidden', 'oh no.')
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,7 @@ const Router = require('express').Router
|
|||
const passport = require('passport')
|
||||
const DropboxStrategy = require('passport-dropbox-oauth2').Strategy
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let dropboxAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@ const LocalStrategy = require('passport-local').Strategy
|
|||
const config = require('../../../config')
|
||||
const models = require('../../../models')
|
||||
const logger = require('../../../logger')
|
||||
const {setReturnToFromReferer} = require('../utils')
|
||||
const {urlencodedParser} = require('../../utils')
|
||||
const { setReturnToFromReferer } = require('../utils')
|
||||
const { urlencodedParser } = require('../../utils')
|
||||
const response = require('../../../response')
|
||||
|
||||
let emailAuth = module.exports = Router()
|
||||
|
|
|
@ -5,7 +5,7 @@ const passport = require('passport')
|
|||
const FacebookStrategy = require('passport-facebook').Strategy
|
||||
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let facebookAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ const passport = require('passport')
|
|||
const GithubStrategy = require('passport-github').Strategy
|
||||
const config = require('../../../config')
|
||||
const response = require('../../../response')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let githubAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ const passport = require('passport')
|
|||
const GitlabStrategy = require('passport-gitlab2').Strategy
|
||||
const config = require('../../../config')
|
||||
const response = require('../../../response')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let gitlabAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ const Router = require('express').Router
|
|||
const passport = require('passport')
|
||||
var GoogleStrategy = require('passport-google-oauth20').Strategy
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let googleAuth = module.exports = Router()
|
||||
|
||||
|
@ -12,14 +12,14 @@ passport.use(new GoogleStrategy({
|
|||
clientID: config.google.clientID,
|
||||
clientSecret: config.google.clientSecret,
|
||||
callbackURL: config.serverURL + '/auth/google/callback',
|
||||
userProfileURL: "https://www.googleapis.com/oauth2/v3/userinfo"
|
||||
userProfileURL: 'https://www.googleapis.com/oauth2/v3/userinfo'
|
||||
}, passportGeneralCallback))
|
||||
|
||||
googleAuth.get('/auth/google', function (req, res, next) {
|
||||
setReturnToFromReferer(req)
|
||||
passport.authenticate('google', { scope: ['profile'] })(req, res, next)
|
||||
})
|
||||
// google auth callback
|
||||
// google auth callback
|
||||
googleAuth.get('/auth/google/callback',
|
||||
passport.authenticate('google', {
|
||||
successReturnToOrRedirect: config.serverURL + '/',
|
||||
|
|
|
@ -6,8 +6,8 @@ const LDAPStrategy = require('passport-ldapauth')
|
|||
const config = require('../../../config')
|
||||
const models = require('../../../models')
|
||||
const logger = require('../../../logger')
|
||||
const {setReturnToFromReferer} = require('../utils')
|
||||
const {urlencodedParser} = require('../../utils')
|
||||
const { setReturnToFromReferer } = require('../utils')
|
||||
const { urlencodedParser } = require('../../utils')
|
||||
const response = require('../../../response')
|
||||
|
||||
let ldapAuth = module.exports = Router()
|
||||
|
|
|
@ -5,7 +5,7 @@ const passport = require('passport')
|
|||
const Mattermost = require('mattermost')
|
||||
const OAuthStrategy = require('passport-oauth2').Strategy
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
const mattermost = new Mattermost.Client()
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ const Router = require('express').Router
|
|||
const passport = require('passport')
|
||||
const { Strategy, InternalOAuthError } = require('passport-oauth2')
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let oauth2Auth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ const OpenIDStrategy = require('@passport-next/passport-openid').Strategy
|
|||
const config = require('../../../config')
|
||||
const models = require('../../../models')
|
||||
const logger = require('../../../logger')
|
||||
const {urlencodedParser} = require('../../utils')
|
||||
const {setReturnToFromReferer} = require('../utils')
|
||||
const { urlencodedParser } = require('../../utils')
|
||||
const { setReturnToFromReferer } = require('../utils')
|
||||
|
||||
let openIDAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ const SamlStrategy = require('passport-saml').Strategy
|
|||
const config = require('../../../config')
|
||||
const models = require('../../../models')
|
||||
const logger = require('../../../logger')
|
||||
const {urlencodedParser} = require('../../utils')
|
||||
const { urlencodedParser } = require('../../utils')
|
||||
const fs = require('fs')
|
||||
const intersection = function (array1, array2) { return array1.filter((n) => array2.includes(n)) }
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ const passport = require('passport')
|
|||
const TwitterStrategy = require('passport-twitter').Strategy
|
||||
|
||||
const config = require('../../../config')
|
||||
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
|
||||
const { setReturnToFromReferer, passportGeneralCallback } = require('../utils')
|
||||
|
||||
let twitterAuth = module.exports = Router()
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
const Router = require('express').Router
|
||||
|
||||
const {urlencodedParser} = require('./utils')
|
||||
const { urlencodedParser } = require('./utils')
|
||||
const history = require('../history')
|
||||
const historyRouter = module.exports = Router()
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
const config = require('../../config')
|
||||
const logger = require('../../logger')
|
||||
|
||||
const imgur = require('imgur')
|
||||
const imgur = require('@hackmd/imgur')
|
||||
|
||||
exports.uploadImage = function (imagePath, callback) {
|
||||
if (!imagePath || typeof imagePath !== 'string') {
|
||||
|
|
|
@ -3,7 +3,7 @@ const fs = require('fs')
|
|||
const path = require('path')
|
||||
|
||||
const config = require('../../config')
|
||||
const {getImageMimeType} = require('../../utils')
|
||||
const { getImageMimeType } = require('../../utils')
|
||||
const logger = require('../../logger')
|
||||
|
||||
const Minio = require('minio')
|
||||
|
|
|
@ -3,7 +3,7 @@ const fs = require('fs')
|
|||
const path = require('path')
|
||||
|
||||
const config = require('../../config')
|
||||
const {getImageMimeType} = require('../../utils')
|
||||
const { getImageMimeType } = require('../../utils')
|
||||
const logger = require('../../logger')
|
||||
|
||||
const AWS = require('aws-sdk')
|
||||
|
|
|
@ -4,7 +4,7 @@ const Router = require('express').Router
|
|||
|
||||
const response = require('../response')
|
||||
|
||||
const {markdownParser} = require('./utils')
|
||||
const { markdownParser } = require('./utils')
|
||||
|
||||
const noteRouter = module.exports = Router()
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ const config = require('../config')
|
|||
const models = require('../models')
|
||||
const logger = require('../logger')
|
||||
|
||||
const {urlencodedParser} = require('./utils')
|
||||
const { urlencodedParser } = require('./utils')
|
||||
|
||||
const statusRouter = module.exports = Router()
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ const response = require('../response')
|
|||
const config = require('../config')
|
||||
const models = require('../models')
|
||||
const logger = require('../logger')
|
||||
const {generateAvatar} = require('../letter-avatars')
|
||||
const { generateAvatar } = require('../letter-avatars')
|
||||
|
||||
const UserRouter = module.exports = Router()
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
// external modules
|
||||
var DiffMatchPatch = require('diff-match-patch')
|
||||
var DiffMatchPatch = require('@hackmd/diff-match-patch')
|
||||
var dmp = new DiffMatchPatch()
|
||||
|
||||
// core
|
||||
|
|
27
package.json
27
package.json
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "CodiMD",
|
||||
"name": "codimd",
|
||||
"version": "1.3.1",
|
||||
"description": "Realtime collaborative markdown notes on all platforms.",
|
||||
"main": "app.js",
|
||||
|
@ -16,9 +16,13 @@
|
|||
"doctoc": "doctoc --title='# Table of Contents' README.md"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hackmd/codemirror": "^5.41.2",
|
||||
"@hackmd/diff-match-patch": "^1.1.1",
|
||||
"@hackmd/idle-js": "^1.0.1",
|
||||
"@hackmd/imgur": "^0.4.1",
|
||||
"@hackmd/js-sequence-diagrams": "^0.0.1-alpha.2",
|
||||
"@hackmd/lz-string": "1.4.4",
|
||||
"@passport-next/passport-openid": "^1.0.0",
|
||||
"Idle.Js": "git+https://github.com/shawnmclean/Idle.js",
|
||||
"archiver": "^2.1.1",
|
||||
"async": "^2.1.4",
|
||||
"aws-sdk": "^2.345.0",
|
||||
|
@ -29,14 +33,12 @@
|
|||
"bootstrap-validator": "^0.11.8",
|
||||
"chance": "^1.0.4",
|
||||
"cheerio": "^0.22.0",
|
||||
"codemirror": "git+https://github.com/hackmdio/CodeMirror.git",
|
||||
"compression": "^1.6.2",
|
||||
"connect-flash": "^0.1.1",
|
||||
"connect-session-sequelize": "^4.1.0",
|
||||
"connect-session-sequelize": "^6.0.0",
|
||||
"cookie": "0.3.1",
|
||||
"cookie-parser": "1.4.3",
|
||||
"deep-freeze": "^0.0.1",
|
||||
"diff-match-patch": "git+https://github.com/hackmdio/diff-match-patch.git",
|
||||
"ejs": "^2.5.5",
|
||||
"emojify.js": "~1.1.0",
|
||||
"express": ">=4.14",
|
||||
|
@ -51,19 +53,16 @@
|
|||
"helmet": "^3.13.0",
|
||||
"highlight.js": "~9.12.0",
|
||||
"i18n": "^0.8.3",
|
||||
"imgur": "git+https://github.com/hackmdio/node-imgur.git",
|
||||
"ionicons": "~2.0.1",
|
||||
"jquery": "^3.1.1",
|
||||
"jquery-mousewheel": "^3.1.13",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"js-cookie": "^2.1.3",
|
||||
"js-url": "^2.3.0",
|
||||
"js-yaml": "^3.7.0",
|
||||
"jsdom-nogyp": "^0.8.3",
|
||||
"keymaster": "^1.6.2",
|
||||
"list.js": "^1.5.0",
|
||||
"lodash": "^4.17.11",
|
||||
"lz-string": "git+https://github.com/hackmdio/lz-string.git",
|
||||
"markdown-it": "^8.2.2",
|
||||
"markdown-it-abbr": "^1.0.4",
|
||||
"markdown-it-container": "^2.0.0",
|
||||
|
@ -105,21 +104,19 @@
|
|||
"pg-hstore": "^2.3.2",
|
||||
"prismjs": "^1.6.0",
|
||||
"randomcolor": "^0.5.3",
|
||||
"raphael": "git+https://github.com/dmitrybaranovskiy/raphael",
|
||||
"raphael": "^2.2.8",
|
||||
"readline-sync": "^1.4.7",
|
||||
"request": "^2.88.0",
|
||||
"reveal.js": "~3.7.0",
|
||||
"scrypt": "^6.0.3",
|
||||
"select2": "^3.5.2-browserify",
|
||||
"sequelize": "^3.28.0",
|
||||
"sequelize-cli": "^2.5.1",
|
||||
"sequelize": "5.3.2",
|
||||
"shortid": "2.2.8",
|
||||
"socket.io": "~2.1.1",
|
||||
"socket.io-client": "~2.1.1",
|
||||
"spin.js": "^2.3.2",
|
||||
"sqlite3": "^4.0.1",
|
||||
"store": "^2.0.12",
|
||||
"string": "^3.3.3",
|
||||
"tedious": "^1.14.0",
|
||||
"toobusy-js": "^0.5.1",
|
||||
"turndown": "^5.0.1",
|
||||
|
@ -130,6 +127,7 @@
|
|||
"viz.js": "^1.7.0",
|
||||
"winston": "^3.1.0",
|
||||
"ws": "^6.0.0",
|
||||
"wurl": "^2.5.3",
|
||||
"xss": "^1.0.3"
|
||||
},
|
||||
"resolutions": {
|
||||
|
@ -138,7 +136,7 @@
|
|||
"**/request": "^2.88.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.x"
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"bugs": "https://github.com/hackmdio/codimd/issues",
|
||||
"keywords": [
|
||||
|
@ -185,13 +183,14 @@
|
|||
"html-webpack-plugin": "4.0.0-beta.2",
|
||||
"imports-loader": "^0.8.0",
|
||||
"jsonlint": "^1.6.2",
|
||||
"less": "^2.7.1",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^4.1.0",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"mocha": "^5.2.0",
|
||||
"mock-require": "^3.0.3",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.0",
|
||||
"script-loader": "^0.7.2",
|
||||
"sequelize-cli": "^5.4.0",
|
||||
"string-loader": "^0.0.1",
|
||||
"style-loader": "^0.21.0",
|
||||
"uglifyjs-webpack-plugin": "^1.2.7",
|
||||
|
|
|
@ -12,7 +12,6 @@ module.exports = {
|
|||
"ui": false,
|
||||
"Spinner": false,
|
||||
"modeType": false,
|
||||
"Idle": false,
|
||||
"serverurl": false,
|
||||
"key": false,
|
||||
"gapi": false,
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
/* eslint-env browser, jquery */
|
||||
/* global moment, serverurl */
|
||||
|
||||
require('./locale')
|
||||
|
||||
require('../css/cover.css')
|
||||
require('../css/site.css')
|
||||
|
||||
import {
|
||||
checkIfAuth,
|
||||
clearLoginState,
|
||||
|
@ -30,7 +25,12 @@ import {
|
|||
|
||||
import { saveAs } from 'file-saver'
|
||||
import List from 'list.js'
|
||||
import S from 'string'
|
||||
import unescapeHTML from 'lodash/unescape'
|
||||
|
||||
require('./locale')
|
||||
|
||||
require('../css/cover.css')
|
||||
require('../css/site.css')
|
||||
|
||||
const options = {
|
||||
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
|
||||
|
@ -397,7 +397,7 @@ function buildTagsFilter (tags) {
|
|||
for (let i = 0; i < tags.length; i++) {
|
||||
tags[i] = {
|
||||
id: i,
|
||||
text: S(tags[i]).unescapeHTML().s
|
||||
text: unescapeHTML(tags[i])
|
||||
}
|
||||
}
|
||||
filtertags = tags
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
/* eslint-env browser, jquery */
|
||||
/* global moment, serverurl */
|
||||
|
||||
import Prism from 'prismjs'
|
||||
import hljs from 'highlight.js'
|
||||
import PDFObject from 'pdfobject'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
import escapeHTML from 'lodash/escape'
|
||||
import unescapeHTML from 'lodash/unescape'
|
||||
|
||||
import { stripTags } from '../../utils/string'
|
||||
|
||||
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/components/prism-wiki')
|
||||
require('prismjs/components/prism-haskell')
|
||||
|
@ -10,17 +28,9 @@ require('prismjs/components/prism-jsx')
|
|||
require('prismjs/components/prism-makefile')
|
||||
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'
|
||||
|
||||
require('./lib/common/login')
|
||||
require('../vendor/md-toc')
|
||||
var Viz = require('viz.js')
|
||||
|
||||
import getUIElements from './lib/editor/ui-elements'
|
||||
const ui = getUIElements()
|
||||
|
||||
// auto update last change
|
||||
|
@ -157,7 +167,7 @@ export function renderTags (view) {
|
|||
|
||||
function slugifyWithUTF8 (text) {
|
||||
// remove html tags and trim spaces
|
||||
let newText = S(text).trim().stripTags().s
|
||||
let newText = stripTags(text.toString().trim())
|
||||
// replace all spaces in between to dashes
|
||||
newText = newText.replace(/\s+/g, '-')
|
||||
// slugify string to make it valid for attribute
|
||||
|
@ -259,9 +269,9 @@ export function finishView (view) {
|
|||
li.innerHTML = html
|
||||
let disabled = 'disabled'
|
||||
if (typeof editor !== 'undefined' && window.havePermission()) { disabled = '' }
|
||||
if (/^\s*\[[x ]\]\s*/.test(html)) {
|
||||
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>`)
|
||||
if (/^\s*\[[x ]]\s*/.test(html)) {
|
||||
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>`)
|
||||
if (li.tagName.toLowerCase() !== 'li') {
|
||||
li.parentElement.setAttribute('class', 'task-list-item')
|
||||
} else {
|
||||
|
@ -492,22 +502,22 @@ export function finishView (view) {
|
|||
value: code
|
||||
}
|
||||
} else if (reallang === 'haskell' || reallang === 'go' || reallang === 'typescript' || reallang === 'jsx' || reallang === 'gherkin') {
|
||||
code = S(code).unescapeHTML().s
|
||||
code = unescapeHTML(code)
|
||||
result = {
|
||||
value: Prism.highlight(code, Prism.languages[reallang])
|
||||
}
|
||||
} else if (reallang === 'tiddlywiki' || reallang === 'mediawiki') {
|
||||
code = S(code).unescapeHTML().s
|
||||
code = unescapeHTML(code)
|
||||
result = {
|
||||
value: Prism.highlight(code, Prism.languages.wiki)
|
||||
}
|
||||
} else if (reallang === 'cmake') {
|
||||
code = S(code).unescapeHTML().s
|
||||
code = unescapeHTML(code)
|
||||
result = {
|
||||
value: Prism.highlight(code, Prism.languages.makefile)
|
||||
}
|
||||
} else {
|
||||
code = S(code).unescapeHTML().s
|
||||
code = unescapeHTML(code)
|
||||
const languages = hljs.listLanguages()
|
||||
if (!languages.includes(reallang)) {
|
||||
result = hljs.highlightAuto(code)
|
||||
|
@ -902,7 +912,7 @@ export function scrollToHash () {
|
|||
|
||||
function highlightRender (code, lang) {
|
||||
if (!lang || /no(-?)highlight|plain|text/.test(lang)) { return }
|
||||
code = S(code).escapeHTML().s
|
||||
code = escapeHTML(code)
|
||||
if (lang === 'sequence') {
|
||||
return `<div class="sequence-diagram raw">${code}</div>`
|
||||
} else if (lang === 'flow') {
|
||||
|
@ -934,9 +944,6 @@ function highlightRender (code, lang) {
|
|||
return result.value
|
||||
}
|
||||
|
||||
import markdownit from 'markdown-it'
|
||||
import markdownitContainer from 'markdown-it-container'
|
||||
|
||||
export let md = markdownit('default', {
|
||||
html: true,
|
||||
breaks: true,
|
||||
|
@ -1034,9 +1041,6 @@ md.renderer.rules.fence = (tokens, idx, options, env, self) => {
|
|||
return `<pre><code${self.renderAttrs(token)}>${highlighted}</code></pre>\n`
|
||||
}
|
||||
|
||||
/* Defined regex markdown it plugins */
|
||||
import Plugin from 'markdown-it-regexp'
|
||||
|
||||
// youtube
|
||||
const youtubePlugin = new Plugin(
|
||||
// regexp to match
|
||||
|
|
|
@ -2,30 +2,29 @@
|
|||
/* global serverurl, moment */
|
||||
|
||||
import store from 'store'
|
||||
import S from 'string'
|
||||
import LZString from 'lz-string'
|
||||
import LZString from '@hackmd/lz-string'
|
||||
|
||||
import escapeHTML from 'lodash/escape'
|
||||
|
||||
import wurl from 'wurl'
|
||||
|
||||
import {
|
||||
checkNoteIdValid,
|
||||
encodeNoteId
|
||||
} from './utils'
|
||||
|
||||
import {
|
||||
checkIfAuth
|
||||
} from './lib/common/login'
|
||||
import { checkIfAuth } from './lib/common/login'
|
||||
|
||||
import {
|
||||
urlpath
|
||||
} from './lib/config'
|
||||
import { urlpath } from './lib/config'
|
||||
|
||||
window.migrateHistoryFromTempCallback = null
|
||||
|
||||
migrateHistoryFromTemp()
|
||||
|
||||
function migrateHistoryFromTemp () {
|
||||
if (window.url('#tempid')) {
|
||||
if (wurl('#tempid')) {
|
||||
$.get(`${serverurl}/temp`, {
|
||||
tempid: window.url('#tempid')
|
||||
tempid: wurl('#tempid')
|
||||
})
|
||||
.done(data => {
|
||||
if (data && data.temp) {
|
||||
|
@ -274,8 +273,8 @@ function parseToHistory (list, notehistory, callback) {
|
|||
notehistory[i].fromNow = timestamp.fromNow()
|
||||
notehistory[i].time = timestamp.format('llll')
|
||||
// prevent XSS
|
||||
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].text = escapeHTML(notehistory[i].text)
|
||||
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? escapeHTML(notehistory[i].tags).split(',') : []
|
||||
// add to list
|
||||
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
|
||||
}
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
/* eslint-env browser, jquery */
|
||||
/* global CodeMirror, Cookies, moment, Spinner, Idle, serverurl,
|
||||
/* global CodeMirror, Cookies, moment, Spinner, serverurl,
|
||||
key, Dropbox, ot, hex2rgb, Visibility */
|
||||
|
||||
require('../vendor/showup/showup')
|
||||
|
||||
require('../css/index.css')
|
||||
require('../css/extra.css')
|
||||
require('../css/slide-preview.css')
|
||||
require('../css/site.css')
|
||||
|
||||
require('highlight.js/styles/github-gist.css')
|
||||
|
||||
import TurndownService from 'turndown'
|
||||
|
||||
import { saveAs } from 'file-saver'
|
||||
|
@ -20,8 +11,12 @@ import hljs from 'highlight.js'
|
|||
|
||||
import _ from 'lodash'
|
||||
|
||||
import wurl from 'wurl'
|
||||
|
||||
import List from 'list.js'
|
||||
|
||||
import Idle from '@hackmd/idle-js'
|
||||
|
||||
import {
|
||||
checkLoginStateChanged,
|
||||
setloginStateChangeEvent
|
||||
|
@ -82,6 +77,15 @@ import getUIElements from './lib/editor/ui-elements'
|
|||
import modeType from './lib/modeType'
|
||||
import appState from './lib/appState'
|
||||
|
||||
require('../vendor/showup/showup')
|
||||
|
||||
require('../css/index.css')
|
||||
require('../css/extra.css')
|
||||
require('../css/slide-preview.css')
|
||||
require('../css/site.css')
|
||||
|
||||
require('highlight.js/styles/github-gist.css')
|
||||
|
||||
var defaultTextHeight = 20
|
||||
var viewportMargin = 20
|
||||
var defaultEditorMode = 'gfm'
|
||||
|
@ -1388,12 +1392,12 @@ $('#gistImportModalConfirm').click(function () {
|
|||
if (!isValidURL(gisturl)) {
|
||||
showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid URL :(', '', '', false)
|
||||
} else {
|
||||
var hostname = window.url('hostname', gisturl)
|
||||
var hostname = wurl('hostname', gisturl)
|
||||
if (hostname !== 'gist.github.com') {
|
||||
showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', '', false)
|
||||
} else {
|
||||
ui.spinner.show()
|
||||
$.get('https://api.github.com/gists/' + window.url('-1', gisturl))
|
||||
$.get('https://api.github.com/gists/' + wurl('-1', gisturl))
|
||||
.done(function (data) {
|
||||
if (data.files) {
|
||||
var contents = ''
|
||||
|
|
|
@ -51,7 +51,7 @@ export function insertText (cm, text, cursorEnd = 0) {
|
|||
let cursor = cm.getCursor()
|
||||
cm.replaceSelection(text, cursor, cursor)
|
||||
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) {
|
||||
|
@ -80,7 +80,7 @@ export function insertLink (cm, isImage) {
|
|||
cm.setSelections(ranges)
|
||||
} else {
|
||||
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()
|
||||
|
@ -88,8 +88,8 @@ export function insertLink (cm, isImage) {
|
|||
|
||||
export function insertHeader (cm) {
|
||||
let cursor = cm.getCursor()
|
||||
let startOfLine = {line: cursor.line, ch: 0}
|
||||
let startOfLineText = cm.getRange(startOfLine, {line: cursor.line, ch: 1})
|
||||
let startOfLine = { line: cursor.line, ch: 0 }
|
||||
let startOfLineText = cm.getRange(startOfLine, { line: cursor.line, ch: 1 })
|
||||
// See if it is already a header
|
||||
if (startOfLineText === '#') {
|
||||
cm.replaceRange('#', startOfLine, startOfLine)
|
||||
|
@ -108,14 +108,14 @@ export function insertOnStartOfLines (cm, symbol) {
|
|||
if (!range.empty()) {
|
||||
const from = range.from()
|
||||
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 = symbol + selection
|
||||
cm.replaceRange(selection, from, to)
|
||||
} 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()
|
||||
}
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
/* eslint-env browser, jquery */
|
||||
/* global refreshView */
|
||||
|
||||
require('../css/extra.css')
|
||||
require('../css/slide-preview.css')
|
||||
require('../css/site.css')
|
||||
|
||||
require('highlight.js/styles/github-gist.css')
|
||||
|
||||
import {
|
||||
autoLinkify,
|
||||
deduplicatedHeaderId,
|
||||
|
@ -24,6 +18,12 @@ import {
|
|||
|
||||
import { preventXSS } from './render'
|
||||
|
||||
require('../css/extra.css')
|
||||
require('../css/slide-preview.css')
|
||||
require('../css/site.css')
|
||||
|
||||
require('highlight.js/styles/github-gist.css')
|
||||
|
||||
const markdown = $('#doc.markdown-body')
|
||||
const text = markdown.text()
|
||||
const lastMeta = md.meta
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/* eslint-env browser, jquery */
|
||||
/* global serverurl, Reveal, RevealMarkdown */
|
||||
|
||||
require('../css/extra.css')
|
||||
require('../css/site.css')
|
||||
|
||||
import { preventXSS } from './render'
|
||||
import { md, updateLastChange, removeDOMEvents, finishView } from './extra'
|
||||
|
||||
require('../css/extra.css')
|
||||
require('../css/site.css')
|
||||
|
||||
const body = preventXSS($('.slides').text())
|
||||
|
||||
window.createtime = window.lastchangeui.time.attr('data-createtime')
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
function stripTags (s) {
|
||||
return s.replace(RegExp(`</?[^<>]*>`, 'gi'), '')
|
||||
}
|
||||
|
||||
exports.stripTags = stripTags
|
|
@ -195,15 +195,11 @@ module.exports = {
|
|||
'bootstrap-validator',
|
||||
'expose-loader?select2!select2',
|
||||
'expose-loader?moment!moment',
|
||||
'script-loader!js-url',
|
||||
path.join(__dirname, 'public/js/cover.js')
|
||||
],
|
||||
index: [
|
||||
'babel-polyfill',
|
||||
'script-loader!jquery-ui-resizable',
|
||||
'script-loader!js-url',
|
||||
'script-loader!Idle.Js',
|
||||
'expose-loader?LZString!lz-string',
|
||||
'script-loader!codemirror',
|
||||
'script-loader!inlineAttachment',
|
||||
'script-loader!jqueryTextcomplete',
|
||||
|
@ -218,16 +214,16 @@ module.exports = {
|
|||
'index-styles': [
|
||||
path.join(__dirname, 'public/vendor/jquery-ui/jquery-ui.min.css'),
|
||||
path.join(__dirname, 'public/vendor/codemirror-spell-checker/spell-checker.min.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/lib/codemirror.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/addon/fold/foldgutter.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/addon/display/fullscreen.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/addon/dialog/dialog.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/addon/scroll/simplescrollbars.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/addon/search/matchesonscrollbar.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/theme/monokai.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/theme/one-dark.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/mode/tiddlywiki/tiddlywiki.css'),
|
||||
path.join(__dirname, 'node_modules/codemirror/mode/mediawiki/mediawiki.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/lib/codemirror.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/fold/foldgutter.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/display/fullscreen.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/dialog/dialog.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/scroll/simplescrollbars.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/search/matchesonscrollbar.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/monokai.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/one-dark.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/tiddlywiki/tiddlywiki.css'),
|
||||
path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/mediawiki/mediawiki.css'),
|
||||
path.join(__dirname, 'public/css/github-extract.css'),
|
||||
path.join(__dirname, 'public/vendor/showup/showup.css'),
|
||||
path.join(__dirname, 'public/css/mermaid.css'),
|
||||
|
@ -248,13 +244,10 @@ module.exports = {
|
|||
'expose-loader?jsyaml!js-yaml',
|
||||
'script-loader!mermaid',
|
||||
'expose-loader?moment!moment',
|
||||
'script-loader!js-url',
|
||||
'script-loader!handlebars',
|
||||
'expose-loader?hljs!highlight.js',
|
||||
'expose-loader?emojify!emojify.js',
|
||||
'script-loader!Idle.Js',
|
||||
'script-loader!gist-embed',
|
||||
'expose-loader?LZString!lz-string',
|
||||
'script-loader!codemirror',
|
||||
'script-loader!inlineAttachment',
|
||||
'script-loader!jqueryTextcomplete',
|
||||
|
@ -355,7 +348,7 @@ module.exports = {
|
|||
modules: ['node_modules'],
|
||||
extensions: ['.js'],
|
||||
alias: {
|
||||
codemirror: path.join(__dirname, 'node_modules/codemirror/codemirror.min.js'),
|
||||
codemirror: path.join(__dirname, 'node_modules/@hackmd/codemirror/codemirror.min.js'),
|
||||
inlineAttachment: path.join(__dirname, 'public/vendor/inlineAttachment/inline-attachment.js'),
|
||||
jqueryTextcomplete: path.join(__dirname, 'public/vendor/jquery-textcomplete/jquery.textcomplete.js'),
|
||||
codemirrorSpellChecker: path.join(__dirname, 'public/vendor/codemirror-spell-checker/spell-checker.min.js'),
|
||||
|
|
Loading…
Reference in New Issue