Skip to content

Commit 47a5216

Browse files
committed
✨(odt) add generic helper and style callout block for odt export
create odtRegisterParagraphStyleForBlock and apply background/padding styles Signed-off-by: Cyril <c.gromoff@gmail.com>
1 parent 9d99d5e commit 47a5216

File tree

3 files changed

+68
-9
lines changed

3 files changed

+68
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to
1010

1111
- ✨(frontend) create skeleton component for DocEditor #1491
1212
- ✨(frontend) add an EmojiPicker in the document tree and title #1381
13+
- ✨(frontend) enable ODT export for documents #1524
1314

1415
### Changed
1516

src/frontend/apps/impress/src/features/docs/doc-export/blocks-mapping/calloutODT.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22

3+
import { odtRegisterParagraphStyleForBlock } from '../utils';
34
import { DocsExporterODT } from '../types';
45

56
export const blockMappingCalloutODT: DocsExporterODT['mappings']['blockMapping']['callout'] =
@@ -10,19 +11,20 @@ export const blockMappingCalloutODT: DocsExporterODT['mappings']['blockMapping']
1011
// Transform inline content (text, bold, links, etc.)
1112
const inlineContent = exporter.transformInlineContent(block.content);
1213

13-
const textAlignment =
14-
block.props.textAlignment === 'center'
15-
? 'center'
16-
: block.props.textAlignment === 'right'
17-
? 'right'
18-
: 'left';
14+
// Resolve background and alignment → create a dedicated paragraph style
15+
const styleName = odtRegisterParagraphStyleForBlock(
16+
exporter,
17+
{
18+
backgroundColor: block.props.backgroundColor,
19+
textAlignment: block.props.textAlignment,
20+
},
21+
{ paddingCm: 0.42 },
22+
);
1923

20-
// Simple paragraph with emoji - ODT background colors are complex to implement
21-
// and not well supported across different ODT readers
2224
return React.createElement(
2325
'text:p',
2426
{
25-
'text:style-name': textAlignment,
27+
'text:style-name': styleName,
2628
},
2729
`${emoji} `,
2830
...inlineContent,

src/frontend/apps/impress/src/features/docs/doc-export/utils.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from 'react';
12
import {
23
COLORS_DEFAULT,
34
DefaultProps,
@@ -98,3 +99,58 @@ export function docxBlockPropsToStyles(
9899
})(),
99100
};
100101
}
102+
103+
// ODT helpers
104+
export function odtRegisterParagraphStyleForBlock(
105+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
106+
exporter: any,
107+
props: Partial<DefaultProps>,
108+
options?: { paddingCm?: number },
109+
) {
110+
const colors = exporter?.options?.colors as typeof COLORS_DEFAULT | undefined;
111+
112+
const bgColorHex =
113+
props.backgroundColor && props.backgroundColor !== 'default' && colors
114+
? colors[props.backgroundColor].background
115+
: undefined;
116+
117+
const textColorHex =
118+
props.textColor && props.textColor !== 'default' && colors
119+
? colors[props.textColor].text
120+
: undefined;
121+
122+
const foTextAlign =
123+
!props.textAlignment || props.textAlignment === 'left'
124+
? 'start'
125+
: props.textAlignment === 'center'
126+
? 'center'
127+
: props.textAlignment === 'right'
128+
? 'end'
129+
: 'justify';
130+
131+
const paddingCm = options?.paddingCm ?? 0.42; // ~1rem (16px)
132+
133+
// registerStyle is available on ODT exporter; call through with React elements
134+
const styleName = (
135+
exporter as unknown as {
136+
registerStyle: (fn: (name: string) => React.ReactNode) => string;
137+
}
138+
).registerStyle((name: string) =>
139+
React.createElement(
140+
'style:style',
141+
{ 'style:name': name, 'style:family': 'paragraph' },
142+
React.createElement('style:paragraph-properties', {
143+
'fo:text-align': foTextAlign,
144+
'fo:padding': `${paddingCm}cm`,
145+
...(bgColorHex ? { 'fo:background-color': bgColorHex } : {}),
146+
}),
147+
textColorHex
148+
? React.createElement('style:text-properties', {
149+
'fo:color': textColorHex,
150+
})
151+
: undefined,
152+
),
153+
);
154+
155+
return styleName;
156+
}

0 commit comments

Comments
 (0)