fix: a divider line is saved flat, not across its frame

A line shape carries no height, and both exporters stood in the 96px default a
text box gets — so a horizontal divider was written across the frame's
diagonal and came back as one. A line kind keeps the 0 it has.

Claude-Session: https://claude.ai/code/session_01Wzs2qG6Y5qm7mKmJHfu44G
This commit is contained in:
Steffen Becker committed 2026-09-11 09:10:29 +02:00
1 parent 9c9362ac8c
commit 98530afe3b
2 files changed
+9 -3

No files matched your search

+5 -2
View File
@@ -17,7 +17,7 @@ import type {
import { unzipSync, zipSync, strFromU8, strToU8 } from 'fflate';
import { isSvgDataUrl, svgToPngDataUrl } from '../import/imageFormats';
import { TEXTBOX_PADDING_CM } from '../editor/extensions/textBox';
import { SHAPES, isShapeKind, drawingMlPath, type ShapeKind } from '../utils/shapes';
import { SHAPES, isShapeKind, isLineKind, drawingMlPath, type ShapeKind } from '../utils/shapes';
import { cellFormatCode, isCellFormat } from '../utils/cellFormat';
import { DEFAULT_MARGINS, type PageMargins } from '../storage/pageMargins';
import type { Orientation } from '../storage/pageOrientation';
@@ -976,9 +976,12 @@ type TextBoxDocx = {
function textBoxDocxDescriptor(node: TiptapNode): TextBoxDocx {
const a = node.attrs ?? {};
const wrapAttr = a.wrap;
// A line has no box (see odt.ts): standing in the default height for a divider of
// none draws it across the frame's diagonal.
const line = isShapeKind(a.shapeKind) && isLineKind(a.shapeKind);
return {
widthPx: typeof a.width === 'number' && a.width > 0 ? Math.round(a.width) : 280,
heightPx: typeof a.height === 'number' && a.height > 0 ? Math.round(a.height) : 96,
heightPx: typeof a.height === 'number' && a.height > 0 ? Math.round(a.height) : line ? 0 : 96,
rotationDeg: typeof a.rotation === 'number' ? a.rotation : 0,
wrap: wrapAttr === 'left' || wrapAttr === 'right' || wrapAttr === 'topBottom' || wrapAttr === 'through' ? wrapAttr : 'inline',
offsetCm: typeof a.wrapOffset === 'number' ? a.wrapOffset : null,
+4 -1
View File
@@ -1001,9 +1001,12 @@ function textBoxDescriptor(node: TiptapNode): TextBoxExport {
const pxToCm = (px: number) => round3((px * 2.54) / 96);
const a = node.attrs ?? {};
const wrapAttr = a.wrap;
// A line has no box: a frame of no height is the horizontal divider both word
// processors write, and standing in the default for it draws a diagonal instead.
const line = isShapeKind(a.shapeKind) && isLineKind(a.shapeKind);
return {
widthCm: pxToCm(typeof a.width === 'number' && a.width > 0 ? a.width : 280),
heightCm: pxToCm(typeof a.height === 'number' && a.height > 0 ? a.height : 96),
heightCm: pxToCm(typeof a.height === 'number' && a.height > 0 ? a.height : line ? 0 : 96),
rotationDeg: typeof a.rotation === 'number' ? a.rotation : 0,
wrap: wrapAttr === 'left' || wrapAttr === 'right' || wrapAttr === 'topBottom' || wrapAttr === 'through' ? wrapAttr : 'inline',
wrapOffsetCm: typeof a.wrapOffset === 'number' ? round3(a.wrapOffset) : null,