|
@@ -1,5 +1,5 @@
|
|
|
import { describe, expect, it } from "vitest"
|
|
import { describe, expect, it } from "vitest"
|
|
|
-import { contentToDoc, docToContent } from "@/lib/content-model"
|
|
|
|
|
|
|
+import { contentToDoc, docToContent, inlineToString } from "@/lib/content-model"
|
|
|
import { schema } from "@/lib/schema"
|
|
import { schema } from "@/lib/schema"
|
|
|
|
|
|
|
|
describe("contentToDoc", () => {
|
|
describe("contentToDoc", () => {
|
|
@@ -9,13 +9,11 @@ describe("contentToDoc", () => {
|
|
|
expect(doc.child(0).textContent).toBe("hello world")
|
|
expect(doc.child(0).textContent).toBe("hello world")
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it("handles newlines as separate paragraphs", () => {
|
|
|
|
|
|
|
+ it("handles newlines as hard_break within a single paragraph", () => {
|
|
|
const doc = contentToDoc("line1\nline2")
|
|
const doc = contentToDoc("line1\nline2")
|
|
|
- expect(doc.childCount).toBe(2)
|
|
|
|
|
- expect(doc.child(0).textContent).toBe("line1")
|
|
|
|
|
- expect(doc.child(1).textContent).toBe("line2")
|
|
|
|
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
expect(doc.child(0).type.name).toBe("paragraph")
|
|
expect(doc.child(0).type.name).toBe("paragraph")
|
|
|
- expect(doc.child(1).type.name).toBe("paragraph")
|
|
|
|
|
|
|
+ expect(inlineToString(doc.child(0))).toBe("line1\nline2")
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it("handles fenced code block with backticks", () => {
|
|
it("handles fenced code block with backticks", () => {
|
|
@@ -146,10 +144,11 @@ describe("roundtrip", () => {
|
|
|
expect(docToContent(doc)).toBe(original)
|
|
expect(docToContent(doc)).toBe(original)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- it("multiline roundtrips", () => {
|
|
|
|
|
|
|
+ it("multiline roundtrips as single paragraph with hard_breaks", () => {
|
|
|
const original = "line1\nline2\nline3"
|
|
const original = "line1\nline2\nline3"
|
|
|
const doc = contentToDoc(original)
|
|
const doc = contentToDoc(original)
|
|
|
- expect(doc.childCount).toBe(3)
|
|
|
|
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
|
|
+ expect(inlineToString(doc.child(0))).toBe("line1\nline2\nline3")
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
it("unicode roundtrips", () => {
|
|
it("unicode roundtrips", () => {
|
|
@@ -240,3 +239,27 @@ describe("math block (content model)", () => {
|
|
|
expect(doc.child(0).textContent).toBe("$$\n$$")
|
|
expect(doc.child(0).textContent).toBe("$$\n$$")
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
|
|
+
|
|
|
|
|
+describe("roundtrip (hard_break preservation)", () => {
|
|
|
|
|
+ const ROUNDTRIP_CASES: [string, string][] = [
|
|
|
|
|
+ ["plain text", "hello world"],
|
|
|
|
|
+ ["single newline", "line1\nline2"],
|
|
|
|
|
+ ["double newline (paragraph break)", "para1\n\npara2"],
|
|
|
|
|
+ ["mixed newlines", "section1\nline1\nline2\n\nsection2"],
|
|
|
|
|
+ ["triple line", "line1\nline2\nline3"],
|
|
|
|
|
+ ["multiple paragraphs", "para1\n\npara2\n\npara3"],
|
|
|
|
|
+ ["code block", "```js\nconst x = 1\n```"],
|
|
|
|
|
+ ["code block with internal blank lines", "text\n\n```\nline1\n\nline2\n```\n\nafter"],
|
|
|
|
|
+ ["math block", "$$\nE = mc^2\n$$"],
|
|
|
|
|
+ ["wrapped math", "text\n\n$$\na^2 + b^2 = c^2\n$$\n\nmore"],
|
|
|
|
|
+ ["properties (motivating case)", "## Properties\n\nauthor:: Enesis Editor\nversion:: 0.1.0"],
|
|
|
|
|
+ ["single line only", "line1\nline2\nline3"],
|
|
|
|
|
+ ["empty string", ""],
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ for (const [label, input] of ROUNDTRIP_CASES) {
|
|
|
|
|
+ it(`roundtrips: ${label}`, () => {
|
|
|
|
|
+ expect(docToContent(contentToDoc(input))).toBe(input)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+})
|