diff --git a/controllers/utilsController.js b/controllers/utilsController.js
index 972ee75..3794829 100644
--- a/controllers/utilsController.js
+++ b/controllers/utilsController.js
@@ -1,6 +1,7 @@
const { promisify } = require('util')
const fetch = require('node-fetch')
const ffmpeg = require('fluent-ffmpeg')
+const MarkdownIt = require('markdown-it')
const path = require('path')
const sharp = require('sharp')
const si = require('systeminformation')
@@ -25,6 +26,15 @@ const self = {
maxSize: (parseInt(config.uploads.scan.maxSize) * 1e6) || null,
passthrough: config.uploads.scan.clamPassthrough
},
+ md: {
+ instance: new MarkdownIt({
+ // https://markdown-it.github.io/markdown-it/#MarkdownIt.new
+ html: false,
+ breaks: true,
+ linkify: true
+ }),
+ defaultRenderers: {}
+ },
gitHash: null,
idSet: null,
@@ -45,6 +55,22 @@ const self = {
timezoneOffset: new Date().getTimezoneOffset()
}
+// Remember old renderer, if overridden, or proxy to default renderer
+self.md.defaultRenderers.link_open = self.md.instance.renderer.rules.link_open || function (tokens, idx, options, env, that) {
+ return that.renderToken(tokens, idx, options)
+}
+
+// Add target="_blank" to URLs if applicable
+self.md.instance.renderer.rules.link_open = function (tokens, idx, options, env, that) {
+ const aIndex = tokens[idx].attrIndex('target')
+ if (aIndex < 0) {
+ tokens[idx].attrPush(['target', '_blank'])
+ } else {
+ tokens[idx].attrs[aIndex][1] = '_blank'
+ }
+ return self.md.defaultRenderers.link_open(tokens, idx, options, env, that)
+}
+
const statsData = {
system: {
title: 'System',
diff --git a/package.json b/package.json
index bdd90d2..add801b 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"helmet": "~5.0.2",
"jszip": "~3.9.1",
"knex": "~0.21.21",
+ "markdown-it": "~13.0.1",
"multer": "~1.4.4",
"node-fetch": "~2.6.7",
"nunjucks": "~3.2.3",
diff --git a/routes/album.js b/routes/album.js
index f1bc8c9..85b03c9 100644
--- a/routes/album.js
+++ b/routes/album.js
@@ -76,6 +76,7 @@ routes.get('/a/:identifier', async (req, res, next) => {
: `api/album/zip/${album.identifier}?v=${album.editedAt}`
album.url = `a/${album.identifier}`
+ album.description = utils.md.instance.render(album.description)
return res.render('album', {
config,
diff --git a/views/album.njk b/views/album.njk
index e3795e2..c80ca54 100644
--- a/views/album.njk
+++ b/views/album.njk
@@ -97,8 +97,8 @@
{% if album.description -%}
-
- {{ album.description | nl2br | safe }}
+
+ {{ album.description | safe }}
{%- endif %}
diff --git a/yarn.lock b/yarn.lock
index 9924479..c1456da 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1925,6 +1925,11 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+entities@~3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
+ integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
+
env-paths@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
@@ -3931,6 +3936,13 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+linkify-it@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
+ integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
+ dependencies:
+ uc.micro "^1.0.1"
+
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -4083,6 +4095,17 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
+markdown-it@~13.0.1:
+ version "13.0.1"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
+ integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
+ dependencies:
+ argparse "^2.0.1"
+ entities "~3.0.1"
+ linkify-it "^4.0.1"
+ mdurl "^1.0.1"
+ uc.micro "^1.0.5"
+
matchdep@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"
@@ -4103,6 +4126,11 @@ mdn-data@2.0.14:
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+mdurl@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
+ integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
+
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@@ -6870,6 +6898,11 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+uc.micro@^1.0.1, uc.micro@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
+ integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
+
unbox-primitive@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"