feat: support rendering of column line separators#2088
feat: support rendering of column line separators#2088JoaaoVerona wants to merge 8 commits intosuperdoc-dev:mainfrom
Conversation
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
@caio-pizzol I could not find, in ECMA-376, a definition for |
caio-pizzol
left a comment
There was a problem hiding this comment.
Hey @JoaaoVerona, this is a great start! The withSeparator flag is threaded cleanly through the whole pipeline - extraction, layout, rendering — nice work.
Tests: would be great to add a visual rendering test with a sample .docx that has w:sep="1" on <w:cols>. The test infra auto-discovers .docx files so it's mostly just dropping one in tests/visual/. This is the best way to catch regressions in separator positioning and styling down the road.
On your lineBetween question: lineBetween isn't part of the ECMA-376 spec - the actual XML attribute for column separators is w:sep on <w:cols> (§17.6.4), which is exactly what this PR implements. The name lineBetween probably comes from the Open XML SDK's property naming, not from the XML itself. Word and LibreOffice both use w:sep, so no need to support lineBetween.
left some inline comments on a few things worth tweaking before merging.
|
@JoaaoVerona btw we've created our own OOXML MCP server (https://ooxml.dev/mcp) :) |
|
@JoaaoVerona, let us know if you have any questions on this one |
fefdd96 to
9a732ac
Compare
|
hey @caio-pizzol, thanks for the info! also, great work with the mcp -- been using it already with CC! additionally to the inline comments:
by looking at document.xml, I can see there are 3 |
correct — the visual test infra isn't set up for external contributors to run locally yet. we'll upload the baseline on our end. we're looking into better ways to support this for the community going forward.
i looked at your document.xml — OOXML sections are end-tagged, meaning the
the confusing part is that the first so the extraction is correct — the values just read counterintuitively because of end-tagged semantics. nothing to fix here. |
caio-pizzol
left a comment
There was a problem hiding this comment.
@JoaaoVerona the round 1 feedback is all addressed — the separator color, the columnWidth <= 1 guard, the ColumnLayout type usage, and the SINGLE_COLUMN_DEFAULT constant are all looking good. left a few inline comments on some remaining rough edges before this is ready to merge.
- Extracts 'w:sep' tag according to OOXML spec
- Renders one separator for each page column ('w:col' / 'w:num') in DOM painter
Closes superdoc-dev#2067
9a732ac to
32753c9
Compare
|
hey @caio-pizzol, thanks for the context! inline comments should be solved now. rebased it with main too. |
caio-pizzol
left a comment
There was a problem hiding this comment.
@JoaaoVerona all the feedback from previous rounds is addressed — looking good.
two small things:
-
the column snapshot in
section-props.tscopies fields by hand and missesequalWidthandwidths. there's already a helper (getColumnConfig) that copies everything — reusing it would avoid this. -
normalizeColumnsForFootnotesinincrementalLayout.tsis a copy ofnormalizeColumnsinindex.ts. worth consolidating so the next person doesn't update one and forget the other.
on tests: renderColumnSeparators doesn't have a unit test for its positioning math and guard clauses. also, tests/visual/columns-with-line-separator.docx won't get picked up by the layout regression suite — it needs to go through pnpm corpus:upload to land in the R2 corpus where rendering.spec.ts auto-discovers test files.
left a couple inline comments.
| if (block.columns) { | ||
| hasProps = true; | ||
| props.columns = { count: block.columns.count, gap: block.columns.gap }; | ||
| props.columns = { count: block.columns.count, gap: block.columns.gap, withSeparator: block.columns.withSeparator }; |
There was a problem hiding this comment.
the manual { count, gap, withSeparator } copy here and at line 138 drops equalWidth and widths — so documents with different-sized columns lose that info in the snapshot. getColumnConfig() in section-breaks.ts already copies everything correctly. worth reusing it here?
| const gap = Math.max(0, input?.gap ?? 0); | ||
| const totalGap = gap * (count - 1); | ||
| const width = (contentWidth - totalGap) / count; | ||
| const withSeparator = input?.withSeparator ?? false; |
There was a problem hiding this comment.
this does the same thing as normalizeColumns in layout-engine/src/index.ts:2633 — both are one-liners wrapping normalizeColumnLayout. not blocking, but if one changes and the other doesn't, things will break quietly.


Summary
Adds support for rendering "line between" separators between page columns in DOM Painter, extracting their presence by looking up the
w:septag in the layout engine and ProseMirror adapter. Closes #2067.Changes
w:septag according to OOXML spec [1] [2]w:num)withSeparatorpropertyQuestions & Additional details
columnsdata (i.e.y.columns = { count: x.count, gap: x.gap }) that needed to be updated also to copywithSeparator; I could have used spread operator to shallow clone the data, but I went with a more conservative approach to avoid, potentially, copying unnecessary/unintended properties that could be declared in these objects at runtime;withSeparatorwill be true whenw:sep="true",w:sep="1"orw:sep="on", according to the spec;#b3b3b3, as I'm not sure if we could infer this somehow;withSeparatoras optional to make sure we don't break userland, but a second look from someone more experienced with the packaging/release of superdoc would be great.Showcase