import { describe, expect, it } from "vitest"; import { BlockNoteEditor } from "../../.."; import { nestedListsToBlockNoteStructure } from "./util/nestedLists"; async function parseHTMLAndCompareSnapshots( html: string, snapshotName: string ) { // use a dynamic import because we want to access // __parseFromClipboard which is not exposed in types const view: any = await import("prosemirror-view"); const editor = BlockNoteEditor.create(); const blocks = await editor.tryParseHTMLToBlocks(html); const snapshotPath = "./__snapshots__/paste/" + snapshotName + ".json"; expect(JSON.stringify(blocks, undefined, 2)).toMatchFileSnapshot( snapshotPath ); // Now, we also want to test actually pasting in the editor, and not just calling // tryParseHTMLToBlocks directly. // The reason is that the prosemirror logic for pasting can be a bit different, because // it's related to the context of where the user is pasting exactly (selection) // // The internal difference come that in tryParseHTMLToBlocks, we use DOMParser.parse, // while when pasting, Prosemirror uses DOMParser.parseSlice, and then tries to fit the // slice in the document. This fitting might change the structure / interpretation of the pasted blocks // Simulate a paste event (this uses DOMParser.parseSlice internally) (window as any).__TEST_OPTIONS.mockID = 0; // reset id counter const htmlNode = nestedListsToBlockNoteStructure(html); const tt = editor._tiptapEditor; const slice = view.__parseFromClipboard( tt.view, "", htmlNode.innerHTML, false, tt.view.state.selection.$from ); tt.view.dispatch(tt.view.state.tr.replaceSelection(slice)); // alternative paste simulation doesn't work in a non-browser vitest env // editor._tiptapEditor.view.pasteHTML(html, { // preventDefault: () => { // // noop // }, // clipboardData: { // types: ["text/html"], // getData: () => html, // }, // } as any); const pastedBlocks = editor.topLevelBlocks; pastedBlocks.pop(); // trailing paragraph expect(pastedBlocks).toStrictEqual(blocks); } describe("Parse HTML", () => { it("Parse basic block types", async () => { const html = `
Paragraph
None Bold Italic Underline Strikethrough All
Bullet List Item
Nested Bullet List Item
Nested Bullet List Item
Bullet List Item
Numbered List Item
Nested Numbered List Item
Nested Numbered List Item
Numbered List Item
Nested Bullet List Item
Nested Bullet List Item
Image Caption
Paragraph
Bold Italic Underline Strikethrough All
Nested Paragraph
Paragraph 1
Nested Paragraph 1
Nested Paragraph 2
Paragraph With Hard Break
Bold Italic Underline Strikethrough All
Background Color Paragraph
!https://www.pulsecarshalton.co.uk/wp-content/uploads/2016/08/jk-placeholder-image.jpg
| Cell 1 | Cell 2 | Cell 3 |
|---|---|---|
| Cell 4 | Cell 5 | Cell 6 |
| Cell 7 | Cell 8 | Cell 9 |
Paragraph
`; await parseHTMLAndCompareSnapshots(html, "parse-notion-html"); }); // Currently breaking, seems related to parsing `` elements it.skip("Parse Google Docs HTML", async () => { // A few notes on Google Docs output HTML: // - All inline markup is represented as `` elements with inline // styles (bold, italic, etc.) // - The nested list structure is not valid, i.e. `Paragraph 1
Paragraph 2
Paragraph 3
Paragraph With
Hard Break
Bold Italic Underline Strikethrough All
Bullet List Item 1
Nested Bullet List Item 1
Nested Numbered List Item 1
Nested Numbered List Item 2
Nested Bullet List Item 2
Bullet List Item 2
Numbered List Item 1
Numbered List Item 2
Paragraph