summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rw-r--r--app.js16
-rw-r--r--config.json.example3
-rw-r--r--lib/config/default.js1
-rw-r--r--lib/config/environment.js2
-rw-r--r--lib/config/index.js6
-rw-r--r--lib/history.js15
-rw-r--r--lib/migrations/20150702001020-update-to-0_3_1.js6
-rw-r--r--lib/migrations/20160112220142-note-add-lastchange.js6
-rw-r--r--lib/migrations/20160420180355-note-add-alias.js6
-rw-r--r--lib/migrations/20160515114000-user-add-tokens.js6
-rw-r--r--lib/migrations/20160607060246-support-revision.js6
-rw-r--r--lib/migrations/20160703062241-support-authorship.js6
-rw-r--r--lib/migrations/20161009040430-support-delete-note.js8
-rw-r--r--lib/migrations/20161201050312-support-email-signin.js14
-rw-r--r--lib/models/note.js6
-rw-r--r--lib/response.js4
-rw-r--r--package.json2
-rw-r--r--public/js/index.js17
-rw-r--r--public/views/codimd/body.ejs2
-rw-r--r--public/views/index/body.ejs2
-rw-r--r--yarn.lock6
22 files changed, 131 insertions, 21 deletions
diff --git a/README.md b/README.md
index 34d52b57..78d89121 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ Thanks for using! :smile:
- [Heroku Deployment](#heroku-deployment)
- [Kubernetes](#kubernetes)
- [CodiMD by docker container](#codimd-by-docker-container)
+ - [Cloudron](#cloudron)
- [Upgrade](#upgrade)
- [Native setup](#native-setup)
- [Configuration](#configuration)
@@ -121,6 +122,12 @@ docker-compose up
```
Read more about it in the [docker repository…](https://github.com/hackmdio/docker-hackmd)
+## Cloudron
+
+Install CodiMD on [Cloudron](https://cloudron.io):
+
+[![Install](https://cloudron.io/img/button.svg)](https://cloudron.io/button.html?app=io.hackmd.cloudronapp)
+
# Upgrade
## Native setup
@@ -170,7 +177,9 @@ There are some config settings you need to change in the files below.
| `DEBUG` | `true` or `false` | set debug mode; show more logs |
| `CMD_DOMAIN` | `codimd.org` | domain name |
| `CMD_URL_PATH` | `codimd` | sub URL path, like `www.example.com/<URL_PATH>` |
+| `CMD_HOST` | `localhost` | host to listen on |
| `CMD_PORT` | `80` | web app port |
+| `CMD_PATH` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `CMD_HOST` and `CMD_PORT` are ignored) |
| `CMD_ALLOW_ORIGIN` | `localhost, codimd.org` | domain name whitelist (use comma to separate) |
| `CMD_PROTOCOL_USESSL` | `true` or `false` | set to use SSL protocol for resources path (only applied when domain is set) |
| `CMD_URL_ADDPORT` | `true` or `false` | set to add port on callback URL (ports `80` or `443` won't be applied) (only applied when domain is set) |
@@ -192,6 +201,7 @@ There are some config settings you need to change in the files below.
| `CMD_GITLAB_BASEURL` | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) |
| `CMD_GITLAB_CLIENTID` | no example | GitLab API client id |
| `CMD_GITLAB_CLIENTSECRET` | no example | GitLab API client secret |
+| `CMD_GITLAB_VERSION` | no example | GitLab API version (v3 or v4) |
| `CMD_MATTERMOST_BASEURL` | no example | Mattermost authentication endpoint |
| `CMD_MATTERMOST_CLIENTID` | no example | Mattermost API client id |
| `CMD_MATTERMOST_CLIENTSECRET` | no example | Mattermost API client secret |
@@ -252,7 +262,9 @@ There are some config settings you need to change in the files below.
| `debug` | `true` or `false` | set debug mode, show more logs |
| `domain` | `localhost` | domain name |
| `urlPath` | `codimd` | sub URL path, like `www.example.com/<urlpath>` |
+| `host` | `localhost` | host to listen on |
| `port` | `80` | web app port |
+| `path` | `/var/run/codimd.sock` | path to UNIX domain socket to listen on (if specified, `host` and `port` are ignored) |
| `allowOrigin` | `['localhost']` | domain name whitelist |
| `useSSL` | `true` or `false` | set to use SSL server (if `true`, will auto turn on `protocolUseSSL`) |
| `hsts` | `{"enable": true, "maxAgeSeconds": 31536000, "includeSubdomains": true, "preload": true}` | [HSTS](https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security) options to use with HTTPS (default is the example value, max age is a year) |
diff --git a/app.js b/app.js
index e2479137..24f0516f 100644
--- a/app.js
+++ b/app.js
@@ -205,11 +205,21 @@ io.sockets.on('connection', realtime.connection)
// listen
function startListen () {
- server.listen(config.port, function () {
+ var address
+ var listenCallback = function () {
var schema = config.useSSL ? 'HTTPS' : 'HTTP'
- logger.info('%s Server listening at port %d', schema, config.port)
+ logger.info('%s Server listening at %s', schema, address)
realtime.maintenance = false
- })
+ }
+
+ // use unix domain socket if 'path' is specified
+ if (config.path) {
+ address = config.path
+ server.listen(config.path, listenCallback)
+ } else {
+ address = config.host + ':' + config.port
+ server.listen(config.port, config.host, listenCallback)
+ }
}
// sync db then start listen
diff --git a/config.json.example b/config.json.example
index 1f2ec3d5..16c95509 100644
--- a/config.json.example
+++ b/config.json.example
@@ -55,7 +55,8 @@
"baseURL": "change this",
"clientID": "change this",
"clientSecret": "change this",
- "scope": "use 'read_user' scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope 'api')"
+ "scope": "use 'read_user' scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope 'api')",
+ "version": "use 'v4' if gitlab version > 11, 'v3' otherwise. Default to 'v4'"
},
"mattermost": {
"baseURL": "change this",
diff --git a/lib/config/default.js b/lib/config/default.js
index 5c39a4da..6096bce4 100644
--- a/lib/config/default.js
+++ b/lib/config/default.js
@@ -3,6 +3,7 @@
module.exports = {
domain: '',
urlPath: '',
+ host: '0.0.0.0',
port: 3000,
urlAddPort: false,
allowOrigin: ['localhost'],
diff --git a/lib/config/environment.js b/lib/config/environment.js
index d850ac9d..6c4ce92f 100644
--- a/lib/config/environment.js
+++ b/lib/config/environment.js
@@ -5,7 +5,9 @@ const {toBooleanConfig, toArrayConfig, toIntegerConfig} = require('./utils')
module.exports = {
domain: process.env.CMD_DOMAIN,
urlPath: process.env.CMD_URL_PATH,
+ host: process.env.CMD_HOST,
port: toIntegerConfig(process.env.CMD_PORT),
+ path: process.env.CMD_PATH,
urlAddPort: toBooleanConfig(process.env.CMD_URL_ADDPORT),
useSSL: toBooleanConfig(process.env.CMD_USESSL),
hsts: {
diff --git a/lib/config/index.js b/lib/config/index.js
index ac03fcd4..f96684ea 100644
--- a/lib/config/index.js
+++ b/lib/config/index.js
@@ -103,6 +103,12 @@ config.isSAMLEnable = config.saml.idpSsoUrl
config.isOAuth2Enable = config.oauth2.clientID && config.oauth2.clientSecret
config.isPDFExportEnable = config.allowPDFExport
+// Check gitlab api version
+if (config.gitlab.version !== 'v4' && config.gitlab.version !== 'v3') {
+ logger.warn('config.js contains wrong version (' + config.gitlab.version + ') for gitlab api; it should be \'v3\' or \'v4\'. Defaulting to v4')
+ config.gitlab.version = 'v4'
+}
+
// Only update i18n files in development setups
config.updateI18nFiles = (env === Environment.development)
diff --git a/lib/history.js b/lib/history.js
index c7d2472c..9c389bfa 100644
--- a/lib/history.js
+++ b/lib/history.js
@@ -31,6 +31,15 @@ function getHistory (userid, callback) {
history = JSON.parse(user.history)
// migrate LZString encoded note id to base64url encoded note id
for (let i = 0, l = history.length; i < l; i++) {
+ // Calculate minimal string length for an UUID that is encoded
+ // base64 encoded and optimize comparsion by using -1
+ // this should make a lot of LZ-String parsing errors obsolete
+ // as we can assume that a nodeId that is 48 chars or longer is a
+ // noteID.
+ const base64UuidLength = ((4 * 36) / 3) - 1
+ if (!(history[i].id.length > base64UuidLength)) {
+ continue
+ }
try {
let id = LZString.decompressFromBase64(history[i].id)
if (id && models.Note.checkNoteIdValid(id)) {
@@ -38,7 +47,11 @@ function getHistory (userid, callback) {
}
} catch (err) {
// most error here comes from LZString, ignore
- logger.error(err)
+ if (err.message === 'Cannot read property \'charAt\' of undefined') {
+ logger.warning('Looks like we can not decode "' + history[i].id + '" with LZString. Can be ignored.')
+ } else {
+ logger.error(err)
+ }
}
}
history = parseHistoryToObject(history)
diff --git a/lib/migrations/20150702001020-update-to-0_3_1.js b/lib/migrations/20150702001020-update-to-0_3_1.js
index 40d9c97a..e661a343 100644
--- a/lib/migrations/20150702001020-update-to-0_3_1.js
+++ b/lib/migrations/20150702001020-update-to-0_3_1.js
@@ -20,6 +20,12 @@ module.exports = {
type: Sequelize.INTEGER,
defaultValue: 0
})
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'shortid'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20160112220142-note-add-lastchange.js b/lib/migrations/20160112220142-note-add-lastchange.js
index b4e111b3..d0030d6b 100644
--- a/lib/migrations/20160112220142-note-add-lastchange.js
+++ b/lib/migrations/20160112220142-note-add-lastchange.js
@@ -7,6 +7,12 @@ module.exports = {
return queryInterface.addColumn('Notes', 'lastchangeAt', {
type: Sequelize.DATE
})
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'lastchangeuserId'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20160420180355-note-add-alias.js b/lib/migrations/20160420180355-note-add-alias.js
index a043cd5c..4bad29ca 100644
--- a/lib/migrations/20160420180355-note-add-alias.js
+++ b/lib/migrations/20160420180355-note-add-alias.js
@@ -7,6 +7,12 @@ module.exports = {
return queryInterface.addIndex('Notes', ['alias'], {
indicesType: 'UNIQUE'
})
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'alias'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20160515114000-user-add-tokens.js b/lib/migrations/20160515114000-user-add-tokens.js
index 4d5818be..4245f1ad 100644
--- a/lib/migrations/20160515114000-user-add-tokens.js
+++ b/lib/migrations/20160515114000-user-add-tokens.js
@@ -3,6 +3,12 @@ module.exports = {
up: function (queryInterface, Sequelize) {
return queryInterface.addColumn('Users', 'accessToken', Sequelize.STRING).then(function () {
return queryInterface.addColumn('Users', 'refreshToken', Sequelize.STRING)
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'accessToken'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20160607060246-support-revision.js b/lib/migrations/20160607060246-support-revision.js
index bcab97e3..10f288b0 100644
--- a/lib/migrations/20160607060246-support-revision.js
+++ b/lib/migrations/20160607060246-support-revision.js
@@ -15,6 +15,12 @@ module.exports = {
createdAt: Sequelize.DATE,
updatedAt: Sequelize.DATE
})
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'savedAt'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20160703062241-support-authorship.js b/lib/migrations/20160703062241-support-authorship.js
index d73923b0..b3ced8c4 100644
--- a/lib/migrations/20160703062241-support-authorship.js
+++ b/lib/migrations/20160703062241-support-authorship.js
@@ -16,6 +16,12 @@ module.exports = {
createdAt: Sequelize.DATE,
updatedAt: Sequelize.DATE
})
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'authorship'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/migrations/20161009040430-support-delete-note.js b/lib/migrations/20161009040430-support-delete-note.js
index a39d1086..4df7a81c 100644
--- a/lib/migrations/20161009040430-support-delete-note.js
+++ b/lib/migrations/20161009040430-support-delete-note.js
@@ -1,7 +1,13 @@
'use strict'
module.exports = {
up: function (queryInterface, Sequelize) {
- return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE)
+ return queryInterface.addColumn('Notes', 'deletedAt', Sequelize.DATE).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'deletedAt'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
+ })
},
down: function (queryInterface, Sequelize) {
diff --git a/lib/migrations/20161201050312-support-email-signin.js b/lib/migrations/20161201050312-support-email-signin.js
index d33225f1..4653e67a 100644
--- a/lib/migrations/20161201050312-support-email-signin.js
+++ b/lib/migrations/20161201050312-support-email-signin.js
@@ -2,7 +2,19 @@
module.exports = {
up: function (queryInterface, Sequelize) {
return queryInterface.addColumn('Users', 'email', Sequelize.TEXT).then(function () {
- return queryInterface.addColumn('Users', 'password', Sequelize.TEXT)
+ return queryInterface.addColumn('Users', 'password', Sequelize.TEXT).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'password'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
+ })
+ }).catch(function (error) {
+ if (error.message === "ER_DUP_FIELDNAME: Duplicate column name 'email'") {
+ console.log('Migration has already run… ignoring.')
+ } else {
+ throw error
+ }
})
},
diff --git a/lib/models/note.js b/lib/models/note.js
index ec7e2b13..0e8dd4dd 100644
--- a/lib/models/note.js
+++ b/lib/models/note.js
@@ -227,7 +227,11 @@ module.exports = function (sequelize, DataTypes) {
var id = LZString.decompressFromBase64(noteId)
if (id && Note.checkNoteIdValid(id)) { return callback(null, id) } else { return _callback(null, null) }
} catch (err) {
- logger.error(err)
+ if (err.message === 'Cannot read property \'charAt\' of undefined') {
+ logger.warning('Looks like we can not decode "' + noteId + '" with LZString. Can be ignored.')
+ } else {
+ logger.error(err)
+ }
return _callback(null, null)
}
},
diff --git a/lib/response.js b/lib/response.js
index 3a31c511..37211998 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -573,11 +573,11 @@ function gitlabActionProjects (req, res, note) {
}
}).then(function (user) {
if (!user) { return response.errorNotFound(res) }
- var ret = { baseURL: config.gitlab.baseURL }
+ var ret = { baseURL: config.gitlab.baseURL, version: config.gitlab.version }
ret.accesstoken = user.accessToken
ret.profileid = user.profileid
request(
- config.gitlab.baseURL + '/api/v3/projects?access_token=' + user.accessToken,
+ config.gitlab.baseURL + '/api/' + config.gitlab.version + '/projects?access_token=' + user.accessToken,
function (error, httpResponse, body) {
if (!error && httpResponse.statusCode === 200) {
ret.projects = JSON.parse(body)
diff --git a/package.json b/package.json
index 88bef3e0..1740500c 100644
--- a/package.json
+++ b/package.json
@@ -76,7 +76,7 @@
"markdown-it-regexp": "^0.4.0",
"markdown-it-sub": "^1.0.0",
"markdown-it-sup": "^1.0.0",
- "markdown-pdf": "^8.0.0",
+ "markdown-pdf": "^9.0.0",
"mathjax": "~2.7.0",
"mermaid": "~7.1.0",
"mattermost": "^3.4.0",
diff --git a/public/js/index.js b/public/js/index.js
index 6e13fe9c..1330deac 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -970,6 +970,7 @@ ui.toolbar.export.snippet.click(function () {
.done(function (data) {
$('#snippetExportModalAccessToken').val(data.accesstoken)
$('#snippetExportModalBaseURL').val(data.baseURL)
+ $('#snippetExportModalVersion').val(data.version)
$('#snippetExportModalLoading').hide()
$('#snippetExportModal').modal('toggle')
$('#snippetExportModalProjects').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>')
@@ -1021,6 +1022,7 @@ ui.toolbar.import.snippet.click(function () {
.done(function (data) {
$('#snippetImportModalAccessToken').val(data.accesstoken)
$('#snippetImportModalBaseURL').val(data.baseURL)
+ $('#snippetImportModalVersion').val(data.version)
$('#snippetImportModalContent').prop('disabled', false)
$('#snippetImportModalConfirm').prop('disabled', false)
$('#snippetImportModalLoading').hide()
@@ -1243,10 +1245,10 @@ ui.modal.snippetImportProjects.change(function () {
var accesstoken = $('#snippetImportModalAccessToken').val()
var baseURL = $('#snippetImportModalBaseURL').val()
var project = $('#snippetImportModalProjects').val()
-
+ var version = $('#snippetImportModalVersion').val()
$('#snippetImportModalLoading').show()
$('#snippetImportModalContent').val('/projects/' + project)
- $.get(baseURL + '/api/v3/projects/' + project + '/snippets?access_token=' + accesstoken)
+ $.get(baseURL + '/api/' + version + '/projects/' + project + '/snippets?access_token=' + accesstoken)
.done(function (data) {
$('#snippetImportModalSnippets').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Snippets</option>')
data.forEach(function (snippet) {
@@ -1433,7 +1435,7 @@ $('#snippetImportModalConfirm').click(function () {
} else {
ui.spinner.show()
var accessToken = '?access_token=' + $('#snippetImportModalAccessToken').val()
- var fullURL = $('#snippetImportModalBaseURL').val() + '/api/v3' + snippeturl
+ var fullURL = $('#snippetImportModalBaseURL').val() + '/api/' + $('#snippetImportModalVersion').val() + snippeturl
$.get(fullURL + accessToken)
.done(function (data) {
var content = '# ' + (data.title || 'Snippet Import')
@@ -1470,15 +1472,19 @@ $('#snippetImportModalConfirm').click(function () {
$('#snippetExportModalConfirm').click(function () {
var accesstoken = $('#snippetExportModalAccessToken').val()
var baseURL = $('#snippetExportModalBaseURL').val()
+ var version = $('#snippetExportModalVersion').val()
+
var data = {
title: $('#snippetExportModalTitle').val(),
file_name: $('#snippetExportModalFileName').val(),
code: editor.getValue(),
- visibility_level: $('#snippetExportModalVisibility').val()
+ visibility_level: $('#snippetExportModalVisibility').val(),
+ visibility: $('#snippetExportModalVisibility').val() === 0 ? 'private' : ($('#snippetExportModalVisibility').val() === 10 ? 'internal' : '')
}
+
if (!data.title || !data.file_name || !data.code || !data.visibility_level || !$('#snippetExportModalProjects').val()) return
$('#snippetExportModalLoading').show()
- var fullURL = baseURL + '/api/v3/projects/' + $('#snippetExportModalProjects').val() + '/snippets?access_token=' + accesstoken
+ var fullURL = baseURL + '/api/' + version + '/projects/' + $('#snippetExportModalProjects').val() + '/snippets?access_token=' + accesstoken
$.post(fullURL
, data
, function (ret) {
@@ -1487,7 +1493,6 @@ $('#snippetExportModalConfirm').click(function () {
var redirect = baseURL + '/' + $("#snippetExportModalProjects option[value='" + $('#snippetExportModalProjects').val() + "']").text() + '/snippets/' + ret.id
showMessageModal('<i class="fa fa-gitlab"></i> Export to Snippet', 'Export Successful!', redirect, 'View Snippet Here', true)
}
- , 'json'
)
})
diff --git a/public/views/codimd/body.ejs b/public/views/codimd/body.ejs
index b5932a61..d4f27a93 100644
--- a/public/views/codimd/body.ejs
+++ b/public/views/codimd/body.ejs
@@ -153,6 +153,7 @@
<div class="modal-body">
<input type="hidden" id="snippetImportModalAccessToken" />
<input type="hidden" id="snippetImportModalBaseURL" />
+ <input type="hidden" id="snippetImportModalVersion" />
<div class="ui-field-contain" style="display:table;margin-bottom:10px;width:100%;">
<div style="display:table-row;margin-bottom:5px;">
<label style="display:table-cell;">Project:</label>
@@ -191,6 +192,7 @@
<div class="modal-body">
<input type="hidden" id="snippetExportModalAccessToken" />
<input type="hidden" id="snippetExportModalBaseURL" />
+ <input type="hidden" id="snippetExportModalVersion" />
<div class="ui-field-contain" style="display:table;margin-bottom:10px;width:100%;">
<div style="display:table-row;margin-bottom:5px;">
<label style="display:table-cell;">Title:</label>
diff --git a/public/views/index/body.ejs b/public/views/index/body.ejs
index 29fa3181..53dbf2a2 100644
--- a/public/views/index/body.ejs
+++ b/public/views/index/body.ejs
@@ -152,7 +152,7 @@
&copy; 2018 <a href="https://hackmd.io">CodiMD</a> | <a href="<%- url %>/s/release-notes" target="_blank"><%= __('Releases') %></a><% if(privacyStatement) { %> | <a href="<%- url %>/s/privacy" target="_blank"><%= __('Privacy') %></a><% } %><% if(termsOfUse) { %> | <a href="<%- url %>/s/terms-of-use" target="_blank"><%= __('Terms of Use') %></a><% } %>
</p>
<h6 class="social-foot">
- <%- __('Follow us on %s and %s.', '<a href="https://github.com/hackmdio/CodiMD" target="_blank"><i class="fa fa-github"></i> GitHub</a>, <a href="https://twitter.com/hackmdio" target="_blank"><i class="fa fa-twitter"></i> Twitter</a>', '<a href="https://www.facebook.com/hackmdio" target="_blank"><i class="fa fa-facebook-square"></i> Facebook</a>') %>
+ <%- __('Follow us on %s and %s.', '<a href="https://github.com/hackmdio/CodiMD" target="_blank"><i class="fa fa-github"></i> GitHub</a>, <a href="https://riot.im/app/#/room/#codimd:matrix.org" target="_blank"><i class="fa fa-comments"></i> Riot</a>') %>
</h6>
</div>
</div>
diff --git a/yarn.lock b/yarn.lock
index 796c2bd3..f3d2eda6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4698,9 +4698,9 @@ markdown-it@^8.2.2:
mdurl "^1.0.1"
uc.micro "^1.0.3"
-markdown-pdf@^8.0.0:
- version "8.1.1"
- resolved "https://registry.yarnpkg.com/markdown-pdf/-/markdown-pdf-8.1.1.tgz#25c025d4f4f91869ac0f3f6fd7f7d32237669438"
+markdown-pdf@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/markdown-pdf/-/markdown-pdf-9.0.0.tgz#d699f29c3b6c41da4b9a2ec7d09ea8895daef146"
dependencies:
commander "^2.2.0"
duplexer "^0.1.1"