diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40f73553..83baa118 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,3 +71,5 @@ If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit -s`. You can also use git [aliases](https://git-scm.com/book/tr/v2/Git-Basics-Git-Aliases) like `git config --global alias.ci 'commit -s'`. Now you can commit with `git ci` and the commit will be signed. + +[dcofile]: https://github.com/hackmdio/codimd/blob/develop/contribute/developer-certificate-of-origin diff --git a/README.md b/README.md index 5c352740..7570435a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ CodiMD [![build status][travis-image]][travis-url] [![version][github-version-badge]][github-release-page] [![Gitter][gitter-image]][gitter-url] +[![Matrix][matrix-image]][matrix-url] [![POEditor][poeditor-image]][poeditor-url] CodiMD lets you collaborate in real-time with markdown. @@ -90,7 +91,7 @@ To stay up to date with your installation it's recommended to subscribe the [rel **License under AGPL.** -[gitter-image]: https://img.shields.io/badge/gitter-hackmdio/codimd-blue.svg +[gitter-image]: https://img.shields.io/badge/gitter-hackmdio/codimd-blue.svg [gitter-url]: https://gitter.im/hackmdio/hackmd [travis-image]: https://travis-ci.com/hackmdio/codimd.svg?branch=master [travis-url]: https://travis-ci.com/hackmdio/codimd @@ -99,3 +100,5 @@ To stay up to date with your installation it's recommended to subscribe the [rel [github-release-feed]: https://github.com/hackmdio/codimd/releases.atom [poeditor-image]: https://img.shields.io/badge/POEditor-translate-blue.svg [poeditor-url]: https://poeditor.com/join/project/q0nuPWyztp +[matrix-image]: https://img.shields.io/matrix/hackmdio_hackmd:gitter.im?color=blue&logo=matrix +[matrix-url]: https://matrix.to/#/#hackmdio_hackmd:gitter.im diff --git a/app.js b/app.js index 4980d45d..700f3137 100644 --- a/app.js +++ b/app.js @@ -194,6 +194,7 @@ app.set('view engine', 'ejs') app.locals.useCDN = config.useCDN app.locals.serverURL = config.serverURL app.locals.sourceURL = config.sourceURL +app.locals.privacyPolicyURL = config.privacyPolicyURL app.locals.allowAnonymous = config.allowAnonymous app.locals.allowAnonymousEdits = config.allowAnonymousEdits app.locals.permission = config.permission diff --git a/app.json b/app.json index 3e8fe4a7..7c43a3da 100644 --- a/app.json +++ b/app.json @@ -143,6 +143,10 @@ "CMD_ALLOW_PDF_EXPORT": { "description": "Enable or disable PDF exports", "required": false + }, + "PGSSLMODE": { + "description": "Enforce PG SSL mode", + "value": "require" } }, "addons": [ diff --git a/lib/auth/utils.js b/lib/auth/utils.js index fe6295d2..636989dc 100644 --- a/lib/auth/utils.js +++ b/lib/auth/utils.js @@ -5,9 +5,22 @@ const config = require('../config') const logger = require('../logger') exports.setReturnToFromReferer = function setReturnToFromReferer (req) { - var referer = req.get('referer') if (!req.session) req.session = {} - req.session.returnTo = referer + + var referer = req.get('referer') + var refererSearchParams = new URLSearchParams(new URL(referer).search) + var nextURL = refererSearchParams.get('next') + + if (nextURL) { + var isRelativeNextURL = nextURL.indexOf('://') === -1 && !nextURL.startsWith('//') + if (isRelativeNextURL) { + req.session.returnTo = (new URL(nextURL, config.serverURL)).toString() + } else { + req.session.returnTo = config.serverURL + } + } else { + req.session.returnTo = referer + } } exports.passportGeneralCallback = function callback (accessToken, refreshToken, profile, done) { diff --git a/lib/config/default.js b/lib/config/default.js index 95ee1940..488363b6 100644 --- a/lib/config/default.js +++ b/lib/config/default.js @@ -37,6 +37,7 @@ module.exports = { defaultPermission: 'editable', dbURL: '', db: {}, + privacyPolicyURL: '', // ssl path sslKeyPath: '', sslCertPath: '', @@ -188,5 +189,6 @@ module.exports = { // 2nd appearance: "31-good-morning-my-friend---do-you-have-5-1" // 3rd appearance: "31-good-morning-my-friend---do-you-have-5-2" linkifyHeaderStyle: 'keep-case', - autoVersionCheck: true + autoVersionCheck: true, + defaultTocDepth: 3 } diff --git a/lib/config/environment.js b/lib/config/environment.js index 0867aecf..b0124a0d 100644 --- a/lib/config/environment.js +++ b/lib/config/environment.js @@ -35,6 +35,7 @@ module.exports = { sessionSecret: process.env.CMD_SESSION_SECRET, sessionLife: toIntegerConfig(process.env.CMD_SESSION_LIFE), responseMaxLag: toIntegerConfig(process.env.CMD_RESPONSE_MAX_LAG), + privacyPolicyURL: process.env.CMD_PRIVACY_POLICY_URL, imageUploadType: process.env.CMD_IMAGE_UPLOAD_TYPE, imgur: { clientID: process.env.CMD_IMGUR_CLIENTID @@ -147,5 +148,6 @@ module.exports = { openID: toBooleanConfig(process.env.CMD_OPENID), defaultUseHardbreak: toBooleanConfig(process.env.CMD_DEFAULT_USE_HARD_BREAK), linkifyHeaderStyle: process.env.CMD_LINKIFY_HEADER_STYLE, - autoVersionCheck: toBooleanConfig(process.env.CMD_AUTO_VERSION_CHECK) + autoVersionCheck: toBooleanConfig(process.env.CMD_AUTO_VERSION_CHECK), + defaultTocDepth: toIntegerConfig(process.env.CMD_DEFAULT_TOC_DEPTH) } diff --git a/lib/models/note.js b/lib/models/note.js index d7109d44..9e0fb6c5 100644 --- a/lib/models/note.js +++ b/lib/models/note.js @@ -92,20 +92,22 @@ module.exports = function (sequelize, DataTypes) { return new Promise(function (resolve, reject) { // if no content specified then use default note if (!note.content) { - var body = null - let filePath = null - if (!note.alias) { - filePath = config.defaultNotePath - } else { - filePath = path.join(config.docsPath, note.alias + '.md') + let filePath = config.defaultNotePath + + if (note.alias) { + const notePathInDocPath = path.join(config.docsPath, path.basename(note.alias) + '.md') + if (Note.checkFileExist(notePathInDocPath)) { + filePath = notePathInDocPath + } } + if (Note.checkFileExist(filePath)) { - var fsCreatedTime = moment(fs.statSync(filePath).ctime) - body = fs.readFileSync(filePath, 'utf8') - note.title = Note.parseNoteTitle(body) - note.content = body + const noteInFS = readFileSystemNote(filePath) + note.title = noteInFS.title + note.content = noteInFS.content if (filePath !== config.defaultNotePath) { - note.createdAt = fsCreatedTime + note.createdAt = noteInFS.lastchangeAt + note.lastchangeAt = noteInFS.lastchangeAt } } } @@ -196,6 +198,29 @@ module.exports = function (sequelize, DataTypes) { }) }) } + + async function syncNote (noteInFS, note) { + const contentLength = noteInFS.content.length + + let note2 = await note.update({ + title: noteInFS.title, + content: noteInFS.content, + lastchangeAt: noteInFS.lastchangeAt + }) + const revision = await sequelize.models.Revision.saveNoteRevisionAsync(note2) + // update authorship on after making revision of docs + const patch = dmp.patch_fromText(revision.patch) + const operations = Note.transformPatchToOperations(patch, contentLength) + let authorship = note2.authorship + for (let i = 0; i < operations.length; i++) { + authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship) + } + note2 = await note.update({ + authorship: authorship + }) + return note2.id + } + Note.parseNoteId = function (noteId, callback) { async.series({ parseNoteIdByAlias: function (_callback) { @@ -204,65 +229,35 @@ module.exports = function (sequelize, DataTypes) { where: { alias: noteId } - }).then(function (note) { - if (note) { - const filePath = path.join(config.docsPath, noteId + '.md') - if (Note.checkFileExist(filePath)) { - // if doc in filesystem have newer modified time than last change time - // then will update the doc in db - var fsModifiedTime = moment(fs.statSync(filePath).mtime) - var dbModifiedTime = moment(note.lastchangeAt || note.createdAt) - var body = fs.readFileSync(filePath, 'utf8') - var contentLength = body.length - var title = Note.parseNoteTitle(body) - if (fsModifiedTime.isAfter(dbModifiedTime) && note.content !== body) { - note.update({ - title: title, - content: body, - lastchangeAt: fsModifiedTime - }).then(function (note) { - sequelize.models.Revision.saveNoteRevision(note, function (err, revision) { - if (err) return _callback(err, null) - // update authorship on after making revision of docs - var patch = dmp.patch_fromText(revision.patch) - var operations = Note.transformPatchToOperations(patch, contentLength) - var authorship = note.authorship - for (let i = 0; i < operations.length; i++) { - authorship = Note.updateAuthorshipByOperation(operations[i], null, authorship) - } - note.update({ - authorship: authorship - }).then(function (note) { - return callback(null, note.id) - }).catch(function (err) { - return _callback(err, null) - }) - }) - }).catch(function (err) { - return _callback(err, null) - }) + }).then(async function (note) { + const filePath = path.join(config.docsPath, path.basename(noteId) + '.md') + if (Note.checkFileExist(filePath)) { + try { + if (note) { + // if doc in filesystem have newer modified time than last change time + // then will update the doc in db + const noteInFS = readFileSystemNote(filePath) + if (shouldSyncNote(note, noteInFS)) { + const noteId = await syncNote(noteInFS, note) + return callback(null, noteId) + } } else { + // create new note with alias, and will sync md file in beforeCreateHook + const note = await Note.create({ + alias: noteId, + owner: null, + permission: 'locked' + }) return callback(null, note.id) } - } else { - return callback(null, note.id) - } - } else { - var filePath = path.join(config.docsPath, noteId + '.md') - if (Note.checkFileExist(filePath)) { - Note.create({ - alias: noteId, - owner: null, - permission: 'locked' - }).then(function (note) { - return callback(null, note.id) - }).catch(function (err) { - return _callback(err, null) - }) - } else { - return _callback(null, null) + } catch (err) { + return _callback(err, null) } } + if (!note) { + return _callback(null, null) + } + return callback(null, note.id) }).catch(function (err) { return _callback(err, null) }) @@ -589,5 +584,21 @@ module.exports = function (sequelize, DataTypes) { return operations } + function readFileSystemNote (filePath) { + const fsModifiedTime = moment(fs.statSync(filePath).mtime) + const content = fs.readFileSync(filePath, 'utf8') + + return { + lastchangeAt: fsModifiedTime, + title: Note.parseNoteTitle(content), + content: content + } + } + + function shouldSyncNote (note, noteInFS) { + const dbModifiedTime = moment(note.lastchangeAt || note.createdAt) + return noteInFS.lastchangeAt.isAfter(dbModifiedTime) && note.content !== noteInFS.content + } + return Note } diff --git a/lib/models/revision.js b/lib/models/revision.js index b628d96d..5f91b7d8 100644 --- a/lib/models/revision.js +++ b/lib/models/revision.js @@ -6,6 +6,7 @@ var moment = require('moment') var childProcess = require('child_process') var shortId = require('shortid') var path = require('path') +var util = require('util') var Op = Sequelize.Op @@ -296,6 +297,7 @@ module.exports = function (sequelize, DataTypes) { return callback(err, null) }) } + Revision.saveNoteRevisionAsync = util.promisify(Revision.saveNoteRevision) Revision.finishSaveNoteRevision = function (note, revision, callback) { note.update({ savedAt: revision.updatedAt diff --git a/lib/note/index.js b/lib/note/index.js index 0a20238e..41d8cf58 100644 --- a/lib/note/index.js +++ b/lib/note/index.js @@ -268,7 +268,7 @@ const deleteNote = async (req, res) => { } const updateNote = async (req, res) => { - if (req.isAuthenticated()) { + if (req.isAuthenticated() || config.allowAnonymousEdits) { const noteId = await Note.parseNoteIdAsync(req.params.noteId) try { const note = await Note.findOne({ @@ -294,7 +294,7 @@ const updateNote = async (req, res) => { lastchangeAt: now, authorship: [ [ - req.user.id, + req.isAuthenticated() ? req.user.id : null, 0, content.length, now, @@ -308,7 +308,9 @@ const updateNote = async (req, res) => { return errorInternalError(req, res) } - updateHistory(req.user.id, note.id, content) + if (req.isAuthenticated()) { + updateHistory(req.user.id, noteId, content) + } Revision.saveNoteRevision(note, (err, revision) => { if (err) { @@ -321,7 +323,7 @@ const updateNote = async (req, res) => { }) }) } catch (err) { - logger.error(err) + logger.error(err.stack) logger.error('Update note failed: Internal Error.') return errorInternalError(req, res) } diff --git a/lib/response.js b/lib/response.js index 0de8f9bc..37a955ba 100644 --- a/lib/response.js +++ b/lib/response.js @@ -32,8 +32,10 @@ function errorForbidden (req, res) { if (req.user) { responseError(res, '403', 'Forbidden', 'oh no.') } else { + var nextURL = new URL('', config.serverURL) + nextURL.search = new URLSearchParams({ next: req.originalUrl }) req.flash('error', 'You are not allowed to access this page. Maybe try logging in?') - res.redirect(config.serverURL + '/') + res.redirect(nextURL.toString()) } } diff --git a/lib/status/index.js b/lib/status/index.js index 2f5366d6..2e344efa 100644 --- a/lib/status/index.js +++ b/lib/status/index.js @@ -41,7 +41,8 @@ exports.getConfig = (req, res) => { allowedUploadMimeTypes: config.allowedUploadMimeTypes, defaultUseHardbreak: config.defaultUseHardbreak, linkifyHeaderStyle: config.linkifyHeaderStyle, - useCDN: config.useCDN + useCDN: config.useCDN, + defaultTocDepth: config.defaultTocDepth } res.set({ 'Cache-Control': 'private', // only cache by client diff --git a/package-lock.json b/package-lock.json index dada5424..e31b7c4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -786,73 +786,10 @@ "dev": true }, "@hackmd/codemirror": { - "version": "5.49.8", - "resolved": "https://registry.npmjs.org/@hackmd/codemirror/-/codemirror-5.49.8.tgz", - "integrity": "sha512-UIkcTHeVDta9/Otr1IljP9d52YfDQq35ypndichvAEWoTGpq+s9ED2zv2QkYdsdoJ0z6ggwOooFJAoWiHFfYVQ==", - "dev": true, - "requires": { - "blint": "^1", - "node-static": "0.7.11", - "phantomjs-prebuilt": "^2.1.12", - "rollup": "^0.66.2", - "rollup-plugin-buble": "^0.19.2", - "rollup-watch": "^4.3.1", - "uglify-js": "^2.8.15" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } - } + "version": "5.57.7", + "resolved": "https://registry.npmjs.org/@hackmd/codemirror/-/codemirror-5.57.7.tgz", + "integrity": "sha512-eNWQaKg39JoCH++PyM6drafjKLf7LmpCypI4/K3ftGo/wuTh4iZXk02qoRWFMVSvowYN7eH8pDSkKiZmiD2T1w==", + "dev": true }, "@hackmd/diff-match-patch": { "version": "1.1.3", @@ -1339,12 +1276,6 @@ "@types/d3-selection": "*" } }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, "@types/express": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.2.tgz", @@ -1679,12 +1610,6 @@ "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", "dev": true }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true - }, "acorn-es7-plugin": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz", @@ -1774,28 +1699,6 @@ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", "dev": true }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", @@ -3183,31 +3086,6 @@ } } }, - "blint": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/blint/-/blint-1.1.1.tgz", - "integrity": "sha512-kpYOL/1xnokcGTUpwfpsfw25YyYHrbgTfx6ym2zgSWb+ok7ga30/ha8qOaiPQufSNIGcnNcZQUkQkRF6YkmmXQ==", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "nomnom": "^1.8.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", - "dev": true - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - } - } - }, "blob": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", @@ -3433,30 +3311,6 @@ "electron-to-chromium": "^1.3.47" } }, - "buble": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/buble/-/buble-0.19.8.tgz", - "integrity": "sha512-IoGZzrUTY5fKXVkgGHw3QeXFMUNBFv+9l8a4QJKG1JhG3nCMHTdEX1DCOg8568E2Q9qvAQIiSokv6Jsgx8p2cA==", - "dev": true, - "requires": { - "acorn": "^6.1.1", - "acorn-dynamic-import": "^4.0.0", - "acorn-jsx": "^5.0.1", - "chalk": "^2.4.2", - "magic-string": "^0.25.3", - "minimist": "^1.2.0", - "os-homedir": "^2.0.0", - "regexpu-core": "^4.5.4" - }, - "dependencies": { - "os-homedir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-2.0.0.tgz", - "integrity": "sha512-saRNz0DSC5C/I++gFIaJTXoFJMRwiP5zHar5vV3xQ2TkgEw6hDCcU5F272JjUylpiVgBrZNQHnfjkLabTfb92Q==", - "dev": true - } - } - }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -3735,16 +3589,6 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -6662,12 +6506,6 @@ "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6759,57 +6597,6 @@ } } }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - }, - "dependencies": { - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -7189,12 +6976,6 @@ "dev": true, "optional": true }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -7322,15 +7103,6 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, "foreground-child": { "version": "1.5.6", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", @@ -7480,21 +7252,21 @@ }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "resolved": false, "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -7505,14 +7277,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -7523,42 +7295,42 @@ }, "chownr": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "resolved": false, "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "resolved": false, "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "optional": true, @@ -7568,28 +7340,28 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "resolved": false, "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "resolved": false, "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", "dev": true, "optional": true, @@ -7599,14 +7371,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -7623,7 +7395,7 @@ }, "glob": { "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "resolved": false, "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "optional": true, @@ -7638,14 +7410,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "resolved": false, "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -7655,7 +7427,7 @@ }, "ignore-walk": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "resolved": false, "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "optional": true, @@ -7665,7 +7437,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -7676,21 +7448,21 @@ }, "inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "resolved": false, "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -7700,14 +7472,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -7717,14 +7489,14 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "resolved": false, "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", "dev": true, "optional": true, @@ -7735,7 +7507,7 @@ }, "minizlib": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "resolved": false, "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", "dev": true, "optional": true, @@ -7745,7 +7517,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -7755,14 +7527,14 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "resolved": false, "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "optional": true }, "needle": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "resolved": false, "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", "dev": true, "optional": true, @@ -7774,7 +7546,7 @@ }, "node-pre-gyp": { "version": "0.14.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "resolved": false, "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", "dev": true, "optional": true, @@ -7793,7 +7565,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -7804,7 +7576,7 @@ }, "npm-bundled": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "resolved": false, "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "optional": true, @@ -7814,14 +7586,14 @@ }, "npm-normalize-package-bin": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "resolved": false, "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.7", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz", + "resolved": false, "integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==", "dev": true, "optional": true, @@ -7832,7 +7604,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -7845,21 +7617,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -7869,21 +7641,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -7894,21 +7666,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "resolved": false, "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "resolved": false, "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -7921,7 +7693,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -7930,7 +7702,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -7946,7 +7718,7 @@ }, "rimraf": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "resolved": false, "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "optional": true, @@ -7956,49 +7728,49 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "resolved": false, "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "resolved": false, "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -8010,7 +7782,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -8020,7 +7792,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -8030,14 +7802,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "resolved": false, "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", "dev": true, "optional": true, @@ -8053,14 +7825,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "resolved": false, "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -8070,14 +7842,14 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "resolved": false, "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "optional": true @@ -8170,42 +7942,6 @@ "path-is-absolute": "^1.0.0" } }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", @@ -9216,21 +8952,6 @@ "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", "dev": true }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -9310,18 +9031,6 @@ "isobject": "^3.0.1" } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -9906,12 +9615,6 @@ "webpack-sources": "^1.1.0" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -10260,12 +9963,6 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10318,15 +10015,6 @@ "request": "^2.88.0" } }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -10488,21 +10176,56 @@ } }, "markdownlint": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.17.2.tgz", - "integrity": "sha512-vsxopn0qEdm0P2XI3S9sVA+jvjKjR8lHZ+0FKlusth+1UK9tI29mRFkKeZPERmbWsMehJcogfMieBUkMgNEFkQ==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.22.0.tgz", + "integrity": "sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w==", "dev": true, "requires": { - "markdown-it": "10.0.0" + "markdown-it": "12.0.2" }, "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.2.tgz", + "integrity": "sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.0.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } } } }, + "markdownlint-rule-helpers": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.13.0.tgz", + "integrity": "sha512-rRY0itbcHG4e+ntz0bbY3AIceSJMKS0TafEMgEtKVHRZ54/JUSy6/4ypCL618RlJvYRej+xMLxX5nkJqIeTZaQ==", + "dev": true + }, "marked": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.3.tgz", @@ -10573,12 +10296,6 @@ "xregexp": "^2.0.0" } }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, "mathjax": { "version": "2.7.5", "resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.5.tgz", @@ -11498,17 +11215,6 @@ } } }, - "node-static": { - "version": "0.7.11", - "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.11.tgz", - "integrity": "sha512-zfWC/gICcqb74D9ndyvxZWaI1jzcoHmf4UTHWQchBNuNMxdBLJMDiUgZ1tjGLEIe/BMhj2DxKD8HOuc2062pDQ==", - "dev": true, - "requires": { - "colors": ">=0.6.0", - "mime": "^1.2.9", - "optimist": ">=0.3.4" - } - }, "nomnom": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", @@ -11801,16 +11507,6 @@ "es-abstract": "^1.17.0-next.1" } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -12141,35 +11837,6 @@ "is-hexadecimal": "^1.0.0" } }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -12440,9 +12107,9 @@ } }, "pdfobject": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pdfobject/-/pdfobject-2.1.1.tgz", - "integrity": "sha512-QFktTHyjs4q/WhGFfV2RdAbscPdNkyQb/JfFz18cwILvs9ocDiYVFAEh/jgkKGv6my+r4nlbLjwj7BHFKAupHQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/pdfobject/-/pdfobject-2.2.4.tgz", + "integrity": "sha512-r6Rw9CQWsrY6uqmKvlgFNoupmuRbSt9EsG0sZhSAy3cIk4WgOXyAVmebFSlLhqj6gA5NIEXL3lSEbwOOYfdUvw==", "dev": true }, "pend": { @@ -13703,12 +13370,6 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, "pretty-error": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", @@ -13939,25 +13600,6 @@ "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -14153,15 +13795,6 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", @@ -14178,15 +13811,6 @@ "private": "^0.1.6" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -14203,37 +13827,6 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, - "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - }, - "dependencies": { - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", @@ -14428,12 +14021,6 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, - "require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, "reselect": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz", @@ -14549,15 +14136,6 @@ "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -14577,173 +14155,6 @@ "inherits": "^2.0.1" } }, - "rollup": { - "version": "0.66.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.66.6.tgz", - "integrity": "sha512-J7/SWanrcb83vfIHqa8+aVVGzy457GcjA6GVZEnD0x2u4OnOd0Q1pCrEoNe8yLwM6z6LZP02zBT2uW0yh5TqOw==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "@types/node": "*" - } - }, - "rollup-plugin-buble": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/rollup-plugin-buble/-/rollup-plugin-buble-0.19.8.tgz", - "integrity": "sha512-8J4zPk2DQdk3rxeZvxgzhHh/rm5nJkjwgcsUYisCQg1QbT5yagW+hehYEW7ZNns/NVbDCTv4JQ7h4fC8qKGOKw==", - "dev": true, - "requires": { - "buble": "^0.19.8", - "rollup-pluginutils": "^2.3.3" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - } - }, - "rollup-watch": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/rollup-watch/-/rollup-watch-4.3.1.tgz", - "integrity": "sha512-6yjnIwfjpSrqA8IafyIu7fsEyeImNR4aDjA1bQ7KWeVuiA+Clfsx8+PGQkyABWIQzmauQ//tIJ5wAxLXsXs8qQ==", - "dev": true, - "requires": { - "chokidar": "^1.7.0", - "require-relative": "0.8.7", - "rollup-pluginutils": "^2.0.1" - }, - "dependencies": { - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - } - } - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -15444,12 +14855,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, "spawn-wrap": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", @@ -16561,13 +15966,6 @@ } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, "uglifyjs-webpack-plugin": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz", @@ -16633,34 +16031,6 @@ "xtend": "^4.0.0" } }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true - }, "unified": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", @@ -18183,12 +17553,6 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, "winston": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", diff --git a/package.json b/package.json index eff7720b..da9754c5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "coverage:ci": "nyc mocha --no-color -R dot --require intelli-espower-loader --exit --recursive ./test", "test": "npm run-script lint && npm run-script jsonlint && npm run-script coverage", "test:ci": "npm run-script lint && npm run-script jsonlint && npm run-script coverage:ci", - "postinstall": "bin/heroku" + "heroku-postbuild": "npm run build && ./bin/heroku" }, "dependencies": { "@aws-sdk/client-s3-node": "0.1.0-preview.2", @@ -105,7 +105,7 @@ "ws": "~7.1.1" }, "devDependencies": { - "@hackmd/codemirror": "~5.49.8", + "@hackmd/codemirror": "~5.57.7", "@hackmd/emojify.js": "^2.1.0", "@hackmd/idle-js": "~1.0.1", "@hackmd/js-sequence-diagrams": "~0.0.1-alpha.3", @@ -163,7 +163,8 @@ "markdown-it-ruby": "^0.1.1", "markdown-it-sub": "~1.0.0", "markdown-it-sup": "~1.0.0", - "markdownlint": "^0.17.0", + "markdownlint": "^0.22.0", + "markdownlint-rule-helpers": "^0.13.0", "markmap-lib": "^0.4.2", "mathjax": "~2.7.5", "mermaid": "~8.6.4", @@ -173,7 +174,7 @@ "nyc": "~14.0.0", "optimize-css-assets-webpack-plugin": "~5.0.0", "papaparse": "^5.2.0", - "pdfobject": "~2.1.1", + "pdfobject": "~2.2.4", "plantuml-encoder": "^1.2.5", "power-assert": "~1.6.1", "prismjs": "^1.17.1", diff --git a/public/css/extra.css b/public/css/extra.css index e795bc1b..2d1a0b32 100644 --- a/public/css/extra.css +++ b/public/css/extra.css @@ -263,6 +263,32 @@ padding-right: 40px; } +.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 50px; + font-size: 12px; + font-weight: 400; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a { + padding-right: 50px; +} + +.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 60px; + font-size: 12px; + font-weight: 400; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a { + padding-right: 60px; +} + + + .ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover { padding-left: 29px; } @@ -279,6 +305,22 @@ padding-right: 39px; } +.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>a:hover { + padding-left: 49px; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>a:hover { + padding-right: 49px; +} + +.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>ul>li>ul>li>a:hover { + padding-left: 59px; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a:focus,.ui-toc-dropdown[dir='rtl'] .nav .nav>li>ul>li>ul>li>ul>li>a:hover { + padding-right: 59px; +} + .ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a { padding-left: 28px; font-weight: 500; @@ -297,6 +339,24 @@ padding-right: 38px; } +.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>a { + padding-left: 48px; + font-weight: 500; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.active>.nav>.nav>.active>a { + padding-right: 48px; +} + +.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active>a { + padding-left: 58px; + font-weight: 500; +} + +.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.nav>.active>.nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir='rtl'] .nav .nav>.active>.active>.nav>.nav>.active>.nav>.active>a { + padding-right: 58px; +} + /* support japanese font */ .markdown-body[lang^="ja"] { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, Arial, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", Osaka, Meiryo, "メイリオ", "MS Gothic", "MS ゴシック", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; diff --git a/public/docs/features.md b/public/docs/features.md index 805ea7cc..3d2201b5 100644 --- a/public/docs/features.md +++ b/public/docs/features.md @@ -82,7 +82,8 @@ View ## Table of Contents: You can look at the bottom right section of the view area, there is a _ToC_ button . Pressing that button will show you a current _Table of Contents_, and will highlight which section you're at. -ToCs support up to **three header levels**. +ToCs support up to **five header levels**, the **default** is **set to three**. The maxLevel can be set for each note by using +[YAML Metadata](./yaml-metadata) ## Permalink Every header will automatically add a permalink on the right side. @@ -133,12 +134,19 @@ You can provide advanced note information to set the browser behavior (visit abo - GA: set to use Google Analytics - disqus: set to use Disqus - slideOptions: setup slide mode options +- toc: set options of the Table of Contents. ## ToC: -Use the syntax `[TOC]` to embed table of content into your note. +Use the syntax `[TOC]` to embed table of content into your note. By default, three header levels are displayed. This can also be specified by using [YAML Metadata](./yaml-metadata). [TOC] +You can also specify the number of header levels by specifying the `maxLevel` like this: `[TOC maxLevel=1]` + +[TOC maxLevel=1] + + + ## Emoji You can type any emoji like this :smile: :smiley: :cry: :wink: > See full emoji list [here](http://www.emoji-cheat-sheet.com/). diff --git a/public/docs/release-notes.md b/public/docs/release-notes.md index 3f5fdf9f..169525ec 100644 --- a/public/docs/release-notes.md +++ b/public/docs/release-notes.md @@ -1,6 +1,44 @@ Release Notes === + 2.4.0 Papilio maraho 2021-05-11 +--- + +
+ + Papilio maraho +
+ +> Papilio maraho is a species of butterfly in the family Papilionidae. It is endemic to Taiwan. +> \- Wikipedia [Papilio maraho](https://en.wikipedia.org/wiki/Papilio_maraho) + +[Check out the complete release note][v2_4_0]. Thank you CodiMD community and all our contributors. ❤️ + +[v2_4_0]: https://hackmd.io/@codimd/release-notes/%2F%40codimd%2Fv2_4_0 + +## Enhancements + +- Support autofix linter errors +- Support anonymous updates via API +- Support mediawiki export format in pandoc export +- Add some help strings to Prometheus metrics +- Allow more syntax highlight modes in editor +- Support TOC level customization +- Follow Google guidelines to use Google OAuth + +## Fixes + +- Vimeo won't show up due to the jsonp callback data unable be parsed with jQuery +- Fix slide mode stored XSS +- Enforce PG ssl require mode on heroku +- Webpack exclude path should support windows path +- Free url can read any md in file system +- Use encoded noteId when calling updateHistory + +## Docs + +- Add matrix badge and links to README [#1629](https://github.com/hackmdio/codimd/pull/1629) [@a-andreyev](https://github.com/a-andreyev) + 2.3.1 Isoetes taiwanensis 2021-01-04 --- diff --git a/public/docs/yaml-metadata.md b/public/docs/yaml-metadata.md index 5c1f54d9..c570a5f6 100644 --- a/public/docs/yaml-metadata.md +++ b/public/docs/yaml-metadata.md @@ -139,6 +139,22 @@ This option allows you to enable Disqus with your shortname. disqus: codimd ``` +toc +--- + +This option allows you to set options regarding the table of contents (toc). Currently, its only option is to set the maxDepth. + +**Notice: always use two spaces as indention in YAML metadata!** + + +> **maxDepth:** +> default: not set (whioch will show everything until level 3 (h1 -- h3)) +> max: 5 (as defined by md-toc.js) + + +**Example** + + type --- This option allows you to switch the document view to the slide preview, to simplify live editing of presentations. diff --git a/public/js/extra.js b/public/js/extra.js index b59a84dc..f076d1bb 100644 --- a/public/js/extra.js +++ b/public/js/extra.js @@ -260,6 +260,23 @@ if (typeof window.mermaid !== 'undefined' && window.mermaid) { } } +function jsonp (url, callback) { + const callbackName = 'jsonp_callback_' + Math.round(1000000000 * Math.random()) + window[callbackName] = function (data) { + delete window[callbackName] + document.body.removeChild(script) + callback(data) + } + + const script = document.createElement('script') + script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'callback=' + callbackName + document.body.appendChild(script) + script.onerror = function (e) { + console.error(e) + script.remove() + } +} + // dynamic event or object binding here export function finishView (view) { // todo list @@ -304,17 +321,11 @@ export function finishView (view) { imgPlayiframe(this, '//player.vimeo.com/video/') }) .each((key, value) => { - $.ajax({ - type: 'GET', - url: `//vimeo.com/api/v2/video/${$(value).attr('data-videoid')}.json`, - jsonp: 'callback', - dataType: 'jsonp', - success (data) { - const thumbnailSrc = data[0].thumbnail_large - const image = `` - $(value).prepend(image) - if (window.viewAjaxCallback) window.viewAjaxCallback() - } + jsonp(`//vimeo.com/api/v2/video/${$(value).attr('data-videoid')}.json`, function (data) { + const thumbnailSrc = data[0].thumbnail_large + const image = `` + $(value).prepend(image) + if (window.viewAjaxCallback) window.viewAjaxCallback() }) }) // gist @@ -597,9 +608,11 @@ export function finishView (view) { const url = $(value).attr('data-pdfurl') const inner = $('
') $(this).append(inner) - PDFObject.embed(url, inner, { - height: '400px' - }) + setTimeout(() => { + PDFObject.embed(url, inner, { + height: '400px' + }) + }, 1) }) // syntax highlighting view.find('code.raw').removeClass('raw') @@ -864,8 +877,12 @@ export function generateToc (id) { const target = $(`#${id}`) target.html('') /* eslint-disable no-unused-vars */ + + var tocOptions = md.meta.toc || {} + var maxLevel = (typeof tocOptions.maxLevel === 'number' && tocOptions.maxLevel > 0) ? tocOptions.maxLevel : window.defaultTocDepth + var toc = new window.Toc('doc', { - level: 3, + level: maxLevel, top: -1, class: 'toc', ulClass: 'nav', @@ -1063,11 +1080,20 @@ export function renderTOC (view) { const target = $(`#${id}`) target.html('') /* eslint-disable no-unused-vars */ + + const specificDepth = parseInt(toc.data('toc-depth')) + + var tocOptions = md.meta.toc || {} + var yamlMaxDepth = (typeof tocOptions.maxLevel === 'number' && tocOptions.maxLevel > 0) ? tocOptions.maxLevel : window.defaultTocDepth + + var maxLevel = specificDepth || yamlMaxDepth + const TOC = new window.Toc('doc', { - level: 3, + level: maxLevel, top: -1, class: 'toc', targetId: id, + data: { tocDepth: specificDepth }, process: getHeaderContent }) /* eslint-enable no-unused-vars */ @@ -1322,9 +1348,12 @@ const gistPlugin = new Plugin( // TOC const tocPlugin = new Plugin( // regexp to match - /^\[TOC\]$/i, + /^\[TOC(|\s*maxLevel=\d+?)\]$/i, - (match, utils) => '
' + (match, utils) => { + const tocDepth = match[1].split(/[?&=]+/)[1] + return `
` + } ) // slideshare const slidesharePlugin = new Plugin( diff --git a/public/js/lib/common/constant.ejs b/public/js/lib/common/constant.ejs index 57438912..3cb960ff 100644 --- a/public/js/lib/common/constant.ejs +++ b/public/js/lib/common/constant.ejs @@ -13,3 +13,5 @@ window.linkifyHeaderStyle = '<%- linkifyHeaderStyle %>' window.DROPBOX_APP_KEY = '<%- DROPBOX_APP_KEY %>' window.USE_CDN = <%- useCDN %> + +window.defaultTocDepth = <%- defaultTocDepth %> diff --git a/public/js/lib/common/metrics.ejs b/public/js/lib/common/metrics.ejs index 72b1d9dc..474094eb 100644 --- a/public/js/lib/common/metrics.ejs +++ b/public/js/lib/common/metrics.ejs @@ -1,9 +1,23 @@ +# HELP online_notes Number of currently used notes +# TYPE online_notes gauge online_notes <%- onlineNotes %> +# HELP online_users Number of online users +# TYPE online_users gauge online_users <%- onlineUsers %> +# HELP distinct_online_users Number of distinct online users +# TYPE distinct_online_users gauge distinct_online_users <%- distinctOnlineUsers %> +# HELP notes_count Total count of notes +# TYPE notes_count gauge notes_count <%- notesCount %> +# HELP registered_users Number of registered users +# TYPE registered_users gauge registered_users <%- registeredUsers %> +# HELP online_registered_users Number of online registered users +# TYPE online_registered_users gauge online_registered_users <%- onlineRegisteredUsers %> +# HELP distinct_online_registered_users Number of distinct online registered users +# TYPE distinct_online_registered_users gauge distinct_online_registered_users <%- distinctOnlineRegisteredUsers %> is_connection_busy <%- isConnectionBusy ? 1 : 0 %> connection_socket_queue_length <%- connectionSocketQueueLength %> diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js index 1d8a0dc7..eb887da6 100644 --- a/public/js/lib/editor/index.js +++ b/public/js/lib/editor/index.js @@ -6,7 +6,7 @@ import * as utils from './utils' import config from './config' import statusBarTemplate from './statusbar.html' import toolBarTemplate from './toolbar.html' -import './markdown-lint' +import { linterOptions } from './markdown-lint' import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from './spellcheck' import { initTableEditor } from './table-editor' import { availableThemes } from './constants' @@ -140,6 +140,42 @@ export default class Editor { } } + CodeMirror.defineMode('c', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-csrc'), ignoreOverlay) + }) + CodeMirror.defineMode('cpp', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-c++src'), ignoreOverlay) + }) + CodeMirror.defineMode('java', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-java'), ignoreOverlay) + }) + CodeMirror.defineMode('csharp', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-csharp'), ignoreOverlay) + }) + CodeMirror.defineMode('objectivec', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-objectivec'), ignoreOverlay) + }) + CodeMirror.defineMode('scala', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-scala'), ignoreOverlay) + }) + CodeMirror.defineMode('kotlin', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-kotlin'), ignoreOverlay) + }) + CodeMirror.defineMode('json', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/json'), ignoreOverlay) + }) + CodeMirror.defineMode('jsonld', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/ld+json'), ignoreOverlay) + }) + CodeMirror.defineMode('bash', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-sh'), ignoreOverlay) + }) + CodeMirror.defineMode('ocaml', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'text/x-ocaml'), ignoreOverlay) + }) + CodeMirror.defineMode('csvpreview', function (config, modeConfig) { + return CodeMirror.overlayMode(CodeMirror.getMode(config, 'csv'), ignoreOverlay) + }) CodeMirror.defineMode('vega', function (config, modeConfig) { return CodeMirror.overlayMode(CodeMirror.getMode(config, 'application/ld+json'), ignoreOverlay) }) @@ -674,7 +710,7 @@ export default class Editor { this.editor.setOption('gutters', gutters.filter(g => g !== lintGutter)) Cookies.remove('linter') } - this.editor.setOption('lint', enable) + this.editor.setOption('lint', enable ? linterOptions : false) } setLinter () { @@ -685,7 +721,7 @@ export default class Editor { } linterToggle.click(() => { - const lintEnable = this.editor.getOption('lint') + const lintEnable = !!this.editor.getOption('lint') this.toggleLinter.bind(this)(!lintEnable) updateLinterStatus(!lintEnable) }) diff --git a/public/js/lib/editor/markdown-lint/index.js b/public/js/lib/editor/markdown-lint/index.js index e3a055e8..349d458b 100644 --- a/public/js/lib/editor/markdown-lint/index.js +++ b/public/js/lib/editor/markdown-lint/index.js @@ -3,6 +3,9 @@ // load CM lint plugin explicitly import '@hackmd/codemirror/addon/lint/lint' +import '@hackmd/codemirror/addon/hint/show-hint.css' +import helpers from 'markdownlint-rule-helpers' + window.markdownit = require('markdown-it') // eslint-disable-next-line require('script-loader!markdownlint'); @@ -26,10 +29,11 @@ require('script-loader!markdownlint'); } return { - messageHTML: `${ruleNames.join('/')}: ${ruleDescription}`, + messageHTML: `${ruleNames.join('/')}: ${ruleDescription} markdownlint(${ruleNames[0]})`, severity: 'error', from: CodeMirror.Pos(lineNumber, start), - to: CodeMirror.Pos(lineNumber, end) + to: CodeMirror.Pos(lineNumber, end), + __error: error } }) } @@ -37,11 +41,84 @@ require('script-loader!markdownlint'); CodeMirror.registerHelper('lint', 'markdown', validator) }) +export const linterOptions = { + fixedTooltip: true, + contextmenu: annotations => { + const singleFixMenus = annotations + .map(annotation => { + const error = annotation.__error + const ruleNameAlias = error.ruleNames.join('/') + + if (annotation.__error.fixInfo) { + return { + content: `Click to fix this violoation of ${ruleNameAlias}`, + onClick () { + const doc = window.editor.doc + const fixInfo = normalizeFixInfo(error.fixInfo, error.lineNumber) + const line = fixInfo.lineNumber - 1 + const lineContent = doc.getLine(line) || '' + const fixedText = helpers.applyFix(lineContent, fixInfo, '\n') + + let from = { line, ch: 0 } + let to = { line, ch: lineContent ? lineContent.length : 0 } + + if (typeof fixedText === 'string') { + doc.replaceRange(fixedText, from, to) + } else { + if (fixInfo.lineNumber === 1) { + if (doc.lineCount() > 1) { + const nextLineStart = doc.indexFromPos({ + line: to.line + 1, + ch: 0 + }) + to = doc.posFromIndex(nextLineStart) + } + } else { + const previousLineEnd = doc.indexFromPos(from) - 1 + from = doc.posFromIndex(previousLineEnd) + } + + doc.replaceRange('', from, to) + } + } + } + } else { + return { + content: `Click for more information about ${ruleNameAlias}`, + onClick () { + window.open(error.ruleInformation, '_blank') + } + } + } + }) + + return singleFixMenus + } +} + function lint (content) { const { content: errors } = window.markdownlint.sync({ strings: { content - } + }, + resultVersion: 3 }) return errors } + +// Taken from https://github.com/DavidAnson/markdownlint/blob/2a9274ece586514ba3e2819cec3eb74312dc1b84/helpers/helpers.js#L611 +/** + * Normalizes the fields of a RuleOnErrorFixInfo instance. + * + * @param {Object} fixInfo RuleOnErrorFixInfo instance. + * @param {number} [lineNumber] Line number. + * @returns {Object} Normalized RuleOnErrorFixInfo instance. + */ +function normalizeFixInfo (fixInfo, lineNumber) { + return { + lineNumber: fixInfo.lineNumber || lineNumber, + editColumn: fixInfo.editColumn || 1, + deleteCount: fixInfo.deleteCount || 0, + insertText: fixInfo.insertText || '' + } +} diff --git a/public/js/reveal-markdown.js b/public/js/reveal-markdown.js index ad5bfd04..c49bb9a2 100644 --- a/public/js/reveal-markdown.js +++ b/public/js/reveal-markdown.js @@ -103,7 +103,7 @@ import { md } from './extra' // prevent script end tags in the content from interfering // with parsing - content = content.replace(/<\/script>/g, SCRIPT_END_PLACEHOLDER) + content = content.replace(/<\/script>/gi, SCRIPT_END_PLACEHOLDER) return '' } diff --git a/public/js/slide.js b/public/js/slide.js index 61546339..455986f4 100644 --- a/public/js/slide.js +++ b/public/js/slide.js @@ -80,6 +80,8 @@ const defaultOptions = { } var options = meta.slideOptions || {} +// delete dependencies to avoid import user defined external resources +delete options.dependencies if (Object.hasOwnProperty.call(options, 'spotlight')) { defaultOptions.dependencies.push({ diff --git a/public/markdown-lint/css/lint.css b/public/markdown-lint/css/lint.css index cad3e236..a5588cd7 100644 --- a/public/markdown-lint/css/lint.css +++ b/public/markdown-lint/css/lint.css @@ -71,3 +71,11 @@ background-position: right bottom; width: 100%; height: 100%; } + +.CodeMirror-hints { + background: #333; +} + +.CodeMirror-hint { + color: white; +} diff --git a/public/vendor/md-toc.js b/public/vendor/md-toc.js index 59e75aed..0c7b5116 100644 --- a/public/vendor/md-toc.js +++ b/public/vendor/md-toc.js @@ -2,6 +2,8 @@ /** * md-toc.js v1.0.2 * https://github.com/yijian166/md-toc.js + * + * Adapted to accept data attributes */ (function (window) { @@ -15,6 +17,7 @@ this.tocTop = parseInt(options.top) || 0 this.elChilds = this.el.children this.process = options['process'] + this.data = options.data || {} if (!this.elChilds.length) return this._init() } @@ -123,6 +126,9 @@ this.toc = document.createElement('div') this.toc.innerHTML = this.tocContent this.toc.setAttribute('class', this.tocClass) + if (this.data.tocDepth) { + this.toc.dataset.tocDepth = this.data.tocDepth + } if (!this.options.targetId) { this.el.appendChild(this.toc) } else { diff --git a/public/views/index/body.ejs b/public/views/index/body.ejs index db20b0e3..5426761d 100644 --- a/public/views/index/body.ejs +++ b/public/views/index/body.ejs @@ -77,7 +77,7 @@
- +

<%= __('Support slide mode') %>

@@ -156,6 +156,7 @@
<%- __('Follow us on %s and %s.', ' GitHub, Gitter', ' POEditor') %>
+ <% if(privacyPolicyURL && privacyPolicyURL.length > 0) { %>

<%= __('Privacy Policy') %>

<% } %>
diff --git a/public/views/shared/pandoc-export-modal.ejs b/public/views/shared/pandoc-export-modal.ejs index 4d985d41..948fb120 100644 --- a/public/views/shared/pandoc-export-modal.ejs +++ b/public/views/shared/pandoc-export-modal.ejs @@ -21,6 +21,7 @@ +