Moved client-side markdown rendering to this server
This commit is contained in:
Generated
+89
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "news-server",
|
"name": "news-server",
|
||||||
"version": "1.3.1",
|
"version": "1.4.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "news-server",
|
"name": "news-server",
|
||||||
"version": "1.3.1",
|
"version": "1.4.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"mariadb": "^2.5.4",
|
"mariadb": "^2.5.4",
|
||||||
|
"markdown-it": "^12.3.0",
|
||||||
"sequelize": "^6.6.5"
|
"sequelize": "^6.6.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -120,6 +121,11 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
|
},
|
||||||
"node_modules/array-flatten": {
|
"node_modules/array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
@@ -567,6 +573,14 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/entities": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/escape-goat": {
|
"node_modules/escape-goat": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
|
||||||
@@ -1032,6 +1046,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/linkify-it": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"uc.micro": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
@@ -1149,6 +1171,26 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/markdown-it": {
|
||||||
|
"version": "12.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.0.tgz",
|
||||||
|
"integrity": "sha512-T345UZZ6ejQWTjG6PSEHplzNy5m4kF6zvUpHVDv8Snl/pEU0OxIK0jGg8YLVNwJvT8E0YJC7/2UvssJDk/wQCQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"argparse": "^2.0.1",
|
||||||
|
"entities": "~2.1.0",
|
||||||
|
"linkify-it": "^3.0.1",
|
||||||
|
"mdurl": "^1.0.1",
|
||||||
|
"uc.micro": "^1.0.5"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"markdown-it": "bin/markdown-it.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mdurl": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||||
|
},
|
||||||
"node_modules/media-typer": {
|
"node_modules/media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
@@ -1903,6 +1945,11 @@
|
|||||||
"is-typedarray": "^1.0.0"
|
"is-typedarray": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uc.micro": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||||
|
},
|
||||||
"node_modules/undefsafe": {
|
"node_modules/undefsafe": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
||||||
@@ -2136,6 +2183,11 @@
|
|||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"argparse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
|
},
|
||||||
"array-flatten": {
|
"array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
@@ -2492,6 +2544,11 @@
|
|||||||
"once": "^1.4.0"
|
"once": "^1.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"entities": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
|
||||||
|
},
|
||||||
"escape-goat": {
|
"escape-goat": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
|
||||||
@@ -2859,6 +2916,14 @@
|
|||||||
"package-json": "^6.3.0"
|
"package-json": "^6.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"linkify-it": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
|
||||||
|
"requires": {
|
||||||
|
"uc.micro": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
@@ -2959,6 +3024,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"markdown-it": {
|
||||||
|
"version": "12.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.0.tgz",
|
||||||
|
"integrity": "sha512-T345UZZ6ejQWTjG6PSEHplzNy5m4kF6zvUpHVDv8Snl/pEU0OxIK0jGg8YLVNwJvT8E0YJC7/2UvssJDk/wQCQ==",
|
||||||
|
"requires": {
|
||||||
|
"argparse": "^2.0.1",
|
||||||
|
"entities": "~2.1.0",
|
||||||
|
"linkify-it": "^3.0.1",
|
||||||
|
"mdurl": "^1.0.1",
|
||||||
|
"uc.micro": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdurl": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
|
||||||
|
},
|
||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
@@ -3519,6 +3601,11 @@
|
|||||||
"is-typedarray": "^1.0.0"
|
"is-typedarray": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"uc.micro": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||||
|
},
|
||||||
"undefsafe": {
|
"undefsafe": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz",
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "news-server",
|
"name": "news-server",
|
||||||
"version": "1.3.1",
|
"version": "1.4.0",
|
||||||
"description": "An API centric news server. Uses Sequelize and mariaDB by default.",
|
"description": "An API centric news server. Uses Sequelize and mariaDB by default.",
|
||||||
"main": "server/server.js",
|
"main": "server/server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"mariadb": "^2.5.4",
|
"mariadb": "^2.5.4",
|
||||||
|
"markdown-it": "^12.3.0",
|
||||||
"sequelize": "^6.6.5"
|
"sequelize": "^6.6.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ const articles = sequelize.define('articles', {
|
|||||||
defaultValue: ''
|
defaultValue: ''
|
||||||
},
|
},
|
||||||
|
|
||||||
|
rendered: {
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
edits: {
|
edits: {
|
||||||
type: Sequelize.INTEGER(11),
|
type: Sequelize.INTEGER(11),
|
||||||
defaultValue: 0
|
defaultValue: 0
|
||||||
|
|||||||
@@ -2,6 +2,14 @@ const Sequelize = require('sequelize');
|
|||||||
const sequelize = require('..');
|
const sequelize = require('..');
|
||||||
|
|
||||||
const revisions = sequelize.define('revisions', {
|
const revisions = sequelize.define('revisions', {
|
||||||
|
index: {
|
||||||
|
type: Sequelize.INTEGER(11),
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
|
||||||
title: {
|
title: {
|
||||||
type: Sequelize.TEXT,
|
type: Sequelize.TEXT,
|
||||||
defaultValue: ''
|
defaultValue: ''
|
||||||
@@ -17,6 +25,11 @@ const revisions = sequelize.define('revisions', {
|
|||||||
defaultValue: ''
|
defaultValue: ''
|
||||||
},
|
},
|
||||||
|
|
||||||
|
rendered: {
|
||||||
|
type: Sequelize.TEXT,
|
||||||
|
defaultValue: ''
|
||||||
|
},
|
||||||
|
|
||||||
originalIndex: {
|
originalIndex: {
|
||||||
type: Sequelize.INTEGER(11),
|
type: Sequelize.INTEGER(11),
|
||||||
default: null
|
default: null
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const { Op } = require('sequelize');
|
const { Op } = require('sequelize');
|
||||||
const { articles, revisions } = require('../database/models');
|
const { articles, revisions } = require('../database/models');
|
||||||
|
const markdownIt = require('markdown-it')();
|
||||||
|
|
||||||
const route = async (req, res) => {
|
const route = async (req, res) => {
|
||||||
//get the existing record
|
//get the existing record
|
||||||
@@ -20,6 +21,7 @@ const route = async (req, res) => {
|
|||||||
title: record.title,
|
title: record.title,
|
||||||
author: record.author,
|
author: record.author,
|
||||||
body: record.body,
|
body: record.body,
|
||||||
|
rendered: record.rendered,
|
||||||
originalIndex: record.index
|
originalIndex: record.index
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -28,6 +30,7 @@ const route = async (req, res) => {
|
|||||||
title: req.body.title || record.title,
|
title: req.body.title || record.title,
|
||||||
author: req.body.author || record.author,
|
author: req.body.author || record.author,
|
||||||
body: req.body.body || record.body,
|
body: req.body.body || record.body,
|
||||||
|
rendered: markdownIt.render(req.body.body) || record.rendered,
|
||||||
edits: record.edits + 1
|
edits: record.edits + 1
|
||||||
}, {
|
}, {
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const { articles } = require('../database/models');
|
const { articles } = require('../database/models');
|
||||||
|
const markdownIt = require('markdown-it')();
|
||||||
|
|
||||||
const route = async (req, res) => {
|
const route = async (req, res) => {
|
||||||
//check for missing data
|
//check for missing data
|
||||||
@@ -18,7 +19,8 @@ const route = async (req, res) => {
|
|||||||
const [instance, created] = await articles.upsert({
|
const [instance, created] = await articles.upsert({
|
||||||
title: req.body.title,
|
title: req.body.title,
|
||||||
author: req.body.author,
|
author: req.body.author,
|
||||||
body: req.body.body
|
body: req.body.body,
|
||||||
|
rendered: markdownIt.render(req.body.body),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!created) {
|
if (!created) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const query = (ascending, metadataOnly) => async (req, res) => {
|
|||||||
if (req.params.id && typeof(parseInt(req.params.id)) === 'number') {
|
if (req.params.id && typeof(parseInt(req.params.id)) === 'number') {
|
||||||
const result = await articles.findOne({
|
const result = await articles.findOne({
|
||||||
attributes: [
|
attributes: [
|
||||||
'index', 'title', 'author', 'edits', 'createdAt', 'updatedAt', ...(!metadataOnly ? ['body'] : [])
|
'index', 'title', 'author', 'edits', 'createdAt', 'updatedAt', ...(!metadataOnly ? ['body', 'rendered'] : [])
|
||||||
],
|
],
|
||||||
where: {
|
where: {
|
||||||
index: {
|
index: {
|
||||||
@@ -24,7 +24,7 @@ const query = (ascending, metadataOnly) => async (req, res) => {
|
|||||||
else {
|
else {
|
||||||
const result = await articles.findAndCountAll({
|
const result = await articles.findAndCountAll({
|
||||||
attributes: [
|
attributes: [
|
||||||
'index', 'title', 'author', 'edits', 'createdAt', 'updatedAt', ...(!metadataOnly ? ['body'] : [])
|
'index', 'title', 'author', 'edits', 'createdAt', 'updatedAt', ...(!metadataOnly ? ['body', 'rendered'] : [])
|
||||||
],
|
],
|
||||||
order: [
|
order: [
|
||||||
['index', ascending ? 'ASC' : 'DESC']
|
['index', ascending ? 'ASC' : 'DESC']
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const route = async (req, res) => {
|
|||||||
title: record.title,
|
title: record.title,
|
||||||
author: record.author,
|
author: record.author,
|
||||||
body: record.body,
|
body: record.body,
|
||||||
|
rendered: record.rendered,
|
||||||
originalIndex: record.index
|
originalIndex: record.index
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,48 @@ app.get('*', (req, res) => {
|
|||||||
server.listen(process.env.WEB_PORT || 3100, async (err) => {
|
server.listen(process.env.WEB_PORT || 3100, async (err) => {
|
||||||
await database.sync();
|
await database.sync();
|
||||||
console.log(`listening to localhost:${process.env.WEB_PORT || 3100}`);
|
console.log(`listening to localhost:${process.env.WEB_PORT || 3100}`);
|
||||||
|
|
||||||
|
//parse the unrendered data from the database
|
||||||
|
const markdownIt = require('markdown-it')();
|
||||||
|
const { articles, revisions } = require('./database/models');
|
||||||
|
|
||||||
|
const missingArticles = await articles.findAll({
|
||||||
|
where: {
|
||||||
|
rendered: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const missingRevisions = await revisions.findAll({
|
||||||
|
where: {
|
||||||
|
rendered: ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
missingArticles.map(async ma => {
|
||||||
|
ma.update({
|
||||||
|
rendered: markdownIt.render(ma.body)
|
||||||
|
}, {
|
||||||
|
where: {
|
||||||
|
index: ma.index
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(result => {if (result.length > 0) console.log('Rendered articles in HTML'); })
|
||||||
|
;
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
missingRevisions.map(async mr => {
|
||||||
|
mr.update({
|
||||||
|
rendered: markdownIt.render(mr.body)
|
||||||
|
}, {
|
||||||
|
where: {
|
||||||
|
index: mr.index
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then(result => {if (result.length > 0) console.log('Rendered revisions in HTML'); })
|
||||||
|
;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE articles ADD COLUMN rendered TEXT DEFAULT "" AFTER body;
|
||||||
|
|
||||||
|
ALTER TABLE revisions ADD COLUMN rendered TEXT DEFAULT "" AFTER body;
|
||||||
|
|
||||||
Reference in New Issue
Block a user