From 6218dcffd0be4ee4cc168229bc8ca8123ee8d717 Mon Sep 17 00:00:00 2001 From: yousefed Date: Thu, 4 Dec 2025 14:02:11 +0100 Subject: [PATCH 1/6] fix html diff error with whitespace --- examples/09-ai/02-playground/src/data/aimodels.ts | 4 ++-- packages/core/src/api/parsers/html/parseHTML.ts | 1 + packages/core/src/schema/blocks/createSpec.ts | 1 + .../xl-ai/src/api/formats/html-blocks/tools/rebaseTool.ts | 8 ++++++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/09-ai/02-playground/src/data/aimodels.ts b/examples/09-ai/02-playground/src/data/aimodels.ts index 344f340b3a..329805d1b2 100644 --- a/examples/09-ai/02-playground/src/data/aimodels.ts +++ b/examples/09-ai/02-playground/src/data/aimodels.ts @@ -11,8 +11,8 @@ export const AI_MODELS = [ "mistral.chat/mistral-medium-latest", "mistral.chat/ministral-3b-latest", "mistral.chat/ministral-8b-latest", - "anthropic.chat/claude-opus-4-1", - "anthropic.chat/claude-sonnet-4-0", + "anthropic.chat/claude-opus-4-5", + "anthropic.chat/claude-sonnet-4-5", "anthropic.chat/claude-3-7-sonnet-latest", "anthropic.chat/claude-3-5-haiku-latest", "albert-etalab.chat/albert-large", diff --git a/packages/core/src/api/parsers/html/parseHTML.ts b/packages/core/src/api/parsers/html/parseHTML.ts index 43f3dc4559..8cb63d9f0d 100644 --- a/packages/core/src/api/parsers/html/parseHTML.ts +++ b/packages/core/src/api/parsers/html/parseHTML.ts @@ -23,6 +23,7 @@ export function HTMLToBlocks< const parentNode = parser.parse(htmlNode, { topNode: pmSchema.nodes["blockGroup"].create(), + preserveWhitespace: true }); const blocks: Block[] = []; diff --git a/packages/core/src/schema/blocks/createSpec.ts b/packages/core/src/schema/blocks/createSpec.ts index 5a404c2459..b5dfef4123 100644 --- a/packages/core/src/schema/blocks/createSpec.ts +++ b/packages/core/src/schema/blocks/createSpec.ts @@ -97,6 +97,7 @@ export function getParseRules< const parser = DOMParser.fromSchema(schema); const parsed = parser.parse(clone, { topNode: schema.nodes.paragraph.create(), + preserveWhitespace: true, }); return parsed.content; diff --git a/packages/xl-ai/src/api/formats/html-blocks/tools/rebaseTool.ts b/packages/xl-ai/src/api/formats/html-blocks/tools/rebaseTool.ts index 7e949c02f6..ce19c6dc0e 100644 --- a/packages/xl-ai/src/api/formats/html-blocks/tools/rebaseTool.ts +++ b/packages/xl-ai/src/api/formats/html-blocks/tools/rebaseTool.ts @@ -48,8 +48,12 @@ export async function createHTMLRebaseTool( ); if (steps.length) { - // console.error("html diff", steps); - throw new Error("html diff"); + throw new Error("html diff", { + cause: { + html, + htmlBlock + } + }); } return rebaseTool(editor, tr); From 743b0d6b86846b2c460761812096a847337bfc5e Mon Sep 17 00:00:00 2001 From: yousefed Date: Thu, 4 Dec 2025 14:45:09 +0100 Subject: [PATCH 2/6] improve logging --- .../src/api/formats/base-tools/createUpdateBlockTool.ts | 8 +++++--- packages/xl-ai/src/api/formats/base-tools/delete.ts | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/xl-ai/src/api/formats/base-tools/createUpdateBlockTool.ts b/packages/xl-ai/src/api/formats/base-tools/createUpdateBlockTool.ts index 645914eada..1394e247c4 100644 --- a/packages/xl-ai/src/api/formats/base-tools/createUpdateBlockTool.ts +++ b/packages/xl-ai/src/api/formats/base-tools/createUpdateBlockTool.ts @@ -143,11 +143,13 @@ export function createUpdateBlockTool(config: { const block = editor.getBlock(id); if (!block) { - // eslint-disable-next-line no-console - console.error("BLOCK NOT FOUND", id); return { ok: false, - error: "block not found", + error: new Error("Block not found (update)", { + cause: { + blockId: id, + }, + }), }; } diff --git a/packages/xl-ai/src/api/formats/base-tools/delete.ts b/packages/xl-ai/src/api/formats/base-tools/delete.ts index 69642a9ddb..dc109bf9a0 100644 --- a/packages/xl-ai/src/api/formats/base-tools/delete.ts +++ b/packages/xl-ai/src/api/formats/base-tools/delete.ts @@ -62,7 +62,11 @@ export const deleteBlockTool = ( if (!block) { return { ok: false, - error: "block not found", + error: new Error("Block not found (delete)", { + cause: { + blockId: id, + }, + }), }; } From c2badf56127d7114f488e50c2750e37a77c6e0c6 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Mon, 15 Dec 2025 12:11:12 +0100 Subject: [PATCH 3/6] fix: only preserveWhitespace on node content See [this description for more details](https://github.com/TypeCellOS/BlockNote/pull/2230#issuecomment-3655063742) --- packages/core/src/api/parsers/html/parseHTML.ts | 1 - .../core/src/api/parsers/markdown/parseMarkdown.ts | 11 +++++++++++ .../parse/__snapshots__/html/mixedTextTableCell.json | 5 ++++- .../parse/__snapshots__/html/notion.json | 3 ++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/core/src/api/parsers/html/parseHTML.ts b/packages/core/src/api/parsers/html/parseHTML.ts index 8cb63d9f0d..43f3dc4559 100644 --- a/packages/core/src/api/parsers/html/parseHTML.ts +++ b/packages/core/src/api/parsers/html/parseHTML.ts @@ -23,7 +23,6 @@ export function HTMLToBlocks< const parentNode = parser.parse(htmlNode, { topNode: pmSchema.nodes["blockGroup"].create(), - preserveWhitespace: true }); const blocks: Block[] = []; diff --git a/packages/core/src/api/parsers/markdown/parseMarkdown.ts b/packages/core/src/api/parsers/markdown/parseMarkdown.ts index d329a5d19c..e98ef00baa 100644 --- a/packages/core/src/api/parsers/markdown/parseMarkdown.ts +++ b/packages/core/src/api/parsers/markdown/parseMarkdown.ts @@ -93,6 +93,17 @@ export function markdownToHTML(markdown: string): string { } }, code, + blockquote: (state: any, node: any) => { + const result = { + type: "element", + tagName: "blockquote", + properties: {}, + // The only difference from the original is that we don't wrap the children with line endings + children: state.wrap(state.all(node), false), + }; + state.patch(node, result); + return state.applyData(node, result); + }, }, }) .use(rehypeStringify) diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/mixedTextTableCell.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/mixedTextTableCell.json index 6c94cdc0ef..40018a5ae2 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/mixedTextTableCell.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/mixedTextTableCell.json @@ -15,7 +15,10 @@ { "styles": {}, "text": "Table Cell -Table Cell Table Cell", +Table Cell + + Table Cell +", "type": "text", }, ], diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/notion.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/notion.json index 9b9d39ca35..7502bc6d5a 100644 --- a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/notion.json +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/notion.json @@ -169,7 +169,8 @@ "content": [ { "styles": {}, - "text": "Paragraph With Hard Break", + "text": "Paragraph +With Hard Break", "type": "text", }, ], From d38ecde879cc90277fa31effadd8f8f1d96be891 Mon Sep 17 00:00:00 2001 From: yousefed Date: Mon, 15 Dec 2025 14:33:22 +0100 Subject: [PATCH 4/6] add test --- .../core/src/api/parsers/html/parseHTML.ts | 2 ++ .../html/trailing whitespace.json | 19 +++++++++++++++++++ .../parse/parseTestInstances.ts | 7 +++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/trailing whitespace.json diff --git a/packages/core/src/api/parsers/html/parseHTML.ts b/packages/core/src/api/parsers/html/parseHTML.ts index 43f3dc4559..2d0290bd68 100644 --- a/packages/core/src/api/parsers/html/parseHTML.ts +++ b/packages/core/src/api/parsers/html/parseHTML.ts @@ -23,6 +23,8 @@ export function HTMLToBlocks< const parentNode = parser.parse(htmlNode, { topNode: pmSchema.nodes["blockGroup"].create(), + // TODO: include or not? + preserveWhitespace: true, }); const blocks: Block[] = []; diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/trailing whitespace.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/trailing whitespace.json new file mode 100644 index 0000000000..22a793ba0b --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/trailing whitespace.json @@ -0,0 +1,19 @@ +[ + { + "children": [], + "content": [ + { + "styles": {}, + "text": "hello, ", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts index b3257825ae..0af90256db 100644 --- a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts +++ b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts @@ -935,6 +935,13 @@ console.log("Third Line")`, testCase: { name: "divider", content: `
` }, executeTest: testParseHTML, }, + { + testCase: { + name: "trailing whitespace", + content: `

hello,

`, + }, + executeTest: testParseHTML, + }, ]; export const parseTestInstancesMarkdown: TestInstance< From 106378eb1dcf9676cbe6dcc7bd9ab311a97f1a19 Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Mon, 15 Dec 2025 15:01:21 +0100 Subject: [PATCH 5/6] fix: preserveWhitespace for our parse rule --- packages/core/src/api/parsers/html/parseHTML.ts | 2 -- packages/core/src/schema/blocks/createSpec.ts | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/api/parsers/html/parseHTML.ts b/packages/core/src/api/parsers/html/parseHTML.ts index 2d0290bd68..43f3dc4559 100644 --- a/packages/core/src/api/parsers/html/parseHTML.ts +++ b/packages/core/src/api/parsers/html/parseHTML.ts @@ -23,8 +23,6 @@ export function HTMLToBlocks< const parentNode = parser.parse(htmlNode, { topNode: pmSchema.nodes["blockGroup"].create(), - // TODO: include or not? - preserveWhitespace: true, }); const blocks: Block[] = []; diff --git a/packages/core/src/schema/blocks/createSpec.ts b/packages/core/src/schema/blocks/createSpec.ts index b5dfef4123..1c9fa38f9a 100644 --- a/packages/core/src/schema/blocks/createSpec.ts +++ b/packages/core/src/schema/blocks/createSpec.ts @@ -70,6 +70,8 @@ export function getParseRules< return props; }, + // Because we do the parsing ourselves, we want to preserve whitespace for content we've parsed + preserveWhitespace: true, getContent: config.content === "inline" || config.content === "none" ? (node, schema) => { From fcbc02c58268c1c35bd235c6087f0bb79b7a29ec Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Mon, 15 Dec 2025 15:24:47 +0100 Subject: [PATCH 6/6] test: add prefix test --- .../__snapshots__/html/whitespace prefix.json | 19 +++++++++++++++++++ .../parse/parseTestInstances.ts | 7 +++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/src/unit/core/formatConversion/parse/__snapshots__/html/whitespace prefix.json diff --git a/tests/src/unit/core/formatConversion/parse/__snapshots__/html/whitespace prefix.json b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/whitespace prefix.json new file mode 100644 index 0000000000..2625b5107a --- /dev/null +++ b/tests/src/unit/core/formatConversion/parse/__snapshots__/html/whitespace prefix.json @@ -0,0 +1,19 @@ +[ + { + "children": [], + "content": [ + { + "styles": {}, + "text": " hello,", + "type": "text", + }, + ], + "id": "1", + "props": { + "backgroundColor": "default", + "textAlignment": "left", + "textColor": "default", + }, + "type": "paragraph", + }, +] \ No newline at end of file diff --git a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts index 0af90256db..d280485923 100644 --- a/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts +++ b/tests/src/unit/core/formatConversion/parse/parseTestInstances.ts @@ -942,6 +942,13 @@ console.log("Third Line")`, }, executeTest: testParseHTML, }, + { + testCase: { + name: "whitespace prefix", + content: `

hello,

`, + }, + executeTest: testParseHTML, + }, ]; export const parseTestInstancesMarkdown: TestInstance<