-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(extension-table): add markdown table column alignment support #7610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
weilinzung
wants to merge
9
commits into
ueberdosis:main
Choose a base branch
from
weilinzung:table-alignments
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
62ff979
chore: initial
weilinzung 8832e48
chore: update demo
weilinzung 5682b62
chore: update to utils
weilinzung af5b2ac
chore: cleanup
weilinzung c0bae81
chore: adjust demo table width
weilinzung aacd40a
chore: add changeset
weilinzung 3dc0bfe
Merge branch 'main' into table-alignments
weilinzung ea90c95
Merge branch 'main' into table-alignments
weilinzung fad545f
Merge branch 'main' into table-alignments
weilinzung File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@tiptap/extension-table': minor | ||
| --- | ||
|
|
||
| Added Markdown table alignment support. The `TableCell` and `TableHeader` nodes now have an `align` attribute (`left`, `center`, `right`) that is parsed from Markdown column alignment markers (`:---`, `---:`, `:---:`) and serialized back when rendering to Markdown. Alignment is also parsed from and rendered to HTML via `style="text-align: ..."`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import Document from '@tiptap/extension-document' | ||
| import Paragraph from '@tiptap/extension-paragraph' | ||
| import { TableKit } from '@tiptap/extension-table' | ||
| import Text from '@tiptap/extension-text' | ||
| import { MarkdownManager } from '@tiptap/markdown' | ||
| import { describe, expect, it } from 'vitest' | ||
|
|
||
| describe('table markdown alignment', () => { | ||
| const markdownManager = new MarkdownManager({ | ||
| extensions: [Document, Paragraph, Text, TableKit], | ||
| }) | ||
|
|
||
| it('should parse and serialize left/right/center table alignment', () => { | ||
| const markdown = `| left | right | center | | ||
| | :---- | ----: | :-----: | | ||
| | a | b | c |` | ||
|
|
||
| const parsed = markdownManager.parse(markdown) | ||
| const table = parsed.content?.[0] | ||
|
|
||
| expect(table?.type).toBe('table') | ||
|
|
||
| const headerCells = table?.content?.[0]?.content || [] | ||
|
|
||
| expect(headerCells[0]?.attrs?.align).toBe('left') | ||
| expect(headerCells[1]?.attrs?.align).toBe('right') | ||
| expect(headerCells[2]?.attrs?.align).toBe('center') | ||
|
|
||
| const serialized = markdownManager.serialize(parsed) | ||
|
|
||
| expect(serialized).toContain('| left | right | center |') | ||
| expect(serialized).toMatch(/\|\s*:[-]+\s*\|\s*[-]+:\s*\|\s*:[-]+:\s*\|/) | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import type { Attribute } from '@tiptap/core' | ||
|
|
||
| /** | ||
| * Supported table cell alignment values | ||
| */ | ||
| export enum TableCellAlign { | ||
| Left = 'left', | ||
| Right = 'right', | ||
| Center = 'center', | ||
| } | ||
|
|
||
| /** | ||
| * Normalize unknown input into a supported table alignment | ||
| * | ||
| * @param value - A potential alignment value | ||
| * @returns A valid TableCellAlign value or null | ||
| */ | ||
| export function normalizeTableCellAlign(value: unknown): TableCellAlign | null { | ||
| if (value === TableCellAlign.Left || value === TableCellAlign.Right || value === TableCellAlign.Center) { | ||
| return value | ||
| } | ||
|
|
||
| return null | ||
| } | ||
|
|
||
| /** | ||
| * Parse table cell alignment from an HTML element | ||
| * | ||
| * Prefers inline style (${"`"}text-align${"`"}) and falls back to the legacy | ||
| * ${"`"}align${"`"} attribute. | ||
| * | ||
| * @param element - The table cell/header DOM element | ||
| * @returns A valid TableCellAlign value or null | ||
| */ | ||
| export function parseAlign(element: HTMLElement): TableCellAlign | null { | ||
| const styleAlign = (element.style.textAlign || '').trim().toLowerCase() | ||
| const attrAlign = (element.getAttribute('align') || '').trim().toLowerCase() | ||
| const align = styleAlign || attrAlign | ||
|
|
||
| return normalizeTableCellAlign(align) | ||
| } | ||
|
|
||
| /** | ||
| * Normalize alignment from a generic attrs object that may include an align field | ||
| * | ||
| * @param attributes - A node attrs-like object with an optional align field | ||
| * @returns A valid TableCellAlign value or null. | ||
| */ | ||
| export function normalizeTableCellAlignFromAttributes( | ||
| attributes: { align?: TableCellAlign } | null | undefined, | ||
| ): TableCellAlign | null { | ||
| return normalizeTableCellAlign(attributes?.align) | ||
| } | ||
|
|
||
| /** | ||
| * Create a reusable Tiptap attribute config for table alignment | ||
| * | ||
| * @returns A Tiptap Attribute definition that parses and renders table alignment | ||
| */ | ||
| export function createAlignAttribute(): Attribute { | ||
| return { | ||
| default: null, | ||
| parseHTML: (element: HTMLElement) => parseAlign(element), | ||
| renderHTML: (attributes: { align?: TableCellAlign | null }) => { | ||
| if (!attributes.align) { | ||
| return {} | ||
| } | ||
|
|
||
| return { | ||
| style: `text-align: ${attributes.align}`, | ||
| } | ||
| }, | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.