mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
fix: Remote table modifications cause CellSelection to be lost (#9596)
* fix: Table modifications lose any existing CellSelection * tsc * doc * Remove unused imports
This commit is contained in:
+3
-3
@@ -90,13 +90,13 @@
|
||||
"@outlinewiki/passport-azure-ad-oauth2": "^0.1.0",
|
||||
"@radix-ui/react-collapsible": "^1.1.11",
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-one-time-password-field": "^0.1.7",
|
||||
"@radix-ui/react-popover": "^1.1.14",
|
||||
"@radix-ui/react-select": "^2.1.4",
|
||||
"@radix-ui/react-switch": "^1.2.5",
|
||||
"@radix-ui/react-tabs": "^1.1.12",
|
||||
"@radix-ui/react-tooltip": "^1.2.7",
|
||||
"@radix-ui/react-visually-hidden": "^1.2.2",
|
||||
"@radix-ui/react-one-time-password-field": "^0.1.7",
|
||||
"@renderlesskit/react": "^0.11.0",
|
||||
"@sentry/node": "^7.120.3",
|
||||
"@sentry/react": "^7.120.3",
|
||||
@@ -183,7 +183,7 @@
|
||||
"passport-google-oauth2": "^0.2.0",
|
||||
"passport-oauth2": "^1.8.0",
|
||||
"passport-slack-oauth2": "^1.2.0",
|
||||
"patch-package": "^7.0.2",
|
||||
"patch-package": "^8.0.0",
|
||||
"pg": "^8.15.6",
|
||||
"pg-tsquery": "^8.4.2",
|
||||
"pluralize": "^8.0.0",
|
||||
@@ -265,7 +265,7 @@
|
||||
"winston": "^3.17.0",
|
||||
"ws": "^7.5.10",
|
||||
"y-indexeddb": "^9.0.11",
|
||||
"y-prosemirror": "^1.2.12",
|
||||
"y-prosemirror": "^1.3.7",
|
||||
"y-protocols": "^1.0.6",
|
||||
"yauzl": "^2.10.0",
|
||||
"yjs": "^13.6.1",
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
diff --git a/node_modules/y-prosemirror/src/plugins/sync-plugin.js b/node_modules/y-prosemirror/src/plugins/sync-plugin.js
|
||||
index dccfb76..45b6f1a 100644
|
||||
--- a/node_modules/y-prosemirror/src/plugins/sync-plugin.js
|
||||
+++ b/node_modules/y-prosemirror/src/plugins/sync-plugin.js
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { createMutex } from 'lib0/mutex'
|
||||
import * as PModel from 'prosemirror-model'
|
||||
-import { AllSelection, Plugin, TextSelection, NodeSelection } from "prosemirror-state"; // eslint-disable-line
|
||||
+import { Plugin, TextSelection } from "prosemirror-state"; // eslint-disable-line
|
||||
import * as math from 'lib0/math'
|
||||
import * as object from 'lib0/object'
|
||||
import * as set from 'lib0/set'
|
||||
@@ -242,40 +242,24 @@ export const ySyncPlugin = (yXmlFragment, {
|
||||
}
|
||||
|
||||
/**
|
||||
- * @param {import('prosemirror-state').Transaction} tr
|
||||
- * @param {ReturnType<typeof getRelativeSelection>} relSel
|
||||
- * @param {ProsemirrorBinding} binding
|
||||
+ * NOTE: restoreRelativeSelection, getRelativeSelection, and relativePositionStore are
|
||||
+ * from the PR here: https://github.com/yjs/y-prosemirror/pull/182 in order to support
|
||||
+ * CellSelection and other selection types.
|
||||
+ *
|
||||
+ * If the PR is merged this patch can be removed.
|
||||
*/
|
||||
-const restoreRelativeSelection = (tr, relSel, binding) => {
|
||||
- if (relSel !== null && relSel.anchor !== null && relSel.head !== null) {
|
||||
- if (relSel.type === 'all') {
|
||||
- tr.setSelection(new AllSelection(tr.doc))
|
||||
- } else if (relSel.type === 'node') {
|
||||
- const anchor = relativePositionToAbsolutePosition(
|
||||
- binding.doc,
|
||||
- binding.type,
|
||||
- relSel.anchor,
|
||||
- binding.mapping
|
||||
- )
|
||||
- tr.setSelection(NodeSelection.create(tr.doc, anchor))
|
||||
- } else {
|
||||
- const anchor = relativePositionToAbsolutePosition(
|
||||
- binding.doc,
|
||||
- binding.type,
|
||||
- relSel.anchor,
|
||||
- binding.mapping
|
||||
- )
|
||||
- const head = relativePositionToAbsolutePosition(
|
||||
- binding.doc,
|
||||
- binding.type,
|
||||
- relSel.head,
|
||||
- binding.mapping
|
||||
- )
|
||||
- if (anchor !== null && head !== null) {
|
||||
- const sel = TextSelection.between(tr.doc.resolve(anchor), tr.doc.resolve(head))
|
||||
- tr.setSelection(sel)
|
||||
- }
|
||||
- }
|
||||
+
|
||||
+/**
|
||||
+ * This will return a function that can be used to convert a relative position to an absolute position.
|
||||
+ * @param {ProsemirrorBinding} pmbinding
|
||||
+ * @param {number} pos
|
||||
+ * @returns {(binding?: ProsemirrorBinding) => number}
|
||||
+ */
|
||||
+export const relativePositionStore = (pmbinding, pos) => {
|
||||
+ const relPos = absolutePositionToRelativePosition(pos, pmbinding.type, pmbinding.mapping)
|
||||
+
|
||||
+ return (binding = pmbinding) => {
|
||||
+ return relativePositionToAbsolutePosition(binding.doc, binding.type, relPos, binding.mapping)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,19 +267,65 @@ const restoreRelativeSelection = (tr, relSel, binding) => {
|
||||
* @param {ProsemirrorBinding} pmbinding
|
||||
* @param {import('prosemirror-state').EditorState} state
|
||||
*/
|
||||
-export const getRelativeSelection = (pmbinding, state) => ({
|
||||
- type: /** @type {any} */ (state.selection).jsonID,
|
||||
- anchor: absolutePositionToRelativePosition(
|
||||
- state.selection.anchor,
|
||||
- pmbinding.type,
|
||||
- pmbinding.mapping
|
||||
- ),
|
||||
- head: absolutePositionToRelativePosition(
|
||||
- state.selection.head,
|
||||
- pmbinding.type,
|
||||
- pmbinding.mapping
|
||||
- )
|
||||
-})
|
||||
+export const getRelativeSelection = (pmbinding, state) => {
|
||||
+ /**
|
||||
+ * @type {Map<number, (binding?: ProsemirrorBinding) => number>}
|
||||
+ */
|
||||
+ const mapping = new Map()
|
||||
+ /**
|
||||
+ * We take a bookmark of the current selection
|
||||
+ * and map it to it's relative positions,
|
||||
+ * so we can restore the selection in the future.
|
||||
+ */
|
||||
+ const bookmark = state.selection.getBookmark().map({
|
||||
+ map (pos) {
|
||||
+ // Store the relative position using the position as the key
|
||||
+ mapping.set(pos, relativePositionStore(pmbinding, pos))
|
||||
+
|
||||
+ // Pass through the position unchanged, since we are just using it to store the relative position
|
||||
+ return pos
|
||||
+ },
|
||||
+ mapResult (pos) {
|
||||
+ // Call the map function to store the relative position
|
||||
+ return { pos: this.map(pos), deleted: false, deletedAcross: false, deletedAfter: false, deletedBefore: false }
|
||||
+ }
|
||||
+ })
|
||||
+
|
||||
+ return {
|
||||
+ mapping,
|
||||
+ bookmark
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Restores the relative selection to the prosemirror view.
|
||||
+ * @param {import('prosemirror-state').Transaction} tr
|
||||
+ * @param {ReturnType<typeof getRelativeSelection>} relSel
|
||||
+ * @param {ProsemirrorBinding} pmbinding
|
||||
+ */
|
||||
+const restoreRelativeSelection = (tr, { mapping, bookmark }, pmbinding) => {
|
||||
+ /**
|
||||
+ * We can now try to map the bookmark into the appropriate absolute positions.
|
||||
+ */
|
||||
+ const selection = bookmark.map({
|
||||
+ map (pos) {
|
||||
+ const getPos = mapping.get(pos)
|
||||
+ if (!getPos) {
|
||||
+ throw new Error('Relative position not set')
|
||||
+ }
|
||||
+ return getPos(pmbinding)
|
||||
+ },
|
||||
+ mapResult (originalPos) {
|
||||
+ const mappedPos = this.map(originalPos)
|
||||
+ if (mappedPos === null) {
|
||||
+ return { pos: originalPos, deleted: true, deletedAcross: true, deletedAfter: true, deletedBefore: true }
|
||||
+ }
|
||||
+ return { pos: mappedPos, deleted: false, deletedAcross: false, deletedAfter: false, deletedBefore: false }
|
||||
+ }
|
||||
+ }).resolve(tr.doc)
|
||||
+
|
||||
+ tr.setSelection(selection)
|
||||
+}
|
||||
|
||||
/**
|
||||
* Binding for prosemirror.
|
||||
@@ -478,7 +478,10 @@ export class DocumentHelper {
|
||||
}
|
||||
|
||||
// apply new document to existing ydoc
|
||||
updateYFragment(type.doc, type, doc, new Map());
|
||||
updateYFragment(type.doc, type, doc, {
|
||||
mapping: new Map(),
|
||||
isOMark: new Map(),
|
||||
});
|
||||
|
||||
const state = Y.encodeStateAsUpdate(ydoc);
|
||||
|
||||
|
||||
@@ -47,7 +47,10 @@ export default async function main(exit = false) {
|
||||
}
|
||||
|
||||
// apply new document to existing ydoc
|
||||
updateYFragment(type.doc, type, doc, new Map());
|
||||
updateYFragment(type.doc, type, doc, {
|
||||
mapping: new Map(),
|
||||
isOMark: new Map(),
|
||||
});
|
||||
|
||||
const state = Y.encodeStateAsUpdate(ydoc);
|
||||
document.state = Buffer.from(state);
|
||||
|
||||
@@ -11219,6 +11219,17 @@ json-stable-stringify-without-jsonify@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||
integrity "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
|
||||
|
||||
json-stable-stringify@^1.0.2:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70"
|
||||
integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==
|
||||
dependencies:
|
||||
call-bind "^1.0.8"
|
||||
call-bound "^1.0.4"
|
||||
isarray "^2.0.5"
|
||||
jsonify "^0.0.1"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
json5@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
@@ -11259,6 +11270,11 @@ jsonfile@^6.0.1:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
|
||||
integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==
|
||||
|
||||
jsonpointer@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
|
||||
@@ -11631,10 +11647,10 @@ levn@~0.3.0:
|
||||
prelude-ls "~1.1.2"
|
||||
type-check "~0.3.2"
|
||||
|
||||
lib0@^0.2.42, lib0@^0.2.46, lib0@^0.2.47, lib0@^0.2.74, lib0@^0.2.85:
|
||||
version "0.2.88"
|
||||
resolved "https://registry.yarnpkg.com/lib0/-/lib0-0.2.88.tgz#18618e0c3b63f6260255eb760f9247d9cc6c6a5b"
|
||||
integrity sha512-KyroiEvCeZcZEMx5Ys+b4u4eEBbA1ch7XUaBhYpwa/nPMrzTjUhI4RfcytmQfYoTBPcdyx+FX6WFNIoNuJzJfQ==
|
||||
lib0@^0.2.109, lib0@^0.2.46, lib0@^0.2.47, lib0@^0.2.74, lib0@^0.2.85:
|
||||
version "0.2.109"
|
||||
resolved "https://registry.yarnpkg.com/lib0/-/lib0-0.2.109.tgz#78a4a15cfb9de489a031396c6497eefe620ca794"
|
||||
integrity sha512-jP0gbnyW0kwlx1Atc4dcHkBbrVAkdHjuyHxtClUPYla7qCmwIif1qZ6vQeJdR5FrOVdn26HvQT0ko01rgW7/Xw==
|
||||
dependencies:
|
||||
isomorphic.js "^0.2.4"
|
||||
|
||||
@@ -12913,10 +12929,10 @@ passthrough-counter@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/passthrough-counter/-/passthrough-counter-1.0.0.tgz#1967d9e66da572b5c023c787db112a387ab166fa"
|
||||
integrity "sha1-GWfZ5m2lcrXAI8eH2xEqOHqxZvo= sha512-Wy8PXTLqPAN0oEgBrlnsXPMww3SYJ44tQ8aVrGAI4h4JZYCS0oYqsPqtPR8OhJpv6qFbpbB7XAn0liKV7EXubA=="
|
||||
|
||||
patch-package@^7.0.2:
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-7.0.2.tgz#c01589bb6964854b5210506a5845d47900641f5a"
|
||||
integrity "sha1-wBWJu2lkhUtSEFBqWEXUeQBkH1o= sha512-PMYfL8LXxGIRmxXLqlEaBxzKPu7/SdP13ld6GSfAUJUZRmBDPp8chZs0dpzaAFn9TSPnFiMwkC6PJt6pBiAl8Q=="
|
||||
patch-package@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61"
|
||||
integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==
|
||||
dependencies:
|
||||
"@yarnpkg/lockfile" "^1.1.0"
|
||||
chalk "^4.1.2"
|
||||
@@ -12924,6 +12940,7 @@ patch-package@^7.0.2:
|
||||
cross-spawn "^7.0.3"
|
||||
find-yarn-workspace-root "^2.0.0"
|
||||
fs-extra "^9.0.0"
|
||||
json-stable-stringify "^1.0.2"
|
||||
klaw-sync "^6.0.0"
|
||||
minimist "^1.2.6"
|
||||
open "^7.4.2"
|
||||
@@ -13237,7 +13254,7 @@ postgres-interval@^1.1.0:
|
||||
postinstall-postinstall@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3"
|
||||
integrity "sha1-T393RB71OdFRLEC9BMcbBqRwTKM= sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ=="
|
||||
integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ==
|
||||
|
||||
pprof-format@^2.1.0:
|
||||
version "2.1.0"
|
||||
@@ -16476,12 +16493,12 @@ y-indexeddb@^9.0.11:
|
||||
dependencies:
|
||||
lib0 "^0.2.74"
|
||||
|
||||
y-prosemirror@^1.2.12:
|
||||
version "1.2.12"
|
||||
resolved "https://registry.yarnpkg.com/y-prosemirror/-/y-prosemirror-1.2.12.tgz#3bb3bd9def611a90e8b7ac6a7e46a6230f238746"
|
||||
integrity sha512-UMnUIR5ppVn30n2kzeeBQEaesWGe4fsbnlch1HnNa3/snJMoOn7M7dieuS+o1OQwKs1dqx2eT3gFfGF2aOaQdw==
|
||||
y-prosemirror@^1.3.7:
|
||||
version "1.3.7"
|
||||
resolved "https://registry.yarnpkg.com/y-prosemirror/-/y-prosemirror-1.3.7.tgz#f88e553da4ea33278b114cf0b6a0ea978b154e84"
|
||||
integrity sha512-NpM99WSdD4Fx4if5xOMDpPtU3oAmTSjlzh5U4353ABbRHl1HtAFUx6HlebLZfyFxXN9jzKMDkVbcRjqOZVkYQg==
|
||||
dependencies:
|
||||
lib0 "^0.2.42"
|
||||
lib0 "^0.2.109"
|
||||
|
||||
y-protocols@^1.0.6:
|
||||
version "1.0.6"
|
||||
|
||||
Reference in New Issue
Block a user