diff --git a/package-lock.json b/package-lock.json index 0c1e9db8..05a69ba0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,9 @@ "license": "MIT", "dependencies": { "@codemirror/lang-markdown": "^6.1.1", + "@codemirror/merge": "^6.1.2", "@codemirror/state": "^6.2.1", + "@codemirror/theme-one-dark": "^6.1.2", "@codemirror/view": "6.15.3", "@codesandbox/sandpack-react": "^2.6.7", "@lexical/clipboard": "^0.12.2", @@ -32,6 +34,8 @@ "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.6", "classnames": "^2.3.2", + "cm6-theme-basic-light": "^0.2.0", + "codemirror": "^6.0.1", "downshift": "^7.6.0", "hast-util-raw": "^8.0.0", "hast-util-sanitize": "^4.1.0", @@ -50,7 +54,6 @@ "micromark-extension-frontmatter": "1.1.0", "micromark-extension-gfm-table": "^1.0.6", "micromark-extension-mdxjs": "1.0.1", - "react-diff-view": "^3.0.3", "react-hook-form": "^7.44.2", "unidiff": "^1.0.2" }, @@ -854,11 +857,43 @@ "crelt": "^1.0.5" } }, + "node_modules/@codemirror/merge": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/merge/-/merge-6.1.2.tgz", + "integrity": "sha512-z/NQu21+w+xCT+Zq/EOREyB251AhBdWoIzcfLuzTZ4uDeiscbi0fZUJY/PM3yZ68bKZIbzLESSZMpm9mThmQ1g==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.11.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.4.tgz", + "integrity": "sha512-YoTrvjv9e8EbPs58opjZKyJ3ewFrVSUzQ/4WXlULQLSDDr1nGPJ67mMXFNNVYwdFhybzhrzrtqgHmtpJwIF+8g==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, "node_modules/@codemirror/state": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz", + "integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, "node_modules/@codemirror/view": { "version": "6.15.3", "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.15.3.tgz", @@ -4599,7 +4634,7 @@ "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "devOptional": true + "dev": true }, "node_modules/@types/qs": { "version": "6.9.7", @@ -4617,7 +4652,7 @@ "version": "18.2.16", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.16.tgz", "integrity": "sha512-LLFWr12ZhBJ4YVw7neWLe6Pk7Ey5R9OCydfuMsz1L8bZxzaawJj2p06Q8/EFEHDeTBQNFLF62X+CG7B2zIyu0Q==", - "devOptional": true, + "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -4628,7 +4663,7 @@ "version": "18.2.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz", "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==", - "devOptional": true, + "dev": true, "dependencies": { "@types/react": "*" } @@ -4637,7 +4672,7 @@ "version": "0.16.3", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==", - "devOptional": true + "dev": true }, "node_modules/@types/semver": { "version": "7.5.2", @@ -6374,6 +6409,17 @@ "node": ">=6" } }, + "node_modules/cm6-theme-basic-light": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cm6-theme-basic-light/-/cm6-theme-basic-light-0.2.0.tgz", + "integrity": "sha512-1prg2gv44sYfpHscP26uLT/ePrh0mlmVwMSoSd3zYKQ92Ab3jPRLzyCnpyOCQLJbK+YdNs4HvMRqMNYdy4pMhA==", + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -6390,6 +6436,20 @@ "integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==", "dev": true }, + "node_modules/codemirror": { + "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/codesandbox-import-util-types": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/codesandbox-import-util-types/-/codesandbox-import-util-types-2.2.3.tgz", @@ -6889,7 +6949,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "devOptional": true + "dev": true }, "node_modules/d": { "version": "1.0.1", @@ -7168,11 +7228,6 @@ "node": ">=0.3.1" } }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" - }, "node_modules/diff-sequences": { "version": "29.4.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", @@ -10328,16 +10383,6 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/isomorphic.js": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", - "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", - "peer": true, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, "node_modules/issue-parser": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", @@ -11212,26 +11257,6 @@ "resolved": "https://registry.npmjs.org/lexical/-/lexical-0.12.2.tgz", "integrity": "sha512-Kxavd+ETjxtVwG/hvPd6WZfXD44sLOKe9Vlkwxy7lBQ1qZArS+rZfs+u5iXwXe6tX9f2PIM0u3RHsrCEDDE0fw==" }, - "node_modules/lib0": { - "version": "0.2.86", - "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.86.tgz", - "integrity": "sha512-kxigQTM4Q7NwJkEgdqQvU21qiR37twcqqLmh+/SbiGbRLfPlLVbHyY9sWp7PwXh0Xus9ELDSjsUOwcrdt5yZ4w==", - "peer": true, - "dependencies": { - "isomorphic.js": "^0.2.4" - }, - "bin": { - "0gentesthtml": "bin/gentesthtml.js", - "0serve": "bin/0serve.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -17522,6 +17547,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -17537,25 +17563,11 @@ "es6-symbol": "^3" } }, - "node_modules/react-diff-view": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/react-diff-view/-/react-diff-view-3.0.3.tgz", - "integrity": "sha512-orETYmQbptfMbOnbkSHH61Ew5RBTYWAO2M1MDx2ZvsEDHPygn6U8mWh7kUCm/z40YzVKmd3+8hpH872Y0uioIg==", - "dependencies": { - "classnames": "^2.3.2", - "diff-match-patch": "^1.0.5", - "shallow-equal": "^3.1.0", - "warning": "^4.0.3" - }, - "peerDependencies": { - "prop-types": ">=15.6", - "react": ">=16.8" - } - }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -18494,6 +18506,7 @@ "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -18735,11 +18748,6 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true }, - "node_modules/shallow-equal": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz", - "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==" - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -20881,14 +20889,6 @@ "node": ">=14" } }, - "node_modules/warning": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", @@ -21251,23 +21251,6 @@ "node": ">=12" } }, - "node_modules/yjs": { - "version": "13.6.8", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.8.tgz", - "integrity": "sha512-ZPq0hpJQb6f59B++Ngg4cKexDJTvfOgeiv0sBc4sUm8CaBWH7OQC4kcCgrqbjJ/B2+6vO49exvTmYfdlPtcjbg==", - "peer": true, - "dependencies": { - "lib0": "^0.2.74" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" - } - }, "node_modules/ylru": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", diff --git a/package.json b/package.json index 31c31b00..00c08757 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,9 @@ "license": "MIT", "dependencies": { "@codemirror/lang-markdown": "^6.1.1", + "@codemirror/merge": "^6.1.2", "@codemirror/state": "^6.2.1", + "@codemirror/theme-one-dark": "^6.1.2", "@codemirror/view": "6.15.3", "@codesandbox/sandpack-react": "^2.6.7", "@lexical/clipboard": "^0.12.2", @@ -58,6 +60,8 @@ "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.6", "classnames": "^2.3.2", + "cm6-theme-basic-light": "^0.2.0", + "codemirror": "^6.0.1", "downshift": "^7.6.0", "hast-util-raw": "^8.0.0", "hast-util-sanitize": "^4.1.0", @@ -76,7 +80,6 @@ "micromark-extension-frontmatter": "1.1.0", "micromark-extension-gfm-table": "^1.0.6", "micromark-extension-mdxjs": "1.0.1", - "react-diff-view": "^3.0.3", "react-hook-form": "^7.44.2", "unidiff": "^1.0.2" }, diff --git a/src/examples/cm-merge.tsx b/src/examples/cm-merge.tsx new file mode 100644 index 00000000..f1885c2c --- /dev/null +++ b/src/examples/cm-merge.tsx @@ -0,0 +1,89 @@ +import React from 'react' +import { MergeView } from '@codemirror/merge' +import { markdown as markdownLanguageSupport } from '@codemirror/lang-markdown' +import { oneDark } from '@codemirror/theme-one-dark' +import { EditorState, EditorStateConfig, Extension } from '@codemirror/state' +import { EditorView, lineNumbers } from '@codemirror/view' +import { syntaxHighlighting } from '@codemirror/language' +import { basicLight } from 'cm6-theme-basic-light' +import { basicSetup } from 'codemirror' + +const md1 = ` +## Hello world + + This is a paragraph + +Some more text. + +Some more text. +Some more text. +Some more text. + +!()[https://example.com/image.png] +` + +const md2 = ` +## Hello world some text + + This is a paragh + +Some more text. + +more +` + +const commonStateConfigExtensions: Extension[] = [basicSetup, basicLight, markdownLanguageSupport(), lineNumbers()] + +export function Example() { + const cmMergeViewRef = React.useRef(null) + const ref = React.useCallback((el: HTMLDivElement | null) => { + if (el !== null) { + cmMergeViewRef.current = new MergeView({ + renderRevertControl: () => { + const el = document.createElement('button') + el.classList.add('cm-merge-revert') + el.appendChild(document.createTextNode('\u2B95')) + return el + }, + parent: el, + orientation: 'a-b', + revertControls: 'a-to-b', + gutter: true, + collapseUnchanged: { margin: 2, minSize: 3 }, + a: { + doc: md1.trim(), + extensions: [...commonStateConfigExtensions, EditorState.readOnly.of(true)] + }, + b: { + doc: md2.trim(), + extensions: [ + ...commonStateConfigExtensions, + EditorView.updateListener.of(({ state }) => { + const md = state.doc.toString() + console.log(md) + }) + ] + } + }) + } else { + cmMergeViewRef.current?.destroy() + cmMergeViewRef.current = null + } + }, []) + + return
Hello
+} + +export function Codemirror() { + const ref = React.useCallback((el: HTMLDivElement | null) => { + if (el !== null) { + el.innerHTML = '' + const e = new EditorView({ + parent: el, + state: EditorState.create({ doc: md1, extensions: [markdownLanguageSupport(), basicLight] }) + }) + } + }, []) + + return
Hello
+} diff --git a/src/plugins/diff-source/DiffViewer.tsx b/src/plugins/diff-source/DiffViewer.tsx index 13da7a79..02b822b8 100644 --- a/src/plugins/diff-source/DiffViewer.tsx +++ b/src/plugins/diff-source/DiffViewer.tsx @@ -1,25 +1,66 @@ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import React from 'react' -import { Diff, Hunk, parseDiff } from 'react-diff-view' -import { diffLines, formatLines } from 'unidiff' -import 'react-diff-view/style/index.css' -import { corePluginHooks } from '../core' import { diffSourcePluginHooks } from '.' +import { corePluginHooks } from '../core' + +import { MergeView } from '@codemirror/merge' +import { EditorState } from '@codemirror/state' +import { EditorView } from '@codemirror/view' +import { COMMON_STATE_CONFIG_EXTENSIONS } from './SourceEditor' export const DiffViewer: React.FC = () => { const [newText] = corePluginHooks.useEmitterValues('markdown') const [oldText] = diffSourcePluginHooks.useEmitterValues('diffMarkdown') + const updateMarkdown = diffSourcePluginHooks.usePublisher('markdownSourceEditorValue') + return +} - const diffText = formatLines(diffLines(oldText, newText), { context: 3 }) - if (diffText.trim() === '') return
No changes
- const [diff] = parseDiff(diffText, { nearbySequences: 'zip' }) +interface CmMergeViewProps { + oldMarkdown: string + newMarkdown: string + onUpdate: (markdown: string) => void +} + +const CmMergeView: React.FC = ({ oldMarkdown, newMarkdown, onUpdate }) => { + const cmMergeViewRef = React.useRef(null) - return ( - - {(hunks) => hunks.map((hunk) => )} - + const ref = React.useCallback( + (el: HTMLDivElement | null) => { + if (el !== null) { + cmMergeViewRef.current = new MergeView({ + renderRevertControl: () => { + const el = document.createElement('button') + el.classList.add('cm-merge-revert') + el.appendChild(document.createTextNode('\u2B95')) + return el + }, + parent: el, + orientation: 'a-b', + revertControls: 'a-to-b', + gutter: true, + collapseUnchanged: { margin: 2, minSize: 3 }, + a: { + doc: oldMarkdown, + extensions: [...COMMON_STATE_CONFIG_EXTENSIONS, EditorState.readOnly.of(true)] + }, + b: { + doc: newMarkdown, + extensions: [ + ...COMMON_STATE_CONFIG_EXTENSIONS, + EditorView.updateListener.of(({ state }) => { + const md = state.doc.toString() + onUpdate(md) + }) + ] + } + }) + } else { + cmMergeViewRef.current?.destroy() + cmMergeViewRef.current = null + } + }, + [newMarkdown, oldMarkdown, onUpdate] ) + + return
} diff --git a/src/plugins/diff-source/SourceEditor.tsx b/src/plugins/diff-source/SourceEditor.tsx index 21ce67af..b495bbdf 100644 --- a/src/plugins/diff-source/SourceEditor.tsx +++ b/src/plugins/diff-source/SourceEditor.tsx @@ -1,33 +1,43 @@ import { markdown as markdownLanguageSupport } from '@codemirror/lang-markdown' -import type { CodeMirrorRef } from '@codesandbox/sandpack-react/components/CodeEditor/CodeMirror' -import { SandpackProvider, CodeEditor as TheEditorFromSandpack } from '@codesandbox/sandpack-react' +import { EditorState, Extension } from '@codemirror/state' +import { EditorView, lineNumbers } from '@codemirror/view' +import { basicLight } from 'cm6-theme-basic-light' +import { basicSetup } from 'codemirror' import React from 'react' import { diffSourcePluginHooks } from '.' import { corePluginHooks } from '../core' -import { EditorView } from '@codemirror/view' + +export const COMMON_STATE_CONFIG_EXTENSIONS: Extension[] = [basicSetup, basicLight, markdownLanguageSupport(), lineNumbers()] export const SourceEditor = () => { const [markdown, readOnly] = corePluginHooks.useEmitterValues('markdown', 'readOnly') const updateMarkdown = diffSourcePluginHooks.usePublisher('markdownSourceEditorValue') - const codeMirrorRef = React.useRef(null) + const editorViewRef = React.useRef(null) - return ( -
- - - - - -
+ const ref = React.useCallback( + (el: HTMLDivElement | null) => { + if (el !== null) { + const extensions = [ + ...COMMON_STATE_CONFIG_EXTENSIONS, + EditorView.updateListener.of(({ state }) => { + updateMarkdown(state.doc.toString()) + }) + ] + if (readOnly) { + extensions.push(EditorState.readOnly.of(true)) + } + el.innerHTML = '' + editorViewRef.current = new EditorView({ + parent: el, + state: EditorState.create({ doc: markdown, extensions }) + }) + } else { + editorViewRef.current?.destroy() + editorViewRef.current = null + } + }, + [markdown, readOnly, updateMarkdown] ) + + return
} diff --git a/src/plugins/diff-source/index.tsx b/src/plugins/diff-source/index.tsx index ca088692..10785238 100644 --- a/src/plugins/diff-source/index.tsx +++ b/src/plugins/diff-source/index.tsx @@ -29,7 +29,8 @@ export const diffSourceSystem = system( r.o.withLatestFrom(markdownSourceEditorValue) ), ([{ current }, markdownSourceFromEditor]) => { - if (current === 'source') { + if (current === 'source' || current === 'diff') { + console.log('setting markdown', markdownSourceFromEditor) r.pub(setMarkdown, markdownSourceFromEditor) } } diff --git a/src/plugins/link-dialog/index.ts b/src/plugins/link-dialog/index.ts index 2ad7cd54..71a0b352 100644 --- a/src/plugins/link-dialog/index.ts +++ b/src/plugins/link-dialog/index.ts @@ -44,6 +44,9 @@ function getLinkNodeInSelection(selection: RangeSelection | null) { return null } const node = getSelectedNode(selection) + if (node === null) { + return null + } const parent = node.getParent() if ($isLinkNode(parent)) { return parent diff --git a/src/styles/globals.css b/src/styles/globals.css index f4881a59..801336eb 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -8,12 +8,6 @@ @import url('@radix-ui/colors/red.css'); .mdxeditor { - & .diff { - --diff-font-family: var(--font-mono); - font-size: var(--text-xs); - } - - /** Code mirror */ & .cm-editor { --sp-font-mono: var(--font-mono); @@ -43,4 +37,23 @@ flex-shrink: 1; } } + + /** Diff viewer */ + & .cm-mergeView .cm-scroller { + font-family: var(--font-mono); + line-height: 1.3rem; + font-size: var(--text-xs); + } + + /** Diff viewer */ + & .cm-sourceView .cm-scroller { + font-family: var(--font-mono); + line-height: 1.3rem; + font-size: var(--text-xs); + } + + & .cm-gutters { + background: transparent; + font-size: var(--text-xxs); + } } diff --git a/src/styles/ui.module.css b/src/styles/ui.module.css index fea8761b..2d0db7b8 100644 --- a/src/styles/ui.module.css +++ b/src/styles/ui.module.css @@ -125,6 +125,7 @@ --text-base: 1rem; --text-sm: 0.875rem; --text-xs: 0.75rem; + --text-xxs: 0.6rem; font-family: var(--font-body); color: var(--baseText); diff --git a/src/utils/lexicalHelpers.ts b/src/utils/lexicalHelpers.ts index 79e1ea9f..a71b616d 100644 --- a/src/utils/lexicalHelpers.ts +++ b/src/utils/lexicalHelpers.ts @@ -10,19 +10,24 @@ export function fromWithinEditorRead(editor: LexicalEditor, fn: () => T): T { }) return result as T } -export function getSelectedNode(selection: RangeSelection): TextNode | ElementNode { - const anchor = selection.anchor - const focus = selection.focus - const anchorNode = selection.anchor.getNode() - const focusNode = selection.focus.getNode() - if (anchorNode === focusNode) { - return anchorNode - } - const isBackward = selection.isBackward() - if (isBackward) { - return $isAtNodeEnd(focus) ? anchorNode : focusNode - } else { - return $isAtNodeEnd(anchor) ? anchorNode : focusNode +export function getSelectedNode(selection: RangeSelection): TextNode | ElementNode | null { + try { + const anchor = selection.anchor + const focus = selection.focus + + const anchorNode = selection.anchor.getNode() + const focusNode = selection.focus.getNode() + if (anchorNode === focusNode) { + return anchorNode + } + const isBackward = selection.isBackward() + if (isBackward) { + return $isAtNodeEnd(focus) ? anchorNode : focusNode + } else { + return $isAtNodeEnd(anchor) ? anchorNode : focusNode + } + } catch { + return null } }