Skip to content

Commit c843810

Browse files
YousefEDareknawo
authored andcommitted
block props basics
1 parent 59a0dfa commit c843810

File tree

4 files changed

+126
-15
lines changed

4 files changed

+126
-15
lines changed

packages/xl-odt-exporter/src/odt/defaultSchema/blocks.tsx

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { BlockMapping, DefaultBlockSchema } from "@blocknote/core";
2+
import { ODTExporter } from "../odtExporter.js";
23
import {
34
DrawFrame,
45
DrawImage,
6+
StyleBackgroundFill,
7+
StyleParagraphProperties,
8+
StyleStyle,
59
Table,
610
TableCell,
711
TableRow,
@@ -17,28 +21,72 @@ export const getTabs = (nestingLevel: number) => {
1721
return Array.from({ length: nestingLevel }, () => <TextTab />);
1822
};
1923

24+
const createParagraphStyle = (
25+
exporter: ODTExporter<any, any, any>,
26+
props: Record<string, any>
27+
) => {
28+
const styles: Record<string, string> = {};
29+
const children: React.ReactNode[] = [];
30+
31+
if (props.textAlignment !== "default") {
32+
styles["fo:text-align"] = props.textAlignment;
33+
}
34+
35+
if (props.backgroundColor && props.backgroundColor !== "default") {
36+
const color =
37+
exporter.options.colors[
38+
props.backgroundColor as keyof typeof exporter.options.colors
39+
].background;
40+
children.push(<StyleBackgroundFill color={color} />);
41+
}
42+
43+
if (Object.keys(styles).length === 0 && children.length === 0) {
44+
return undefined;
45+
}
46+
47+
return exporter.registerStyle((name) => (
48+
<StyleStyle style:family="paragraph" style:name={name}>
49+
<StyleParagraphProperties {...styles}>
50+
{children}
51+
</StyleParagraphProperties>
52+
</StyleStyle>
53+
));
54+
};
55+
2056
export const odtBlockMappingForDefaultSchema: BlockMapping<
2157
DefaultBlockSchema,
2258
any,
2359
any,
2460
React.ReactNode,
2561
React.ReactNode
2662
> = {
27-
paragraph: (block, exporter, nestingLevel) => (
28-
<TextP>
29-
{getTabs(nestingLevel)}
30-
{exporter.transformInlineContent(block.content)}
31-
</TextP>
32-
),
63+
paragraph: (block, exporter, nestingLevel) => {
64+
const styleName = createParagraphStyle(
65+
exporter as ODTExporter<any, any, any>,
66+
block.props
67+
);
68+
return (
69+
<TextP text:style-name={styleName}>
70+
{getTabs(nestingLevel)}
71+
{exporter.transformInlineContent(block.content)}
72+
</TextP>
73+
);
74+
},
3375

34-
heading: (block, exporter, nestingLevel) => (
35-
<TextH
36-
level={block.props.level}
37-
text:style-name={`Heading${block.props.level}`}>
38-
{getTabs(nestingLevel)}
39-
{exporter.transformInlineContent(block.content)}
40-
</TextH>
41-
),
76+
heading: (block, exporter, nestingLevel) => {
77+
const customStyleName = createParagraphStyle(
78+
exporter as ODTExporter<any, any, any>,
79+
block.props
80+
);
81+
const styleName = customStyleName;
82+
83+
return (
84+
<TextH level={block.props.level} text:style-name={styleName}>
85+
{getTabs(nestingLevel)}
86+
{exporter.transformInlineContent(block.content)}
87+
</TextH>
88+
);
89+
},
4290

4391
bulletListItem: (block, exporter) => (
4492
<TextList text:style-name="List_1">

packages/xl-odt-exporter/src/odt/odtExporter.tsx

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,44 @@ export class ODTExporter<
6262
this.options = { ...defaults, ...options };
6363
}
6464

65+
private blockPropsToStyles(
66+
props: Record<string, any>
67+
): Record<string, string> {
68+
const styles: Record<string, string> = {};
69+
70+
if (props.textAlignment) {
71+
styles["fo:text-align"] = props.textAlignment;
72+
}
73+
74+
if (props.backgroundColor && props.backgroundColor !== "default") {
75+
const color =
76+
this.options.colors[
77+
props.backgroundColor as keyof typeof this.options.colors
78+
].background;
79+
styles["fo:background-fill"] = color;
80+
}
81+
82+
return styles;
83+
}
84+
85+
private getBlockStyleName(props: Record<string, any>): string | undefined {
86+
const styles = this.blockPropsToStyles(props);
87+
if (Object.keys(styles).length === 0) {
88+
return undefined;
89+
}
90+
91+
const styleName = `P${++this.styleCounter}`;
92+
93+
this.automaticStyles.set(
94+
styleName,
95+
<StyleStyle style:name={styleName} style:family="paragraph">
96+
<style:paragraph-properties {...styles} />
97+
</StyleStyle>
98+
);
99+
100+
return styleName;
101+
}
102+
65103
public transformStyledText(styledText: StyledText<S>): React.ReactNode {
66104
const stylesArray = this.mapStyles(styledText.styles);
67105
const styles = Object.assign({}, ...stylesArray);
@@ -101,8 +139,9 @@ export class ODTExporter<
101139
block.children,
102140
nestingLevel + 1
103141
);
142+
104143
const content = await this.mapBlock(
105-
block as any,
144+
block,
106145
nestingLevel,
107146
numberedListIndex
108147
);
@@ -160,4 +199,10 @@ export class ODTExporter<
160199
type: "application/vnd.oasis.opendocument.text",
161200
});
162201
}
202+
203+
public registerStyle(style: (name: string) => React.ReactNode): string {
204+
const styleName = `S${++this.styleCounter}`;
205+
this.automaticStyles.set(styleName, style(styleName));
206+
return styleName;
207+
}
163208
}

packages/xl-odt-exporter/src/odt/util/components.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,16 @@ export const StyleStyle = ({ children, ...props }: Props) =>
103103

104104
export const StyleTextProperties = ({ children, ...props }: Props) =>
105105
createElement("style:text-properties", props, children);
106+
107+
export const StyleBackgroundFill = ({
108+
color,
109+
...props
110+
}: Props & { color: string }) =>
111+
createElement("style:background-fill", {
112+
"draw:fill": "solid",
113+
"draw:fill-color": color,
114+
...props,
115+
});
116+
117+
export const StyleParagraphProperties = ({ children, ...props }: Props) =>
118+
createElement("style:paragraph-properties", props, children);

packages/xl-odt-exporter/src/odt/util/jsx.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ declare namespace JSX {
1919
"table:table-cell": any;
2020
"manifest:manifest": any;
2121
"manifest:file-entry": any;
22+
"style:paragraph-properties": any;
23+
"style:background-fill": any;
2224
}
2325

2426
interface IntrinsicAttributes {
2527
"text:style-name"?: string;
2628
"style:style-name"?: string;
2729
"style:name"?: string;
2830
"style:family"?: string;
31+
"style:background-fill"?: string;
32+
"draw:fill"?: string;
33+
"draw:fill-color"?: string;
2934
}
3035
}

0 commit comments

Comments
 (0)