From bb5bb52244c57f148944381e0df0ed44e37886f4 Mon Sep 17 00:00:00 2001 From: claude-stand Date: Thu, 2 Jul 2026 18:36:53 +0300 Subject: [PATCH] fix(git-sync): round-trip paragraph/heading text alignment (review #10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligned paragraphs were exported as
which had NO matching import parse rule — the div was unwrapped and the alignment lost on every round trip. Emit a styled

instead, and give the textAlign global attribute (docmost-schema) an explicit parseHTML that reads element.style.textAlign (and legacy align=) plus a renderHTML that writes the style. Now heading/paragraph alignment survives Docmost->git->Docmost. Verified on stand: a textAlign=center paragraph exports as

, and after a git-side edit + re-import the paragraph still has textAlign=center in the DB (was null before). Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/git-sync/src/lib/docmost-schema.ts | 14 +++++++++++++- packages/git-sync/src/lib/markdown-converter.ts | 7 ++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/git-sync/src/lib/docmost-schema.ts b/packages/git-sync/src/lib/docmost-schema.ts index 249013fa..276efe90 100644 --- a/packages/git-sync/src/lib/docmost-schema.ts +++ b/packages/git-sync/src/lib/docmost-schema.ts @@ -238,7 +238,19 @@ const DocmostAttributes = Extension.create({ attributes: { id: { default: null }, indent: { default: null }, - textAlign: { default: null }, + // textAlign must round-trip the exported `

` + // (and the legacy `<... align="…">`) form (review #10). Without an + // explicit parseHTML the default reads a bare `textAlign` attribute + // (never present), so alignment was silently dropped on every import. + textAlign: { + default: null, + parseHTML: (el: HTMLElement) => + el.style?.textAlign || el.getAttribute("align") || null, + renderHTML: (attrs: Record) => + attrs.textAlign + ? { style: `text-align: ${attrs.textAlign}` } + : {}, + }, }, }, { diff --git a/packages/git-sync/src/lib/markdown-converter.ts b/packages/git-sync/src/lib/markdown-converter.ts index 113894a5..8347e1b0 100644 --- a/packages/git-sync/src/lib/markdown-converter.ts +++ b/packages/git-sync/src/lib/markdown-converter.ts @@ -97,7 +97,12 @@ export function convertProseMirrorToMarkdown(content: any): string { const text = nodeContent.map(processNode).join(""); const align = node.attrs?.textAlign; if (align && align !== "left") { - return `

${text}
`; + // Emit alignment as a styled `

` (review #10). The old + // `

` had NO matching import parse rule — the div was + // unwrapped and alignment lost on every round trip. A styled `

` + // round-trips: the paragraph parse rule (tag:"p") matches and the + // textAlign global-attribute parseHTML (docmost-schema) reads the style. + return `

${text}

`; } return text || "";