support markdown in descriptions

also convert html descriptions from Audible and iTunes to markdown
This commit is contained in:
MxMarx 2023-09-29 17:48:44 -07:00
parent ed82a5aa19
commit 41b685d118
6 changed files with 42 additions and 8 deletions

View file

@ -125,7 +125,7 @@
</div> </div>
<div class="my-4 max-w-2xl"> <div class="my-4 max-w-2xl">
<p class="text-base text-gray-100 whitespace-pre-line">{{ description }}</p> <div class="text-base text-gray-100 default-style" v-html="description" />
</div> </div>
<div v-if="invalidAudioFiles.length" class="bg-error border-red-800 shadow-md p-4"> <div v-if="invalidAudioFiles.length" class="bg-error border-red-800 shadow-md p-4">
@ -153,6 +153,8 @@
</template> </template>
<script> <script>
import { marked } from '@/static/libs/marked/index.js'
export default { export default {
async asyncData({ store, params, app, redirect, route }) { async asyncData({ store, params, app, redirect, route }) {
if (!store.state.user.user) { if (!store.state.user.user) {
@ -323,7 +325,7 @@ export default {
return this.media.audioFile return this.media.audioFile
}, },
description() { description() {
return this.mediaMetadata.description || '' return marked(this.mediaMetadata.description || '')
}, },
userMediaProgress() { userMediaProgress() {
if (this.isMusic) return null if (this.isMusic) return null

27
package-lock.json generated
View file

@ -18,6 +18,7 @@
"sequelize": "^6.32.1", "sequelize": "^6.32.1",
"socket.io": "^4.5.4", "socket.io": "^4.5.4",
"sqlite3": "^5.1.6", "sqlite3": "^5.1.6",
"turndown": "^7.1.2",
"xml2js": "^0.5.0" "xml2js": "^0.5.0"
}, },
"bin": { "bin": {
@ -641,6 +642,11 @@
"url": "https://github.com/fb55/domhandler?sponsor=1" "url": "https://github.com/fb55/domhandler?sponsor=1"
} }
}, },
"node_modules/domino": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
},
"node_modules/domutils": { "node_modules/domutils": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
@ -2517,6 +2523,14 @@
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
}, },
"node_modules/turndown": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
"integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
"dependencies": {
"domino": "^2.1.6"
}
},
"node_modules/type-is": { "node_modules/type-is": {
"version": "1.6.18", "version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@ -3167,6 +3181,11 @@
"domelementtype": "^2.3.0" "domelementtype": "^2.3.0"
} }
}, },
"domino": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
},
"domutils": { "domutils": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
@ -4539,6 +4558,14 @@
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
}, },
"turndown": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
"integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
"requires": {
"domino": "^2.1.6"
}
},
"type-is": { "type-is": {
"version": "1.6.18", "version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",

View file

@ -39,6 +39,7 @@
"sequelize": "^6.32.1", "sequelize": "^6.32.1",
"socket.io": "^4.5.4", "socket.io": "^4.5.4",
"sqlite3": "^5.1.6", "sqlite3": "^5.1.6",
"turndown": "^7.1.2",
"xml2js": "^0.5.0" "xml2js": "^0.5.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,5 +1,6 @@
const axios = require('axios') const axios = require('axios')
const htmlSanitizer = require('../utils/htmlSanitizer') const TurndownService = require('turndown')
var turndownService = new TurndownService()
const Logger = require('../Logger') const Logger = require('../Logger')
class Audible { class Audible {
@ -45,7 +46,7 @@ class Audible {
narrator: narrators ? narrators.map(({ name }) => name).join(', ') : null, narrator: narrators ? narrators.map(({ name }) => name).join(', ') : null,
publisher: publisherName, publisher: publisherName,
publishedYear: releaseDate ? releaseDate.split('-')[0] : null, publishedYear: releaseDate ? releaseDate.split('-')[0] : null,
description: summary ? htmlSanitizer.stripAllTags(summary) : null, description: summary ? turndownService.turndown(summary) : null,
cover: image, cover: image,
asin, asin,
genres: genresFiltered.length ? genresFiltered : null, genres: genresFiltered.length ? genresFiltered : null,

View file

@ -1,6 +1,8 @@
const axios = require('axios') const axios = require('axios')
const Logger = require('../Logger') const Logger = require('../Logger')
const htmlSanitizer = require('../utils/htmlSanitizer') const htmlSanitizer = require('../utils/htmlSanitizer')
const TurndownService = require('turndown')
var turndownService = new TurndownService()
class iTunes { class iTunes {
constructor() { } constructor() { }
@ -69,7 +71,7 @@ class iTunes {
artistId: data.artistId, artistId: data.artistId,
title: data.collectionName, title: data.collectionName,
author, author,
description: htmlSanitizer.stripAllTags(data.description || ''), description: turndownService.turndown(data.description || ''),
publishedYear: data.releaseDate ? data.releaseDate.split('-')[0] : null, publishedYear: data.releaseDate ? data.releaseDate.split('-')[0] : null,
genres: data.primaryGenreName ? [data.primaryGenreName] : null, genres: data.primaryGenreName ? [data.primaryGenreName] : null,
cover: this.getCoverArtwork(data) cover: this.getCoverArtwork(data)

View file

@ -1,5 +1,6 @@
const { xmlToJSON } = require('../index') const { xmlToJSON } = require('../index')
const htmlSanitizer = require('../htmlSanitizer') const TurndownService = require('turndown')
var turndownService = new TurndownService()
function parseCreators(metadata) { function parseCreators(metadata) {
if (!metadata['dc:creator']) return null if (!metadata['dc:creator']) return null
@ -87,7 +88,7 @@ function fetchDescription(metadata) {
// check if description is HTML or plain text. only plain text allowed // check if description is HTML or plain text. only plain text allowed
// calibre stores < and > as &lt; and &gt; // calibre stores < and > as &lt; and &gt;
description = description.replace(/&lt;/g, '<').replace(/&gt;/g, '>') description = description.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
return htmlSanitizer.stripAllTags(description) return turndownService.turndown(description)
} }
function fetchGenres(metadata) { function fetchGenres(metadata) {