diff --git a/package-lock.json b/package-lock.json index e9ab63c..5f0375e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,18 @@ { "name": "panwriter", - "version": "0.8.6", + "version": "0.8.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "panwriter", - "version": "0.8.6", + "version": "0.8.7", "hasInstallScript": true, "dependencies": { - "codemirror": "^5.61.0", + "@codemirror/lang-markdown": "^6.2.5", + "@codemirror/lang-yaml": "^6.1.1", + "@codemirror/language": "^6.10.2", + "codemirror": "^6.0.1", "electron-updater": "^4.6.1", "fix-path": "^3.0.0", "js-yaml": "^4.1.0", @@ -29,7 +32,6 @@ "markdown-it-texmath": "^0.8.0", "pagedjs": "0.1.43", "react": "^18.2.0", - "react-codemirror2": "^7.2.1", "react-color": "^2.19.3", "react-dom": "^18.2.0", "react-scripts": "^5.0.1" @@ -1896,6 +1898,151 @@ "version": "0.2.3", "license": "MIT" }, + "node_modules/@codemirror/autocomplete": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz", + "integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz", + "integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz", + "integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", + "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz", + "integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz", + "integrity": "sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.1.tgz", + "integrity": "sha512-HV2NzbK9bbVnjWxwObuZh5FuPCowx51mEfoFT9y3y+M37fA3+pbxx4I7uePuygFzDsAmCTwQSc/kXh/flab4uw==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz", + "integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz", + "integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" + }, + "node_modules/@codemirror/view": { + "version": "6.32.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.32.0.tgz", + "integrity": "sha512-AgVNvED2QTsZp5e3syoHLsrWtwJFYWdx1Vr/m3f4h1ATQz0ax60CfXF3Htdmk69k2MlYZw8gXesnQdHtzyVmAw==", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "license": "CC0-1.0" @@ -2646,6 +2793,76 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" + }, + "node_modules/@lezer/css": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz", + "integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz", + "integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.4.17", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz", + "integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.3.0.tgz", + "integrity": "sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==", + "dependencies": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", + "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, "node_modules/@malept/cross-spawn-promise": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", @@ -5542,8 +5759,18 @@ } }, "node_modules/codemirror": { - "version": "5.61.0", - "license": "MIT" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } }, "node_modules/collect-v8-coverage": { "version": "1.0.1", @@ -5977,6 +6204,11 @@ "node": ">= 10" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "license": "MIT", @@ -13506,14 +13738,6 @@ "version": "0.13.9", "license": "MIT" }, - "node_modules/react-codemirror2": { - "version": "7.2.1", - "license": "MIT", - "peerDependencies": { - "codemirror": "5.x", - "react": ">=15.5 <=16.x" - } - }, "node_modules/react-color": { "version": "2.19.3", "license": "MIT", @@ -15101,6 +15325,11 @@ "webpack": "^5.0.0" } }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" + }, "node_modules/stylehacks": { "version": "5.0.1", "license": "MIT", @@ -16110,6 +16339,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "license": "MIT", diff --git a/package.json b/package.json index 3e79ed4..cc6cdf6 100644 --- a/package.json +++ b/package.json @@ -114,13 +114,19 @@ "target": [ { "target": "AppImage", - "arch": ["x64", "arm64"] + "arch": [ + "x64", + "arm64" + ] } ] } }, "dependencies": { - "codemirror": "^5.61.0", + "@codemirror/lang-markdown": "^6.2.5", + "@codemirror/lang-yaml": "^6.1.1", + "@codemirror/language": "^6.10.2", + "codemirror": "^6.0.1", "electron-updater": "^4.6.1", "fix-path": "^3.0.0", "js-yaml": "^4.1.0", @@ -140,7 +146,6 @@ "markdown-it-texmath": "^0.8.0", "pagedjs": "0.1.43", "react": "^18.2.0", - "react-codemirror2": "^7.2.1", "react-color": "^2.19.3", "react-dom": "^18.2.0", "react-scripts": "^5.0.1" diff --git a/src/appState/appStateReducer.ts b/src/appState/appStateReducer.ts index 58c448a..e1617a8 100644 --- a/src/appState/appStateReducer.ts +++ b/src/appState/appStateReducer.ts @@ -26,13 +26,17 @@ export const appStateReducer = (state: AppState, action: Action): AppState => { } case 'setMdAndRender': { const { md } = action - const doc = { - ...state.doc, - ...parseYaml(md), - md, - fileDirty: true + if (md === state.doc.md) { + return state + } else { + const doc = { + ...state.doc, + ...parseYaml(md), + md, + fileDirty: true + } + return { ...state, doc } } - return { ...state, doc } } case 'setMetaAndRender': { const { key, value } = action diff --git a/src/components/Editor/Editor.css b/src/components/Editor/Editor.css index 0040da0..3e16570 100644 --- a/src/components/Editor/Editor.css +++ b/src/components/Editor/Editor.css @@ -1,95 +1,25 @@ -@import './codemirror.css'; /* https://github.com/codemirror/CodeMirror/blob/master/lib/codemirror.css */ - -.CodeMirror { +.cm-editor { font-family: var(--mono-font); color: var(--font-color); font-size: 17px; - line-height: 1.8em; -} -div.CodeMirror { height: 100vh; background-color: var(--background-color); } -/* Make editor resize to fit its content - * see https://codemirror.net/doc/manual.html#styling - * and https://codemirror.net/demo/resize.html - */ -.CodeMirror-scroll { - overflow-x: auto; - overflow-y: hidden; +.cm-content { + line-height: 1.8em; + padding-top: 60px !important; + padding-bottom: 50px !important; } -.CodeMirror-lines { /* div holding all the text lines */ - padding: 60px 50px 50px 50px; + +.cm-line { + padding-left: 50px !important; + padding-right: 50px !important; max-width: 40em; margin: 0 auto; } -.CodeMirror-sizer { - overflow: hidden; -} - -.CodeMirror-vscrollbar:focus { - outline: 0; -} - -.CodeMirror-dialog { - font-family: var(--system-font); - font-size: 13px; - width: 100%; - padding: 2px 50px; - box-sizing: border-box; - background: var(--overlay-transparent-background-color); - z-index: 10; - position: fixed; - bottom: 0; -} -.CodeMirror-search-field { - font-size: 13px; - width: 200px !important; - margin-left: 15px; -} -.CodeMirror-search-hint { - display: none; -} - -.CodeMirror div.CodeMirror-cursor { - border-left: 1px solid var(--cursor-color); -} - -.CodeMirror div.CodeMirror-selected { - background: var(--input-border-color); -} - -.cm-s-paper .cm-keyword { color: var(--highlight-font-color); } -.cm-s-paper .cm-atom { color: var(--highlight-font-color); } -.cm-s-paper .cm-variable { color: var(--font-color); } -.cm-s-paper .cm-variable-2 { color: var(--font-color); } -.cm-s-paper .cm-variable-3 { color: var(--font-color); } -.cm-s-paper .cm-property { color: var(--font-color); } -.cm-s-paper .cm-operator { color: var(--font-color); } -.cm-s-paper .cm-comment { color: var(--highlight-font-color); } -.cm-s-paper .cm-meta { color: var(--highlight-font-color); } -.cm-s-paper .cm-qualifier { color: var(--highlight-font-color); } -.cm-s-paper .cm-builtin { color: var(--highlight-font-color); } -.cm-s-paper .cm-quote { color: var(--highlight-font-color); } -.cm-s-paper .cm-hr { color: var(--highlight-font-color); } -.cm-s-paper .cm-def { color: var(--highlight-font-color); } -.cm-s-paper .cm-image-marker { color: var(--highlight-font-color); } - -/* HTML stuff -.cm-s-paper .cm-bracket { color: var(--highlight-font-color); } -.cm-s-paper .cm-tag { color: var(--highlight-font-color); } -.cm-s-paper .cm-attribute { color: var(--highlight-font-color); } -.cm-s-paper .cm-string { color: var(--highlight-font-color); } -.cm-s-paper .cm-string-2 { color: var(--highlight-font-color); } +/* +var(--highlight-font-color) +var(--font-color) */ - -.cm-s-paper .cm-link { - color: var(--highlight-font-color); - text-decoration: none; -} -.cm-s-paper .cm-url { - color: var(--highlight-font-color); - text-decoration: underline; -} diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index 9bf6e55..88f2fca 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -1,20 +1,17 @@ -import { countColumn, Editor as CMEditor } from 'codemirror' -import 'codemirror/addon/dialog/dialog' -import 'codemirror/addon/search/search' -import 'codemirror/addon/search/searchcursor' -import 'codemirror/addon/search/jump-to-line' -import 'codemirror/addon/mode/overlay' -import 'codemirror/mode/markdown/markdown' -import 'codemirror/mode/yaml/yaml' -import 'codemirror/mode/yaml-frontmatter/yaml-frontmatter' -import 'codemirror/addon/edit/continuelist' -import { Controlled as CodeMirror } from 'react-codemirror2' +import { indentWithTab } from '@codemirror/commands' +import { markdown, markdownLanguage } from '@codemirror/lang-markdown' +import { yamlFrontmatter } from '@codemirror/lang-yaml' +import { HighlightStyle, indentUnit, syntaxHighlighting } from '@codemirror/language' +import { EditorState, Extension } from '@codemirror/state' +import { EditorView, keymap } from '@codemirror/view' +import { tags } from '@lezer/highlight' import { AppState } from '../../appState/AppState' import { Action } from '../../appState/Action' import { registerScrollEditor, scrollPreview } from '../../renderPreview/scrolling' import './Editor.css' +import { useEffect, useRef } from 'react' interface Props { state: AppState; @@ -23,60 +20,71 @@ interface Props { export const Editor = (props: Props) => { const { state, dispatch } = props - return ( - + const { md } = state.doc + const editorDiv = useRef(null) + const editorView = useRef(null) + + useEffect(() => { + const extensions: Extension[] = [ + yamlFrontmatter({ + content: markdown({ + base: markdownLanguage, + }) + }), + syntaxHighlighting(myHighlightStyle), + EditorView.lineWrapping, + indentUnit.of(' '), // four spaces because of how numbered lists work in CommonMark + keymap.of([indentWithTab]), + EditorView.updateListener.of(update => { + const md = update.state.doc.toString() dispatch({ type: 'setMdAndRender', md }) - } - onScroll={scrollPreview} - editorDidMount={onEditorDidMount} - value={state.doc.md} - autoCursor={true} - options={codeMirrorOptions} - /> - ) -} + }), + ] + + editorView.current = new EditorView({ + parent: editorDiv.current!, + state: EditorState.create({ + extensions, + }), + }) -const codeMirrorOptions = { - mode: { - name: 'yaml-frontmatter' - , base: 'markdown' - } -, theme: 'paper' -, indentUnit: 4 // because of how numbered lists behave in CommonMark -, tabSize: 4 -, lineNumbers: false -, lineWrapping: true -, autofocus: true -, extraKeys: { - Enter: 'newlineAndIndentContinueMarkdownList' - , Tab: 'indentMore' - , 'Shift-Tab': 'indentLess' - } + return () => editorView.current?.destroy() + }, [editorDiv]) + + useEffect(() => { + if (md !== editorView.current?.state.doc.toString()) { + editorView.current?.dispatch({ changes: { + from: 0, + to: editorView.current.state.doc.length, + insert: md, + }}) + } + }, [md]) + + return
} +// to debug, use: +// import { defaultHighlightStyle } from '@codemirror/language' +// const extensions = [ syntaxHighlighting(defaultHighlightStyle), +// console.log(defaultHighlightStyle.specs, defaultHighlightStyle.specs[7].tag.toString()) +const myHighlightStyle = HighlightStyle.define([ + { tag: tags.definition(tags.propertyName), color: 'var(--highlight-font-color)' }, + { tag: tags.emphasis, fontStyle: 'italic' }, + { tag: tags.heading, color: 'var(--font-color) !important', fontWeight: 'bold' }, + { tag: tags.labelName, color: 'var(--highlight-font-color)' }, + { tag: tags.meta, color: 'var(--highlight-font-color)' }, + { tag: tags.strikethrough, textDecorationLine: 'line-through' }, + { tag: tags.strong, fontWeight: 'bold' }, + { tag: tags.url, color: 'var(--highlight-font-color)' }, +]) + + +/* const onEditorDidMount = (editor: CMEditor) => { editor.focus(); - // adapted from https://codemirror.net/demo/indentwrap.html - const charWidth = editor.defaultCharWidth() - const basePadding = 4 - // matches markdown list `-`, `+`, `*`, `1.`, `1)` and blockquote `>` markers: - // eslint-disable-next-line no-useless-escape - const listRe = /^(([-|\+|\*|\>]|\d+[\.|\)])\s+)(.*)/ - - editor.on('renderLine', (cm, line, elt) => { - const txt = line.text - const matches = txt.trim().match(listRe) - if (matches && matches[1]) { - const extraIndent = matches[1].length - const columnCount = countColumn(txt, null, cm.getOption('tabSize') || 4) - const off = (columnCount + extraIndent) * charWidth - elt.style.textIndent = '-' + off + 'px'; - elt.style.paddingLeft = (basePadding + off) + 'px'; - } - }); - editor.refresh(); + // https://codemirror.net/demo/indentwrap.html registerScrollEditor(editor); @@ -92,3 +100,4 @@ const onEditorDidMount = (editor: CMEditor) => { window.ipcApi?.on.addItalic( () => replaceSelection(s => ['_', s, '_' ].join('')) ) window.ipcApi?.on.addStrikethrough( () => replaceSelection(s => ['~~', s, '~~'].join('')) ) } +*/ diff --git a/src/components/Editor/codemirror.css b/src/components/Editor/codemirror.css deleted file mode 100644 index 5ea2d2b..0000000 --- a/src/components/Editor/codemirror.css +++ /dev/null @@ -1,350 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; - direction: ltr; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre.CodeMirror-line, -.CodeMirror pre.CodeMirror-line-like { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: transparent; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0 !important; - background: #7e7; -} -.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} -.cm-fat-cursor-mark { - background-color: rgba(20, 255, 20, 0.5); - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; -} -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; -} -@-moz-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} - -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-rulers { - position: absolute; - left: 0; right: 0; top: -50px; bottom: 0; - overflow: hidden; -} -.CodeMirror-ruler { - border-left: 1px solid #ccc; - top: 0; bottom: 0; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -.CodeMirror-composing { border-bottom: 2px solid; } - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - position: relative; - overflow: hidden; - background: white; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 50px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -50px; margin-right: -50px; - padding-bottom: 50px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; -} -.CodeMirror-sizer { - position: relative; - border-right: 50px solid transparent; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actual scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; - outline: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - min-height: 100%; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - vertical-align: top; - margin-bottom: -50px; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; -} -.CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} -.CodeMirror-gutter-wrapper ::selection { background-color: transparent } -.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre.CodeMirror-line, -.CodeMirror pre.CodeMirror-line-like { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; - -webkit-font-variant-ligatures: contextual; - font-variant-ligatures: contextual; -} -.CodeMirror-wrap pre.CodeMirror-line, -.CodeMirror-wrap pre.CodeMirror-line-like { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - padding: 0.1px; /* Force widget margins to stay inside of the container */ -} - -.CodeMirror-widget {} - -.CodeMirror-rtl pre { direction: rtl; } - -.CodeMirror-code { - outline: none; -} - -/* Force content-box sizing for the elements where we expect it */ -.CodeMirror-scroll, -.CodeMirror-sizer, -.CodeMirror-gutter, -.CodeMirror-gutters, -.CodeMirror-linenumber { - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} - -.CodeMirror-cursor { - position: absolute; - pointer-events: none; -} -.CodeMirror-measure pre { position: static; } - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -div.CodeMirror-dragcursors { - visibility: visible; -} - -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } - -.cm-searching { - background-color: #ffa; - background-color: rgba(255, 255, 0, .4); -} - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } diff --git a/src/renderPreview/scrolling.ts b/src/renderPreview/scrolling.ts index 85d3081..c120827 100644 --- a/src/renderPreview/scrolling.ts +++ b/src/renderPreview/scrolling.ts @@ -1,6 +1,7 @@ -import { Editor } from 'codemirror' import { throttle } from './throttle' +type Editor = any + let editor: Editor , editorOffset = 0 , scrollEditorFn: ((e: Event) => void) | undefined