From 0f489d54c3513e8abab09fd261a12367cc922b81 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 30 Dec 2022 14:49:53 -0500 Subject: [PATCH] Add DocumentHelper.toPlainText --- server/models/helpers/DocumentHelper.test.ts | 63 +++++++++++++++++++- server/models/helpers/DocumentHelper.tsx | 21 ++++++- 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/server/models/helpers/DocumentHelper.test.ts b/server/models/helpers/DocumentHelper.test.ts index dda1f2ce2..9dec809a3 100644 --- a/server/models/helpers/DocumentHelper.test.ts +++ b/server/models/helpers/DocumentHelper.test.ts @@ -1,7 +1,7 @@ import Revision from "@server/models/Revision"; import DocumentHelper from "./DocumentHelper"; -describe("toEmailDiff", () => { +describe("DocumentHelper", () => { test("toEmailDiff", async () => { const before = new Revision({ title: "Title", @@ -80,4 +80,65 @@ same on both sides`, expect(html).not.toContain("same on both sides"); expect(html).not.toContain("this is a highlight"); }); + + test("toPlainText", async () => { + const revision = new Revision({ + title: "Title", + text: ` +This is a test paragraph + +A new [link](https://www.google.com) + +- list item 1 + +This is a new paragraph. + +!!This is a placeholder!! + +==this is a highlight== + +- [x] checklist item 1 +- [x] checklist item 2 +- [ ] checklist item 3 +- [ ] checklist item 4 +- [x] checklist item 5 + +same on both sides + +same on both sides + +same on both sides`, + }); + + const text = await DocumentHelper.toPlainText(revision); + + // Strip all formatting + expect(text).toEqual(`This is a test paragraph + +A new link + +list item 1 + +This is a new paragraph. + +This is a placeholder + +this is a highlight + +checklist item 1 + +checklist item 2 + +checklist item 3 + +checklist item 4 + +checklist item 5 + +same on both sides + +same on both sides + +same on both sides`); + }); }); diff --git a/server/models/helpers/DocumentHelper.tsx b/server/models/helpers/DocumentHelper.tsx index d8af4f1d0..55ded7696 100644 --- a/server/models/helpers/DocumentHelper.tsx +++ b/server/models/helpers/DocumentHelper.tsx @@ -10,6 +10,7 @@ import { renderToString } from "react-dom/server"; import styled, { ServerStyleSheet, ThemeProvider } from "styled-components"; import * as Y from "yjs"; import EditorContainer from "@shared/editor/components/Styles"; +import textBetween from "@shared/editor/lib/textBetween"; import GlobalStyles from "@shared/styles/globals"; import light from "@shared/styles/theme"; import { @@ -44,7 +45,7 @@ type HTMLOptions = { export default class DocumentHelper { /** * Returns the document as a Prosemirror Node. This method uses the - * collaborative state if available, otherwise it falls back to Markdown->HTML. + * collaborative state if available, otherwise it falls back to Markdown. * * @param document The document or revision to convert * @returns The document content as a Prosemirror Node @@ -58,6 +59,24 @@ export default class DocumentHelper { return parser.parse(document.text); } + /** + * Returns the document as plain text. This method uses the + * collaborative state if available, otherwise it falls back to Markdown. + * + * @param document The document or revision to convert + * @returns The document content as plain text without formatting. + */ + static toPlainText(document: Document | Revision) { + const node = DocumentHelper.toProsemirror(document); + const textSerializers = Object.fromEntries( + Object.entries(schema.nodes) + .filter(([, node]) => node.spec.toPlainText) + .map(([name, node]) => [name, node.spec.toPlainText]) + ); + + return textBetween(node, 0, node.content.size, textSerializers); + } + /** * Returns the document as Markdown. This is a lossy conversion and should * only be used for export.