From f4dc57e5acce238243048fc09cc680a7c69059cf Mon Sep 17 00:00:00 2001 From: Anton Reshetov Date: Sat, 14 Mar 2020 18:57:04 +0300 Subject: [PATCH] feat: add mardown syntax highlight --- package.json | 2 + .../components/editor/MarkdownPreview.vue | 49 +++++++++- static/css/hljs/atom-one-dark.css | 96 +++++++++++++++++++ static/css/hljs/atom-one-light.css | 96 +++++++++++++++++++ yarn.lock | 43 +++++++++ 5 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 static/css/hljs/atom-one-dark.css create mode 100644 static/css/hljs/atom-one-light.css diff --git a/package.json b/package.json index 4505ed6..5a17d74 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "emmet-monaco-es": "^4.3.3", "feather-icons": "^4.25.0", "fs-extra": "^8.1.0", + "highlight.js": "^9.18.1", "interactjs": "^1.8.0-alpha.6", "junk": "^3.1.0", "lodash-es": "^4.17.15", @@ -86,6 +87,7 @@ "nedb": "^1.8.0", "perfect-scrollbar": "^1.4.0", "popper.js": "^1.16.0", + "prismjs": "^1.19.0", "rimraf": "^3.0.2", "sanitize-html": "^1.21.1", "shortid": "^2.2.15", diff --git a/src/renderer/components/editor/MarkdownPreview.vue b/src/renderer/components/editor/MarkdownPreview.vue index bfbec07..02bc5d8 100644 --- a/src/renderer/components/editor/MarkdownPreview.vue +++ b/src/renderer/components/editor/MarkdownPreview.vue @@ -13,6 +13,9 @@ import mila from 'markdown-it-link-attributes' import { shell } from 'electron' import PerfectScrollbar from 'perfect-scrollbar' import sanitizeHtml from 'sanitize-html' +import hljs from 'highlight.js' +import fs from 'fs' +import { mapState } from 'vuex' export default { name: 'MarkdownPreview', @@ -36,6 +39,7 @@ export default { }, computed: { + ...mapState(['app']), result () { const raw = this.md.render(this.model) return sanitizeHtml(raw, { @@ -49,7 +53,8 @@ export default { 'name', 'src', 'target', - 'width' + 'width', + 'class' ] } }) @@ -72,6 +77,9 @@ export default { watch: { model () { this.setLinksClass() + }, + 'app.theme' (v) { + this.toggleHljsStyles(v) } }, @@ -93,13 +101,31 @@ export default { init () { this.md = new MarkdownIt({ html: true, - langPrefix: 'language-' + langPrefix: 'language-', + highlight (str, lang) { + if (lang && hljs.getLanguage(lang)) { + try { + return `
${
+                hljs.highlight(lang, str, true).value
+              }
` + } catch (err) { + console.log(err) + } + } + return `
${MarkdownIt().utils.escapeHtml(
+            str
+          )}
` + } }) this.md.use(mila, { attrs: { class: 'external' } }) + + this.app.theme === 'dark' + ? this.toggleHljsStyles('dark') + : this.toggleHljsStyles('light') }, // Добавляем класс ссылкам которые были созданы как HTML setLinksClass () { @@ -116,6 +142,25 @@ export default { }, initPS () { this.ps = new PerfectScrollbar(this.$refs.preview) + }, + toggleHljsStyles (theme) { + const dark = fs.readFileSync( + __static + '/css/hljs/atom-one-dark.css', + 'utf8' + ) + const light = fs.readFileSync( + __static + '/css/hljs/atom-one-light.css', + 'utf8' + ) + const style = document.createElement('style') + style.setAttribute('name', 'hljs') + + const existStyle = document.querySelector('style[name="hljs"]') + + if (existStyle) existStyle.remove() + + theme === 'dark' ? (style.innerHTML = dark) : (style.innerHTML = light) + document.head.appendChild(style) } } } diff --git a/static/css/hljs/atom-one-dark.css b/static/css/hljs/atom-one-dark.css new file mode 100644 index 0000000..1616aaf --- /dev/null +++ b/static/css/hljs/atom-one-dark.css @@ -0,0 +1,96 @@ +/* + +Atom One Dark by Daniel Gamage +Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax + +base: #282c34 +mono-1: #abb2bf +mono-2: #818896 +mono-3: #5c6370 +hue-1: #56b6c2 +hue-2: #61aeee +hue-3: #c678dd +hue-4: #98c379 +hue-5: #e06c75 +hue-5-2: #be5046 +hue-6: #d19a66 +hue-6-2: #e6c07b + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #abb2bf; + background: #282c34; +} + +.hljs-comment, +.hljs-quote { + color: #5c6370; + font-style: italic; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: #c678dd; +} + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: #e06c75; +} + +.hljs-literal { + color: #56b6c2; +} + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: #98c379; +} + +.hljs-built_in, +.hljs-class .hljs-title { + color: #e6c07b; +} + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-type, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: #d19a66; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id, +.hljs-title { + color: #61aeee; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/static/css/hljs/atom-one-light.css b/static/css/hljs/atom-one-light.css new file mode 100644 index 0000000..d5bd1d2 --- /dev/null +++ b/static/css/hljs/atom-one-light.css @@ -0,0 +1,96 @@ +/* + +Atom One Light by Daniel Gamage +Original One Light Syntax theme from https://github.com/atom/one-light-syntax + +base: #fafafa +mono-1: #383a42 +mono-2: #686b77 +mono-3: #a0a1a7 +hue-1: #0184bb +hue-2: #4078f2 +hue-3: #a626a4 +hue-4: #50a14f +hue-5: #e45649 +hue-5-2: #c91243 +hue-6: #986801 +hue-6-2: #c18401 + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #383a42; + background: #fafafa; +} + +.hljs-comment, +.hljs-quote { + color: #a0a1a7; + font-style: italic; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: #a626a4; +} + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: #e45649; +} + +.hljs-literal { + color: #0184bb; +} + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: #50a14f; +} + +.hljs-built_in, +.hljs-class .hljs-title { + color: #c18401; +} + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-type, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: #986801; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id, +.hljs-title { + color: #4078f2; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/yarn.lock b/yarn.lock index 3d554e5..0ca573a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2288,6 +2288,15 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= +clipboard@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376" + integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -2973,6 +2982,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -4484,6 +4498,13 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -4654,6 +4675,11 @@ helper-js@^1.0.47, helper-js@^1.2.0, helper-js@^1.3.7, helper-js@^1.4.5: resolved "https://registry.yarnpkg.com/helper-js/-/helper-js-1.4.12.tgz#ae66e145e56963189227047d4c69ecef4f61f068" integrity sha512-LcZ/z/eA/f/OMea9XYVBLRYv3jYQKDOQyI5m6uB80DyWwte4OLGFewYtguoDu+APFQKVoWs++ODGSYwzZmTSkg== +highlight.js@^9.18.1: + version "9.18.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.1.tgz#ed21aa001fe6252bb10a3d76d47573c6539fe13c" + integrity sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg== + highlight.js@^9.3.0: version "9.17.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.17.1.tgz#14a4eded23fd314b05886758bb906e39dd627f9a" @@ -7437,6 +7463,13 @@ pretty-error@^2.0.2: renderkid "^2.0.1" utila "~0.4" +prismjs@^1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.19.0.tgz#713afbd45c3baca4b321569f2df39e17e729d4dc" + integrity sha512-IVFtbW9mCWm9eOIaEkNyo2Vl4NnEifis2GQ7/MLRG5TQe6t+4Sj9J5QWI9i3v+SS43uZBlCAOn+zYTVYQcPXJw== + optionalDependencies: + clipboard "^2.0.0" + private@^0.1.6, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -8177,6 +8210,11 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + selfsigned@^1.10.7: version "1.10.7" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" @@ -8975,6 +9013,11 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + title-case@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/title-case/-/title-case-2.1.1.tgz#3e127216da58d2bc5becf137ab91dae3a7cd8faa"