|
|
@@ -18,6 +18,48 @@ describe("contentToDoc", () => {
|
|
|
expect(doc.child(1).type.name).toBe("paragraph")
|
|
|
})
|
|
|
|
|
|
+ it("handles fenced code block with backticks", () => {
|
|
|
+ const doc = contentToDoc("```python\ndef foo():\n pass\n```")
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
+ expect(doc.child(0).type.name).toBe("code_block")
|
|
|
+ expect(doc.child(0).attrs.language).toBe("python")
|
|
|
+ expect(doc.child(0).textContent).toBe("```python\ndef foo():\n pass\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("handles fenced code block with tildes", () => {
|
|
|
+ const doc = contentToDoc("~~~js\nconsole.log('hi')\n~~~")
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
+ expect(doc.child(0).type.name).toBe("code_block")
|
|
|
+ expect(doc.child(0).attrs.language).toBe("js")
|
|
|
+ expect(doc.child(0).textContent).toBe("~~~js\nconsole.log('hi')\n~~~")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("handles fenced code block without language", () => {
|
|
|
+ const doc = contentToDoc("```\nplain code\n```")
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
+ expect(doc.child(0).type.name).toBe("code_block")
|
|
|
+ expect(doc.child(0).attrs.language).toBe("")
|
|
|
+ expect(doc.child(0).textContent).toBe("```\nplain code\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("handles code block with empty content", () => {
|
|
|
+ const doc = contentToDoc("```\n```")
|
|
|
+ expect(doc.childCount).toBe(1)
|
|
|
+ expect(doc.child(0).type.name).toBe("code_block")
|
|
|
+ expect(doc.child(0).textContent).toBe("```\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("mixes code blocks and paragraphs", () => {
|
|
|
+ const doc = contentToDoc("before\n```\ncode\n```\nafter")
|
|
|
+ expect(doc.childCount).toBe(3)
|
|
|
+ expect(doc.child(0).type.name).toBe("paragraph")
|
|
|
+ expect(doc.child(0).textContent).toBe("before")
|
|
|
+ expect(doc.child(1).type.name).toBe("code_block")
|
|
|
+ expect(doc.child(1).textContent).toBe("```\ncode\n```")
|
|
|
+ expect(doc.child(2).type.name).toBe("paragraph")
|
|
|
+ expect(doc.child(2).textContent).toBe("after")
|
|
|
+ })
|
|
|
+
|
|
|
it("handles unicode and emoji", () => {
|
|
|
const doc = contentToDoc("Hello 🌍 你好 🔥")
|
|
|
expect(doc.child(0).textContent).toBe("Hello 🌍 你好 🔥")
|
|
|
@@ -54,6 +96,48 @@ describe("docToContent", () => {
|
|
|
expect(docToContent(doc)).toBe("line1\nline2")
|
|
|
})
|
|
|
|
|
|
+ it("serializes code block with language", () => {
|
|
|
+ const doc = schema.nodes.doc.create(null, [
|
|
|
+ schema.nodes.code_block.create(
|
|
|
+ { language: "python" },
|
|
|
+ [schema.text("```python\ndef foo():\n pass\n```")],
|
|
|
+ ),
|
|
|
+ ])
|
|
|
+ expect(docToContent(doc)).toBe("```python\ndef foo():\n pass\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("serializes code block without language", () => {
|
|
|
+ const doc = schema.nodes.doc.create(null, [
|
|
|
+ schema.nodes.code_block.create(
|
|
|
+ null,
|
|
|
+ [schema.text("```\nplain code\n```")],
|
|
|
+ ),
|
|
|
+ ])
|
|
|
+ expect(docToContent(doc)).toBe("```\nplain code\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("serializes code block with empty content", () => {
|
|
|
+ const doc = schema.nodes.doc.create(null, [
|
|
|
+ schema.nodes.code_block.create(
|
|
|
+ null,
|
|
|
+ [schema.text("```\n```")],
|
|
|
+ ),
|
|
|
+ ])
|
|
|
+ expect(docToContent(doc)).toBe("```\n```")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("serializes mixed paragraphs and code blocks", () => {
|
|
|
+ const doc = schema.nodes.doc.create(null, [
|
|
|
+ schema.nodes.paragraph.create(null, [schema.text("before")]),
|
|
|
+ schema.nodes.code_block.create(
|
|
|
+ { language: "js" },
|
|
|
+ [schema.text("```js\ncode\n```")],
|
|
|
+ ),
|
|
|
+ schema.nodes.paragraph.create(null, [schema.text("after")]),
|
|
|
+ ])
|
|
|
+ expect(docToContent(doc)).toBe("before\n```js\ncode\n```\nafter")
|
|
|
+ })
|
|
|
+
|
|
|
it("handles empty paragraph", () => {
|
|
|
const doc = schema.nodes.doc.create(null, [schema.nodes.paragraph.create()])
|
|
|
expect(docToContent(doc)).toBe("")
|
|
|
@@ -84,4 +168,29 @@ describe("roundtrip", () => {
|
|
|
const doc = contentToDoc(original)
|
|
|
expect(docToContent(doc)).toBe(original)
|
|
|
})
|
|
|
+
|
|
|
+ it("fenced code block with language roundtrips", () => {
|
|
|
+ const original = "```python\ndef foo():\n pass\n```"
|
|
|
+ const doc = contentToDoc(original)
|
|
|
+ expect(docToContent(doc)).toBe(original)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("fenced code block without language roundtrips", () => {
|
|
|
+ const original = "```\nplain code\n```"
|
|
|
+ const doc = contentToDoc(original)
|
|
|
+ expect(docToContent(doc)).toBe(original)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("mixed paragraphs and code blocks roundtrips", () => {
|
|
|
+ const original = "before\n```js\ncode\n```\nafter"
|
|
|
+ const doc = contentToDoc(original)
|
|
|
+ expect(docToContent(doc)).toBe(original)
|
|
|
+ })
|
|
|
+
|
|
|
+ it("tildes fenced code block roundtrips", () => {
|
|
|
+ const original = "~~~js\nconsole.log('hi')\n~~~"
|
|
|
+ const doc = contentToDoc(original)
|
|
|
+ // Fences are preserved as-is in the text content
|
|
|
+ expect(docToContent(doc)).toBe(original)
|
|
|
+ })
|
|
|
})
|