fix: preserve line spacing and indentation on Google Docs paste#2183
Conversation
When pasting from Google Docs, line spacing and paragraph indentation were lost because parseAttrs only read SuperDoc's internal data-* attributes. Add CSS inline style fallback to extract lineHeight, marginTop, marginBottom, and marginLeft from node.style and convert to OOXML twips. Data attributes still take priority for regression safety. Closes superdoc-dev#2151
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5937c7f1dc
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
Handle %, px, and pt line-height values correctly instead of treating all values as unitless multipliers. Percentage values are normalized to a multiplier, while px/pt values are stored as exact line spacing.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7aada6407e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
Replace duplicated unit if/else chains with a single parseCssLength helper backed by a CSS_LENGTH_TO_PT conversion map. Supports pt, px, in, cm, mm; rejects unrecognized units (em, rem, etc.) to avoid misinterpretation. Percentage lineHeight is normalized to a multiplier.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57e66763b7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
Allow zero-valued margins (margin-top: 0, etc.) through parseCssLength so they are stored as 0 twips in paragraphProperties. This prevents the style-engine from filling in non-zero defaults for paragraphs that explicitly have no spacing/indent. Zero lineHeight remains rejected.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aaf3c15a2c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
Map text-indent to indent.firstLine (positive) or indent.hanging (negative) so pasted HTML with first-line/hanging indentation renders correctly. Allow negative values through parseCssLength for this case while keeping >= 0 guards on margins and spacing callers.
|
@codex review |
|
Codex Review: Didn't find any major issues. Delightful! ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
caio-pizzol
left a comment
There was a problem hiding this comment.
thanks for the contribution @gpardhivvarma!
the CSS fallback approach is solid and the test coverage is thorough.
left a few inline comments - nothing blocking, mostly small tweaks.
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.js
Outdated
Show resolved
Hide resolved
packages/super-editor/src/extensions/paragraph/helpers/parseAttrs.test.js
Outdated
Show resolved
Hide resolved
- Use exact 72/96 ratio for px→pt conversion (matches PX_PER_PT in pm-adapter) - Add comment explaining the 1.15 inversion from normalizeLineValue - Skip Number() coercion for lineRule to preserve 'auto' string value - Update tests to use exact ratio and fix lineRule expectation
There was a problem hiding this comment.
@gpardhivvarma all three items from last round are addressed — 72 / 96 is exact, lineRule is preserved, and the 1.15 comment makes the inversion clear. no new issues in the incremental diff.
tested locally — CSS spacing values (line-height, margin-top/bottom) are being picked up and converted to twips correctly on Google Docs paste. looks good to merge.
note: text-align (center/right/justify) is not preserved on paste either, should be fixed on another PR
|
🎉 This PR is included in superdoc v1.17.0-next.32 The release is available on GitHub release |
|
🎉 This PR is included in superdoc-cli v0.2.0-next.27 The release is available on GitHub release |
Will look into it and create a new PR |
Add CSS text-align fallback in parseAttrs to extract justification from inline styles (e.g. `<p style="text-align: center">`), following the same pattern as the existing spacing/indent CSS fallbacks from PR superdoc-dev#2183. Maps CSS values (left, center, right, justify, start, end) to OOXML justification values.
# [1.17.0](v1.16.0...v1.17.0) (2026-02-28) ### Bug Fixes * active track change ([#2163](#2163)) ([108c14d](108c14d)) * add currentTotalPages getter and pagination-update event ([#2202](#2202)) ([95b4579](95b4579)), closes [#958](#958) * always call resolveComment after custom TC bubble handlers (SD-2049) ([#2204](#2204)) ([34fb4e0](34fb4e0)) * backward replace insert text ([#2172](#2172)) ([66f0849](66f0849)) * **collaboration:** deduplicate updateYdocDocxData during replaceFile (SD-1920) ([#2162](#2162)) ([52962fc](52962fc)) * **comments:** cross-page collision avoidance for floating comment bubbles (SD-1998) ([#2180](#2180)) ([6cfbeca](6cfbeca)) * **comments:** remove synchronous dispatch from plugin apply() (SD-1940) ([#2157](#2157)) ([887175b](887175b)) * **css:** scope ProseMirror CSS to prevent bleeding into host apps (SD-1850) ([#2134](#2134)) ([b9d98fa](b9d98fa)) * document-api improvements, plan mode, query.match, mutations ([6221580](6221580)) * **document-api:** delete table cell fix ([#2209](#2209)) ([5e5c43f](5e5c43f)) * **document-api:** distribute columns command fixes ([#2207](#2207)) ([8f4eaf7](8f4eaf7)) * **document-api:** fix cell shading in document api ([#2215](#2215)) ([456f60e](456f60e)) * **document-api:** insert table cell ([#2210](#2210)) ([357ee90](357ee90)) * **document-api:** plan-engine reliability fixes and error diagnostics ([#2185](#2185)) ([abfd81b](abfd81b)) * **document-api:** split table cell command ([#2217](#2217)) ([0b3e2b4](0b3e2b4)) * **document-api:** split table command ([#2214](#2214)) ([ec31699](ec31699)) * **editor:** render styles applied inside SDT fields (SD-2011) ([#2188](#2188)) ([9c34be3](9c34be3)) * **editor:** selection highlight flickers when dragging across mark boundaries (SD-2024) ([#2205](#2205)) ([ba03e76](ba03e76)) * extract duplicate block identity normalization from docxImporter ([7f7ff93](7f7ff93)) * improve backspace behavior near run boundaries for tracked changes ([#2175](#2175)) ([6c9c7a3](6c9c7a3)) * **layout:** per-section footer constraints for multi-section docs (SD-1837) ([#2022](#2022)) ([e11acc5](e11acc5)) * normalize review namespace into trackChanges, harden input validation ([33e907b](33e907b)) * outside click for toolbar dropdown ([#2174](#2174)) ([5f859c7](5f859c7)) * preserve line spacing and indentation on Google Docs paste ([#2183](#2183)) ([b9a7357](b9a7357)), closes [#2151](#2151) * **shapes:** render grouped DrawingML shapes with custom geometry (SD-1877) ❇️ ([#2105](#2105)) ([14985a5](14985a5)) * support cell spacing ([#1879](#1879)) ([1639967](1639967)) * **tables:** expand auto-width tables to fill available page width ([#2109](#2109)) ([15f36bc](15f36bc)) * text highlight on export ([#2189](#2189)) ([9cbd022](9cbd022)) * track highlight changes ([#2192](#2192)) ([e164625](e164625)) * undo/redo actions ([#2161](#2161)) ([495e92f](495e92f)) ### Features * allow custom accept/reject handlers for TC bubbles ([#1921](#1921)) ([e30abf6](e30abf6)) * **document-api:** add format operations font size alignment color font family ([#2179](#2179)) ([f19c688](f19c688)) * **document-api:** add plan-based mutation engine with query.match and style capture ([#2160](#2160)) ([365293a](365293a)) * **document-api:** doc default initial styles ([#2184](#2184)) ([f25e41f](f25e41f)) * **document-api:** include anchored text in comments list response ([#2177](#2177)) ([b3a2912](b3a2912)) * **document-api:** inline formatting parity core end-to-end ([#2197](#2197)) ([b405b03](b405b03)) * **document-api:** inline formatting rpr parity ([#2198](#2198)) ([41ab771](41ab771)) * **document-api:** section commands ([#2199](#2199)) ([ec4abe3](ec4abe3)) * **document-api:** support deleting entire block nodes not only text ([#2181](#2181)) ([2897246](2897246)) * **document-api:** table of contents commands ([#2200](#2200)) ([baa72c4](baa72c4)) * **document-api:** tables namespace and commands ([#2182](#2182)) ([b80ee31](b80ee31)) * **markdown:** add markdown override to sdk, improve conversion ([#2196](#2196)) ([04a1c71](04a1c71)) * preserve w:view setting through DOCX round-trip ([#2190](#2190)) ([48b4210](48b4210)), closes [#2070](#2070) * **track-changes:** clear comment bubbles when bulk accept or reject TCs ([#2159](#2159)) ([27fbe8e](27fbe8e)) ### Performance Improvements * **comments:** batch tracked change comment creation on load ([#2166](#2166)) ([0c2eca5](0c2eca5)) * **comments:** batch tracked change creation and virtualize floating bubbles (SD-1997) ([#2168](#2168)) ([70fd7d9](70fd7d9))
Summary
parseAttrs.jsso line spacing (lineHeight), paragraph spacing (marginTop/marginBottom), indentation (marginLeft), and first-line/hanging indent (textIndent) are preserved when pasting from Google Docs or other sources that use inline CSS instead of SuperDoc'sdata-*attributesparseCssLengthhelper backed by aCSS_LENGTH_TO_PTconversion map supportingpt,px,in,cm,mm— unrecognized units (em,rem, etc.) are safely ignored72 / 96ratio for px→pt conversion, matchingPX_PER_PTin pm-adapterline-heightunits: unitless and%values are stored as auto multipliers, while absolute lengths are stored as exact line spacing in twipsnormalizeLineValue(value * 1.15 / 240) so values round-trip correctlytext-indenttoindent.firstLineand negativetext-indenttoindent.hangingmargin-top: 0) as0twips to prevent the style-engine from applying non-zero defaultsNumber()coercion forlineRuleindata-spacingparsing to preserve the'auto'string valueCloses #2151
Test plan
data-spacing/data-indentbehavior is unchangedpnpm test— all parseAttrs tests pass (28/28)