Feat/extend paragraph supported attributes#7715
Conversation
🦋 Changeset detectedLatest commit: 7a1d902 The changes in this PR will be included in the next version bump. This PR includes changesets to release 72 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for tiptap-embed ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Adds paragraph/heading spacing + indentation attributes so DOCX-imported layout data isn’t dropped by ProseMirror during parsing/setContent, and updates tests/fixtures to reflect the new null-default attrs in JSON output.
Changes:
- Add
spacingBefore,spacingAfter,lineHeight,indent,firstLineIndentattributes to@tiptap/extension-paragraphand@tiptap/extension-headingvia acreateSpacingAttributes()factory. - Add unit/integration tests for parsing/rendering + JSON round-trip of the new attrs.
- Update existing JSON/HTML-related tests to include the new null-default attrs; add a changeset for both packages.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/extension-paragraph/src/utilities/create-spacing-attributes.ts | Introduces spacing/indent attribute factory for Paragraph (parse from inline styles, render back to style). |
| packages/extension-paragraph/src/paragraph.ts | Wires the new spacing/indent attributes into the Paragraph node schema. |
| packages/extension-paragraph/tests/utilities/create-spacing-attributes.spec.ts | Unit tests for the new spacing/indent attribute factory. |
| packages/extension-paragraph/tests/paragraphAttributes.spec.ts | Editor-level integration tests for Paragraph parse/render/defaults/JSON round-trip. |
| packages/extension-heading/src/utilities/create-spacing-attributes.ts | Introduces spacing/indent attribute factory for Heading (duplicated for package independence). |
| packages/extension-heading/src/heading.ts | Wires the new spacing/indent attributes into the Heading node schema alongside level. |
| packages/extension-heading/tests/headingAttributes.spec.ts | Editor-level integration tests for Heading parse/render/defaults/JSON round-trip + coexistence with level. |
| packages/html/tests/server-with-jsdom.spec.ts | Updates expected JSON to include new null-default paragraph attrs. |
| packages/html/tests/generateJSON.spec.ts | Updates expected JSON to include new null-default paragraph attrs. |
| packages/html/tests/generateHTML.spec.ts | Updates input JSON shapes for HTML generation tests to include new attrs on paragraph/heading nodes. |
| packages/extensions/tests/trailing-node.spec.ts | Updates expected heading/paragraph JSON to include new null-default attrs. |
| packages/extension-mathematics/tests/inlineMath.spec.ts | Updates expected paragraph JSON to include new null-default attrs. |
| packages/extension-list/tests/taskItem.spec.ts | Updates expected paragraph JSON in task item tests to include new null-default attrs. |
| packages/core/tests/unmounted.spec.ts | Updates expected JSON to include new null-default paragraph attrs. |
| packages/core/tests/generateJSON.spec.ts | Updates expected JSON to include new null-default paragraph attrs. |
| packages/core/tests/createNodeFromContent.spec.ts | Updates expected JSON shapes to include new null-default paragraph attrs. |
| .changeset/breezy-goats-approve.md | Adds a minor changeset for both extensions documenting the new attributes. |
packages/extension-paragraph/src/utilities/create-spacing-attributes.ts
Outdated
Show resolved
Hide resolved
packages/extension-heading/src/utilities/create-spacing-attributes.ts
Outdated
Show resolved
Hide resolved
bdbch
left a comment
There was a problem hiding this comment.
I went through this and I think it does solve the immediate problem, but I’m not sure base Paragraph and Heading are the right place for these attrs.
Adding them directly to those core extensions exposes them to every user, including people who don’t need this import/export behavior, and it also starts to overlap with other existing concepts like lineHeight.
So the fix itself makes sense, I’m just not convinced the schema change belongs on the default node extensions in this form.
Maybe a better fit would be a separate extension that adds these attributes globally to paragraph and heading only when needed, instead of exposing them by default on the base extensions.
|
|
||
| Add support for more attributes across paragraph, and heading extensions | ||
|
|
||
| **@tiptap/extension-paragraph** |
There was a problem hiding this comment.
This is a format we usually don't do. I think it makes sense to have two separate changeset files per package if the changes are not related to each other.
Changes Overview
Adds spacing and indentation attributes to the
@tiptap/extension-paragraphand@tiptap/extension-headingextensions:spacingBefore,spacingAfter,lineHeight,indent, andfirstLineIndent. These attributes match what the Tiptap Convert DOCX import API returns on paragraph and heading nodes, which were previously dropped by ProseMirror duringsetContentbecause the schemas didn't define them.Implementation Approach
Following the factory pattern established in the table extension (
createAlignAttribute,createBorderAttributes), a sharedcreateSpacingAttributes()factory function was created that returns all 5 attribute definitions. Each attribute:nullmargin-top,margin-bottom,line-height,padding-left,text-indent)Since
extension-paragraphandextension-headingare separate packages with no cross-dependency, the factory is duplicated in each package'ssrc/utilities/directory.Testing Done
54 new tests across 3 test files:
extension-paragraph/__tests__/utilities/create-spacing-attributes.spec.ts(22 tests) — Unit tests for the factory: all 5 attributes created with correct defaults, parse from inline styles, render to inline styles, null handlingextension-paragraph/__tests__/paragraphAttributes.spec.ts(16 tests) — Integration tests on<p>: parse, render, default null, and JSON round-trip for all 5 attributesextension-heading/__tests__/headingAttributes.spec.ts(16 tests) — Integration tests on<h1>–<h6>: parse, render, default null, JSON round-trip, coexistence withlevelattributeUpdated 9 existing test files to include the new null-default attributes in expected JSON shapes (
createNodeFromContent,generateJSON,unmounted,taskItem,inlineMath,trailing-node,generateHTML,server-with-jsdom).Full test suite: 825 tests passing across 81 test files.
Verification Steps
cd oss && pnpm run test:unit— all 825 tests passParagraphextension, calleditor.commands.setContent({ type: 'doc', content: [{ type: 'paragraph', attrs: { spacingBefore: 28, spacingAfter: 13, lineHeight: 1.6 }, content: [{ type: 'text', text: 'Hello' }] }] })— verify the<p>element renders withmargin-top: 28px; margin-bottom: 13px; line-height: 1.6inline styleseditor.getJSON()— verify the spacing attributes round-trip correctlyAdditional Notes
These attributes are returned by the Tiptap Convert DOCX import API on paragraph and heading nodes (derived from
w:spacingandw:indDOCX XML elements). Previously ProseMirror silently dropped them duringsetContentbecause the schema didn't define them. With this change, per-paragraph spacing and indentation from DOCX imports are preserved end-to-end.Note: ProseMirror requires all defined attributes to have an explicit default value. Using
nullmeans these attrs always appear ingetJSON()output even when unset — this is a ProseMirror constraint, not a design choice. Usingundefinedas default would make the attributes required and throw errors when creating nodes without them.Checklist
Related Issues
N/A — Part of the experimental CSS export style mapping feature (
feat/experimental-css-export-style-mapping).