UNPKG

@automattic/rtjson-to-wpblocks

Version:

Javascript code to convert Day One RTJson to WordPress Gutenberg Blocks

741 lines (706 loc) 17.4 kB
// @ts-check const dedent = require("dedent").default; const { describe, it, expect } = require("@jest/globals"); const { buildNodeTree } = require("../build-node-tree.js"); describe("Test text nodes", () => { it("Should return a paragraph with one node", () => { let node = { attributes: {}, text: "It has a paragraph\n", }; let expected = [ { type: "paragraph", content: [ { type: "text", attributes: {}, text: "It has a paragraph\n" }, ], }, ]; expect(buildNodeTree([node])).toEqual(expected); }); it("Should handle multiple paragraphs without merging them", () => { let nodes = [ { attributes: {}, text: "It has a paragraph\n", }, { attributes: {}, text: "Second paragraph\n", }, { attributes: {}, text: "Third paragraph\n", }, ]; let expected = [ { type: "paragraph", content: [ { type: "text", attributes: {}, text: "It has a paragraph\n" }, ], }, { type: "paragraph", content: [{ type: "text", attributes: {}, text: "Second paragraph\n" }], }, { type: "paragraph", content: [{ type: "text", attributes: {}, text: "Third paragraph\n" }], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("Should return header node", () => { let nodeH2 = { attributes: { line: { header: 2, }, }, text: "Header 2\n", }; let expectedH2 = [ { type: "header", content: [{ type: "text", ...nodeH2 }], }, ]; expect(buildNodeTree([nodeH2])).toEqual(expectedH2); let nodeH3 = { attributes: { line: { header: 3, }, }, text: "Header 3\n", }; let expectedH3 = [ { type: "header", content: [{ type: "text", ...nodeH3 }], }, ]; expect(buildNodeTree([nodeH3])).toEqual(expectedH3); let nodeH1 = { attributes: { line: { header: 1, }, }, text: "Header 1\n", }; let expectedH1 = [ { type: "header", content: [{ type: "text", ...nodeH1 }], }, ]; expect(buildNodeTree([nodeH1])).toEqual(expectedH1); }); it("Should handle italics and bold in the middle of a paragraph", () => { /** @type {Array<RTJNode>} */ let nodes = [ { attributes: {}, text: "Here is a paragraph ", }, { attributes: { bold: true, }, text: "with bold text", }, { attributes: {}, text: " and ", }, { attributes: { italic: true, }, text: "with italicized text", }, { attributes: {}, text: " and ", }, { attributes: { bold: true, italic: true, }, text: "with both", }, { attributes: {}, text: ".\n", }, ]; let expected = [ { type: "paragraph", content: nodes.map((n) => ({ type: "text", ...n })), }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("Should handle highlighted text in the middle of a paragraph", () => { let color = "#ffdddd"; /** @type {Array<RTJNode>} */ let nodes = [ { attributes: {}, text: "Here is a paragraph ", }, { attributes: { highlightedColor: color, }, text: "with highlighted text", }, { attributes: {}, text: ".\n", }, ]; let expected = [ { type: "paragraph", content: [ { type: "text", attributes: {}, text: "Here is a paragraph " }, { type: "text", attributes: { highlightedColor: color, }, text: "with highlighted text", }, { type: "text", attributes: {}, text: ".\n" }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("Should handle inline code in the middle of a paragraph", () => { /** @type {Array<RTJNode>} */ let nodes = [ { attributes: {}, text: "Here is a paragraph ", }, { attributes: { inlineCode: true, }, text: "with some code", }, { attributes: {}, text: " in it.\n", }, ]; let expected = [ { type: "paragraph", content: [ { type: "text", attributes: {}, text: "Here is a paragraph " }, { type: "text", attributes: { inlineCode: true }, text: "with some code", }, { type: "text", attributes: {}, text: " in it.\n" }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("should handle a code block", () => { /** @type {Array<RTJNode>} */ let nodes = [ { attributes: { line: { codeBlock: true, }, }, text: "Here is a code block\n", }, ]; let expected = [ { type: "code", content: nodes.map((n) => ({ type: "text", ...n })) }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("should handle a horizontal ruler", () => { /** @type {RTJNode} */ let node = { embeddedObjects: [{ type: "horizontalRuleLine" }], }; let expected = [{ type: "embedded", content: node }]; expect(buildNodeTree([node])).toEqual(expected); }); it("should handle multiple quote nodes correctly", () => { /** @type {Array<RTJNode>} */ let nodes = [ { text: "First quote line ", attributes: { line: { quote: true }, }, }, { text: "still first paragraph\n", attributes: { line: { quote: true }, }, }, { text: "Second paragraph in quote\n", attributes: { line: { quote: true }, }, }, // Add a non-quote node to ensure quote block closes properly { text: "Regular paragraph\n", }, ]; let expected = [ { type: "quote", content: [ { type: "paragraph", content: [ { type: "text", text: "First quote line ", attributes: { line: { quote: true }, }, }, { type: "text", text: "still first paragraph\n", attributes: { line: { quote: true }, }, }, ], }, { type: "paragraph", content: [ { type: "text", attributes: { line: { quote: true }, }, text: "Second paragraph in quote\n", }, ], }, ], }, { type: "paragraph", content: [{ type: "text", text: "Regular paragraph\n" }], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("should handle quotes with text formatting", () => { /** @type {Array<RTJNode>} */ let nodes = [ { text: "Quote with ", attributes: { line: { quote: true }, bold: true, }, }, { text: "mixed formatting\n", attributes: { line: { quote: true }, italic: true, }, }, ]; let expected = [ { type: "quote", content: [ { type: "paragraph", content: [ { type: "text", text: "Quote with ", attributes: { line: { quote: true }, bold: true, }, }, { type: "text", text: "mixed formatting\n", attributes: { line: { quote: true }, italic: true, }, }, ], }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); }); describe("Test lists", () => { it("should handle a simple list", () => { /** @type {Array<RTJ.Node>} */ let nodes = [ { attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "one\n", }, { attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "two\n", }, ]; let expected = [ { type: "bulleted", content: [ { type: "listItem", content: [ { type: "text", attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "one\n", }, ], }, { type: "listItem", content: [ { type: "text", attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "two\n", }, ], }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("Should handle complex lists", () => { /** @type {Array<RTJ.Node>} */ let nodes = [ { attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "And a list\n", }, { attributes: { line: { listStyle: "bulleted", indentLevel: 2, }, }, text: "Indented\n", }, { attributes: { line: { listStyle: "bulleted", indentLevel: 3, }, }, text: "again\n", }, ]; let expected = [ { type: "bulleted", content: [ { type: "listItem", content: [ { type: "text", attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "And a list\n", }, { type: "bulleted", content: [ { type: "listItem", content: [ { type: "text", attributes: { line: { listStyle: "bulleted", indentLevel: 2, }, }, text: "Indented\n", }, { type: "bulleted", content: [ { type: "listItem", content: [ { type: "text", attributes: { line: { listStyle: "bulleted", indentLevel: 3, }, }, text: "again\n", }, ], }, ], }, ], }, ], }, ], }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); it("Should handle different lists following each other", () => { /** @type {Array<RTJ.Node>} */ let nodes = [ { attributes: { line: { listStyle: "bulleted", indentLevel: 1, }, }, text: "And a bulleted list\n", }, { attributes: { line: { listStyle: "numbered", indentLevel: 1, }, }, text: "A numbered list\n", }, { attributes: { line: { listStyle: "numbered", indentLevel: 1, }, }, text: "numbered 2\n", }, ]; const expected = [ { type: "bulleted", content: [ { type: "listItem", content: [{ type: "text", ...nodes[0] }] }, ], }, { type: "numbered", content: [ { type: "listItem", content: [{ type: "text", ...nodes[1] }] }, { type: "listItem", content: [{ type: "text", ...nodes[2] }] }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); }); describe("Embedded objects", () => { it("should handle a video block", () => { /** @type {RTJ.Node} */ let node = { embeddedObjects: [ { type: "video", identifier: "B7C0EB0794D04FF3B496308ED46D179A", }, ], }; let expected = [{ type: "embedded", content: node }]; expect(buildNodeTree([node])).toEqual(expected); }); }); describe("It should correctly handle edge cases", () => { it("should handle an empty node", () => { let nodes = [ { attributes: { line: { header: 1, identifier: "5BDE10FE-4D22-47B4-A00A-82D5F6488D69", }, }, text: "Hello World!\n", }, { embeddedObjects: [ { identifier: "ADA6341371F8441696DD75932177D1D0", type: "photo", }, ], }, { text: "\n8-bit helvetica taxidermy tacos cred semiotics. plant asymmetrical.\n", }, { embeddedObjects: [ { identifier: "F589ABE4B1554A8B9AE5ED50D3B10441", type: "photo", }, ], }, { text: "\nBanh mi taxidermy tattooed vinyl.", }, { embeddedObjects: [ { identifier: "29421FE8EBCC4D969F262E17E7FB1891", type: "photo", }, ], }, { text: "Flexitarian ugh portland wolf moon keffiyeh. Vaporware shaman everyday carry brunch literally waistcoat biodiesel sus locavore. humblebrag church-key ennui cred keytar vexillologist.\n\nCupping adaptogen disrupt poke, twee humblebrag praxis godard activated charcoal ugh gluten-free art party leggings taiyaki slow-carb.\n\nPok pok offal bushwick kickstarter, cupping salvia gentrify prism copper mug pinterest.\n\nDummy text?", }, ]; let expected = [ { type: "header", content: [ { type: "text", attributes: { line: { header: 1, identifier: "5BDE10FE-4D22-47B4-A00A-82D5F6488D69", }, }, text: "Hello World!\n", }, ], }, { type: "embedded", content: { embeddedObjects: [ { identifier: "ADA6341371F8441696DD75932177D1D0", type: "photo", }, ], }, }, { type: "paragraph", content: [ { type: "text", text: "\n8-bit helvetica taxidermy tacos cred semiotics. plant asymmetrical.\n", }, ], }, { type: "embedded", content: { embeddedObjects: [ { identifier: "F589ABE4B1554A8B9AE5ED50D3B10441", type: "photo", }, ], }, }, { type: "paragraph", content: [ { type: "text", text: "\nBanh mi taxidermy tattooed vinyl." }, ], }, { type: "embedded", content: { embeddedObjects: [ { identifier: "29421FE8EBCC4D969F262E17E7FB1891", type: "photo", }, ], }, }, { type: "paragraph", content: [ { type: "text", text: "Flexitarian ugh portland wolf moon keffiyeh. Vaporware shaman everyday carry brunch literally waistcoat biodiesel sus locavore. humblebrag church-key ennui cred keytar vexillologist.\n\nCupping adaptogen disrupt poke, twee humblebrag praxis godard activated charcoal ugh gluten-free art party leggings taiyaki slow-carb.\n\nPok pok offal bushwick kickstarter, cupping salvia gentrify prism copper mug pinterest.\n\nDummy text?", }, ], }, ]; expect(buildNodeTree(nodes)).toEqual(expected); }); });