diff --git a/package-lock.json b/package-lock.json index eb30e76..76802e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "debug": "^4.3.1", "graphql": "^15.5.0", "graphql-tools": "^7.0.2", + "highlight.js": "^10.7.2", "ioredis": "^4.25.0", "js-yaml": "^4.0.0", "marked": "^2.1.3", @@ -42,6 +43,7 @@ "@nestjs/schematics": "^7.3.1", "@nestjs/testing": "^7.6.15", "@types/express": "^4.17.8", + "@types/highlight.js": "^10.1.0", "@types/jest": "^26.0.22", "@types/marked": "^2.0.3", "@types/node": "^14.14.41", @@ -3296,6 +3298,16 @@ "@types/node": "*" } }, + "node_modules/@types/highlight.js": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-10.1.0.tgz", + "integrity": "sha512-77hF2dGBsOgnvZll1vymYiNUtqJ8cJfXPD6GG/2M0aLRc29PkvB7Au6sIDjIEFcSICBhCh2+Pyq6WSRS7LUm6A==", + "deprecated": "This is a stub types definition. highlight.js provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "highlight.js": "*" + } + }, "node_modules/@types/http-assert": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", @@ -18198,6 +18210,15 @@ "@types/node": "*" } }, + "@types/highlight.js": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-10.1.0.tgz", + "integrity": "sha512-77hF2dGBsOgnvZll1vymYiNUtqJ8cJfXPD6GG/2M0aLRc29PkvB7Au6sIDjIEFcSICBhCh2+Pyq6WSRS7LUm6A==", + "dev": true, + "requires": { + "highlight.js": "*" + } + }, "@types/http-assert": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", diff --git a/package.json b/package.json index 7a0cfdb..01f2d67 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "debug": "^4.3.1", "graphql": "^15.5.0", "graphql-tools": "^7.0.2", + "highlight.js": "^10.7.2", "ioredis": "^4.25.0", "js-yaml": "^4.0.0", "marked": "^2.1.3", @@ -55,6 +56,7 @@ "@nestjs/schematics": "^7.3.1", "@nestjs/testing": "^7.6.15", "@types/express": "^4.17.8", + "@types/highlight.js": "^10.1.0", "@types/jest": "^26.0.22", "@types/marked": "^2.0.3", "@types/node": "^14.14.41", diff --git a/src/articles/articles.resolver.ts b/src/articles/articles.resolver.ts index 6d4ca66..75cafcf 100644 --- a/src/articles/articles.resolver.ts +++ b/src/articles/articles.resolver.ts @@ -12,6 +12,7 @@ import { Article } from './entities/article.entity'; import { CreateArticleInput } from './dto/create-article.input'; import { UpdateArticleInput } from './dto/update-article.input'; import * as marked from 'marked'; +import { getLanguage, highlight } from 'highlight.js'; @Resolver(() => Article) export class ArticlesResolver { @@ -49,7 +50,22 @@ export class ArticlesResolver { @ResolveField(() => String) async html(@Parent() article: Article) { - return marked(article.content); + const tokens = marked.lexer(article.content); + const index = tokens.findIndex((token) => ['heading'].includes(token.type)); + if (index !== -1) { + tokens.splice(index, 1); + } + return marked.parser(tokens, { + gfm: true, + smartLists: true, + smartypants: true, + langPrefix: 'hljs language-', + highlight: (code, language) => { + return highlight(code, { + language: getLanguage(language) ? language : 'plaintext', + }).value; + }, + }); } @ResolveField(() => String, { nullable: true })