diff --git a/package-lock.json b/package-lock.json index 0cee752..64ef200 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,10 @@ "version": "0.8.10", "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" @@ -1900,6 +1902,162 @@ "version": "0.2.3", "license": "MIT" }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz", + "integrity": "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.2.tgz", + "integrity": "sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==", + "license": "MIT", + "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.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "license": "MIT", + "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.12" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz", + "integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==", + "license": "MIT", + "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.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", + "integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==", + "license": "MIT", + "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.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz", + "integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==", + "license": "MIT", + "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/lr": "^1.0.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.1.tgz", + "integrity": "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.4.tgz", + "integrity": "sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.35.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.6.0.tgz", + "integrity": "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz", + "integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.39.15", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.15.tgz", + "integrity": "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.5.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "license": "CC0-1.0" @@ -2884,6 +3042,84 @@ "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.5.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.1.tgz", + "integrity": "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==", + "license": "MIT" + }, + "node_modules/@lezer/css": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.1.tgz", + "integrity": "sha512-PYAKeUVBo3HFThruRyp/iK91SwiZJnzXh8QzkQlwijB5y+N5iB28+iLk78o2zmKqqV0uolNhCwFqB8LA7b0Svg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.8.tgz", + "integrity": "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.3.tgz", + "integrity": "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.4.tgz", + "integrity": "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", @@ -2939,6 +3175,12 @@ "node": ">=10" } }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "license": "MIT" + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "license": "MIT", @@ -6029,9 +6271,20 @@ } }, "node_modules/codemirror": { - "version": "5.61.0", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", "license": "MIT", - "peer": true + "peer": true, + "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", @@ -6371,6 +6624,12 @@ "buffer": "^5.1.0" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "license": "MIT" + }, "node_modules/cross-dirname": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", @@ -14444,14 +14703,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", @@ -16108,6 +16359,12 @@ "webpack": "^5.0.0" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/stylehacks": { "version": "5.0.1", "license": "MIT", @@ -17297,6 +17554,12 @@ "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==", + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "license": "MIT", diff --git a/package.json b/package.json index c596c72..8757cb0 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,10 @@ } }, "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", @@ -148,7 +151,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