fix: a paragraph margin the style half-declares follows LibreOffice
LibreOffice keeps a paragraph's space above and below in one item, so a style that declares only one of them does not inherit the other from its parent chain — the missing half falls back to the default paragraph style. Probed against soffice with the OPG fixture's own styles, where it is the difference between a heading sitting flush and 4mm too low.
This commit is contained in:
1 parent
0b89b5af8a
commit
a70df06fc1
1 file changed
+16
-1
@@ -81,6 +81,20 @@ export function layerTextProps(base: PropMap, over: PropMap): PropMap {
|
||||
return Object.assign(out, over);
|
||||
}
|
||||
|
||||
// LibreOffice holds a paragraph's two vertical margins in one item, so a style that
|
||||
// declares just one of them does not inherit the other — the missing one falls back to
|
||||
// the default paragraph style's value (probed: heading margins, and the space after a
|
||||
// paragraph that only sets fo:margin-top).
|
||||
const VERTICAL_MARGINS = ['fo:margin-top', 'fo:margin-bottom'] as const;
|
||||
|
||||
export function layerParaProps(base: PropMap, over: PropMap, poolDefaults: PropMap): PropMap {
|
||||
const out = Object.assign({}, base, over);
|
||||
if (VERTICAL_MARGINS.some((k) => k in over)) {
|
||||
for (const k of VERTICAL_MARGINS) if (!(k in over)) out[k] = poolDefaults[k] ?? '0cm';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// The size a percentage font-size is relative to when nothing is inherited yet
|
||||
// (ODF's implied default, matching the editor's body size).
|
||||
const BASE_FONT_SIZE_PT = 12;
|
||||
@@ -277,12 +291,13 @@ export class StyleResolver {
|
||||
if (def) chain.push(def);
|
||||
|
||||
const result = { text: {} as PropMap, para: {} as PropMap, misc: {} as PropMap };
|
||||
const poolDefaults = def?.para ?? {};
|
||||
// Apply root-first so nearer definitions overwrite.
|
||||
for (const entry of chain.reverse()) {
|
||||
const inherited = result.text['fo:font-size'];
|
||||
result.text = layerTextProps(result.text, entry.text);
|
||||
resolvePercentSize(result.text, inherited);
|
||||
Object.assign(result.para, entry.para);
|
||||
result.para = entry === def ? { ...entry.para } : layerParaProps(result.para, entry.para, poolDefaults);
|
||||
Object.assign(result.misc, entry.misc);
|
||||
}
|
||||
this.mergedCache.set(cacheKey, result);
|
||||
|
||||
Reference in new issue
Block a user