bug: list items are cut off on left edge inside table (SD-1836)#1996
bug: list items are cut off on left edge inside table (SD-1836)#1996luccas-harbour wants to merge 2 commits intomainfrom
Conversation
7f70b78 to
8b0e219
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b0e21929e
ℹ️ 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".
| // Align text start to the marker start position (gutter spacing comes from marker padding) | ||
| lineEl.style.paddingLeft = `${markerStartPos}px`; | ||
| // Position marker within the container | ||
| if (['center', 'right'].includes(markerJustification)) { |
There was a problem hiding this comment.
Apply anchor offset for left-justified table list markers
This block only applies marker/text offset logic for center and right, so the default left case never uses anchorPoint to position the first line. In table list paragraphs with non-zero list indents/hanging indents, the marker and following text are laid out from the cell edge instead of the computed list anchor, which shifts content left and can still clip near the table border.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
left-justified markers start at x=0 in the container -- anchorPoint offset is not applied. continuation lines get paddingLeft = indentLeftPx, so first-line text won't align with body text.
maybe lineEl.paddingLeft = anchorPoint would fix this (like in renderer.ts)
| markerMeasure, | ||
| indentLeftPx, | ||
| hangingIndentPx, | ||
| firstLineIndentPx, | ||
| }); |
There was a problem hiding this comment.
Pass paragraph tab stops when rendering table list markers
renderListMarker now computes tab spacing from tabsPx, but this call site never forwards wordLayout?.tabsPx, so explicit tab stops from the paragraph are dropped for list items inside table cells. Documents that use custom list tab stops will therefore fall back to default/implicit tab widths and render marker-to-text spacing incorrectly.
Useful? React with 👍 / 👎.
caio-pizzol
left a comment
There was a problem hiding this comment.
added a few comments!
also worth mentioning - we might need to upload the sample/test file to R2 so we can run visual testing against it
| * This is applied when a gutter width is not explicitly provided in the marker layout. | ||
| * The 8px default matches Microsoft Word's standard list marker spacing. | ||
| */ | ||
| const LIST_MARKER_GAP = 8; |
There was a problem hiding this comment.
LIST_MARKER_GAP is dead code after the rewrite -- no longer referenced.
| * Word layout information for paragraph list markers. | ||
| * Contains positioning, styling, and rendering details for list markers (bullets/numbers). | ||
| */ | ||
| type WordLayoutMarker = { |
There was a problem hiding this comment.
local WordLayoutMarker/WordLayoutInfo duplicate types in @superdoc/contracts.
maybe import from contracts to stay in sync?
| markerStartPos = anchorPoint - markerTextWidth; | ||
| currentPos = anchorPoint; | ||
| } else { | ||
| markerStartPos = anchorPoint - markerTextWidth / 2; |
There was a problem hiding this comment.
center justification computes left = anchorPoint - markerTextWidth (half-width subtracted twice), identical to right-justified positioning. renderer.ts line 2305 has the same math -- intentional, or pre-existing bug?
| // Align text start to the marker start position (gutter spacing comes from marker padding) | ||
| lineEl.style.paddingLeft = `${markerStartPos}px`; | ||
| // Position marker within the container | ||
| if (['center', 'right'].includes(markerJustification)) { |
There was a problem hiding this comment.
left-justified markers start at x=0 in the container -- anchorPoint offset is not applied. continuation lines get paddingLeft = indentLeftPx, so first-line text won't align with body text.
maybe lineEl.paddingLeft = anchorPoint would fix this (like in renderer.ts)
| lineEl.style.paddingLeft = `${markerStartPos}px`; | ||
| // Position marker within the container | ||
| if (['center', 'right'].includes(markerJustification)) { | ||
| lineEl.style.paddingLeft = parseFloat(lineEl.style.paddingLeft || '0') + currentPos + listTabWidth + 'px'; |
There was a problem hiding this comment.
paddingLeft includes listTabWidth, but the separator element (width listTabWidth) is a sibling outside lineEl -- tab width counted twice. text shifts one tab-width too far right.
should we drop listTabWidth from the padding or move the separator inside lineEl?
| // Create wrapper for this paragraph's SDT metadata | ||
| // Use absolute positioning within the content container to stack blocks vertically | ||
| const paraWrapper = doc.createElement('div'); | ||
| paraWrapper.classList.add('superdoc-table-paragraph'); |
There was a problem hiding this comment.
superdoc-table-paragraph class added but no CSS or JS references it.
| * This creates a container with the marker positioned absolutely | ||
| * and the line content positioned with appropriate padding. | ||
| */ | ||
| const lineContainer = renderListMarker({ |
There was a problem hiding this comment.
tabsPx is accepted but never passed -- explicit tab stops from the document will be ignored in table cells, falling back to default 48px intervals.
should we add tabsPx to WordLayoutInfo and pass it here?
| @@ -0,0 +1,60 @@ | |||
| /** | |||
There was a problem hiding this comment.
extraction is justified (2 call sites) but the export has no JSDoc.
let's add a one-liner describing what it does.
| ): number => { | ||
| const nextDefaultTabStop = currentPos + DEFAULT_TAB_INTERVAL_PX - (currentPos % DEFAULT_TAB_INTERVAL_PX); | ||
| let tabWidth: number; | ||
| if ((justification ?? 'left') === 'left') { |
There was a problem hiding this comment.
(justification ?? 'left') -- param is string, never null or undefined. redudant?
| explicitTabs.push(implicitTabPos); | ||
| // Sort tab stops to maintain order | ||
| explicitTabs.sort((a, b) => { | ||
| if (typeof a === 'number' && typeof b === 'number') { |
There was a problem hiding this comment.
typeof guards in sort comparator looks like dead code -- the array is number[].
Before:

After:
