Skip to content

Commit

Permalink
fix: Incorrect plain text serialization in exportTable (#8234)
Browse files Browse the repository at this point in the history
  • Loading branch information
tommoor authored Jan 14, 2025
1 parent a0d7837 commit 1aaabf1
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 27 deletions.
7 changes: 2 additions & 5 deletions app/editor/extensions/ClipboardTextSerializer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Plugin, PluginKey } from "prosemirror-state";
import Extension from "@shared/editor/lib/Extension";
import textBetween from "@shared/editor/lib/textBetween";
import { getTextSerializers } from "@shared/editor/lib/textSerializers";

/**
* A plugin that allows overriding the default behavior of the editor to allow
Expand All @@ -13,11 +14,7 @@ export default class ClipboardTextSerializer extends Extension {
}

get plugins() {
const textSerializers = Object.fromEntries(
Object.entries(this.editor.schema.nodes)
.filter(([, node]) => node.spec.toPlainText)
.map(([name, node]) => [name, node.spec.toPlainText])
);
const textSerializers = getTextSerializers(this.editor.schema);

return [
new Plugin({
Expand Down
7 changes: 2 additions & 5 deletions app/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import Extension, {
import ExtensionManager from "@shared/editor/lib/ExtensionManager";
import { MarkdownSerializer } from "@shared/editor/lib/markdown/serializer";
import textBetween from "@shared/editor/lib/textBetween";
import { getTextSerializers } from "@shared/editor/lib/textSerializers";
import Mark from "@shared/editor/marks/Mark";
import { basicExtensions as extensions } from "@shared/editor/nodes";
import Node from "@shared/editor/nodes/Node";
Expand Down Expand Up @@ -713,11 +714,7 @@ export class Editor extends React.PureComponent<
*/
public getPlainText = () => {
const { doc } = this.view.state;
const textSerializers = Object.fromEntries(
Object.entries(this.schema.nodes)
.filter(([, node]) => node.spec.toPlainText)
.map(([name, node]) => [name, node.spec.toPlainText])
);
const textSerializers = getTextSerializers(this.schema);

return textBetween(doc, 0, doc.content.size, textSerializers);
};
Expand Down
7 changes: 2 additions & 5 deletions server/models/helpers/DocumentHelper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Node } from "prosemirror-model";
import { updateYFragment, yDocToProsemirrorJSON } from "y-prosemirror";
import * as Y from "yjs";
import textBetween from "@shared/editor/lib/textBetween";
import { getTextSerializers } from "@shared/editor/lib/textSerializers";
import { EditorStyleHelper } from "@shared/editor/styles/EditorStyleHelper";
import { IconType, ProsemirrorData } from "@shared/types";
import { determineIconType } from "@shared/utils/icon";
Expand Down Expand Up @@ -487,9 +488,5 @@ export class DocumentHelper {
);
}

private static textSerializers = Object.fromEntries(
Object.entries(schema.nodes)
.filter(([, n]) => n.spec.toPlainText)
.map(([name, n]) => [name, n.spec.toPlainText])
);
private static textSerializers = getTextSerializers(schema);
}
3 changes: 2 additions & 1 deletion shared/editor/commands/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
deleteRow,
deleteColumn,
} from "prosemirror-tables";
import { ProsemirrorHelper } from "../../utils/ProsemirrorHelper";
import { chainTransactions } from "../lib/chainTransactions";
import { getCellsInColumn, isHeaderEnabled } from "../queries/table";
import { TableLayout } from "../types";
Expand Down Expand Up @@ -116,7 +117,7 @@ export function exportTable({
.map((row) =>
row
.map((cell) => {
let value = cell.textContent;
let value = ProsemirrorHelper.toPlainText(cell, state.schema);

// Escape double quotes by doubling them
if (value.includes('"')) {
Expand Down
14 changes: 14 additions & 0 deletions shared/editor/lib/textSerializers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Schema } from "prosemirror-model";

/**
* Generate a map of text serializers for a given schema
* @param schema
* @returns Text serializers
*/
export function getTextSerializers(schema: Schema) {
return Object.fromEntries(
Object.entries(schema.nodes)
.filter(([, node]) => node.spec.toPlainText)
.map(([name, node]) => [name, node.spec.toPlainText])
);
}
14 changes: 3 additions & 11 deletions shared/utils/ProsemirrorHelper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Node, Schema } from "prosemirror-model";
import headingToSlug from "../editor/lib/headingToSlug";
import textBetween from "../editor/lib/textBetween";
import { getTextSerializers } from "../editor/lib/textSerializers";
import { ProsemirrorData } from "../types";
import { TextHelper } from "./TextHelper";

Expand Down Expand Up @@ -90,12 +91,7 @@ export class ProsemirrorHelper {
* @returns The document content as plain text without formatting.
*/
static toPlainText(root: Node, schema: Schema) {
const textSerializers = Object.fromEntries(
Object.entries(schema.nodes)
.filter(([, node]) => node.spec.toPlainText)
.map(([name, node]) => [name, node.spec.toPlainText])
);

const textSerializers = getTextSerializers(schema);
return textBetween(root, 0, root.content.size, textSerializers);
}

Expand Down Expand Up @@ -153,11 +149,7 @@ export class ProsemirrorHelper {
return !doc || doc.textContent.trim() === "";
}

const textSerializers = Object.fromEntries(
Object.entries(schema.nodes)
.filter(([, node]) => node.spec.toPlainText)
.map(([name, node]) => [name, node.spec.toPlainText])
);
const textSerializers = getTextSerializers(schema);

let empty = true;
doc.descendants((child: Node) => {
Expand Down

0 comments on commit 1aaabf1

Please sign in to comment.