mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 10:13:47 +10:00
fix(pdf): paint background, border and padding on block text
Forme's Text draws no background, border or padding of its own. A block text carrying any of them is now wrapped in a box that paints them, the way texts inside rows already were. Section headings rendered as filled bars or underlined titles vanished whenever section icons were hidden (Kakuna, Meowth, Rhyhorn, Chikorita, Leafish, Gengar, Ditgar, Glalie and Pikachu lost their heading rules), and text-only contact links lost their box styles. The 1pt gap between a section icon and its title, already requested by the shared heading code, now takes effect too.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { Document, Page, Text } from "./primitives";
|
||||
import { renderHostTree } from "./reconciler";
|
||||
import { toFormeDocument } from "./to-forme";
|
||||
|
||||
type SerializedNode = { kind: { type: string }; style: Record<string, unknown>; children: SerializedNode[] };
|
||||
|
||||
describe("toFormeDocument", () => {
|
||||
// Forme's Text paints no background, border or padding, so a section heading drawn as a filled bar or an underlined
|
||||
// title vanished whenever its icon (which made it a box) was hidden.
|
||||
it("puts a text's background, border and padding on a box around it", () => {
|
||||
const tree = renderHostTree(
|
||||
<Document>
|
||||
<Page>
|
||||
<Text style={{ backgroundColor: "#24346E", borderBottomWidth: 1, paddingTop: 4, color: "#ffffff" }}>Bar</Text>
|
||||
</Page>
|
||||
</Document>,
|
||||
);
|
||||
const { document } = toFormeDocument(tree) as unknown as { document: { children: SerializedNode[] } };
|
||||
const [box] = document.children[0]?.children ?? [];
|
||||
|
||||
expect(box?.kind.type).toBe("View");
|
||||
expect(box?.style).toMatchObject({ backgroundColor: expect.anything(), padding: { top: 4 } });
|
||||
expect(box?.style).toHaveProperty("borderWidth");
|
||||
expect(box?.children[0]?.kind.type).toBe("Text");
|
||||
expect(box?.children[0]?.style).not.toHaveProperty("backgroundColor");
|
||||
expect(box?.children[0]?.style).toHaveProperty("color");
|
||||
});
|
||||
});
|
||||
@@ -307,6 +307,29 @@ const ROW_ITEM_KEYS = new Set([
|
||||
"breakBefore",
|
||||
]);
|
||||
|
||||
// What Forme's Text ignores: it paints no background, border or padding of its own, so a text that has them sits in
|
||||
// a box that does.
|
||||
const TEXT_BOX_KEYS = new Set([
|
||||
"backgroundColor",
|
||||
...PADDING_KEYS,
|
||||
"borderWidth",
|
||||
"borderTopWidth",
|
||||
"borderRightWidth",
|
||||
"borderBottomWidth",
|
||||
"borderLeftWidth",
|
||||
"borderColor",
|
||||
"borderTopColor",
|
||||
"borderRightColor",
|
||||
"borderBottomColor",
|
||||
"borderLeftColor",
|
||||
"borderStyle",
|
||||
"borderRadius",
|
||||
"borderTopLeftRadius",
|
||||
"borderTopRightRadius",
|
||||
"borderBottomRightRadius",
|
||||
"borderBottomLeftRadius",
|
||||
]);
|
||||
|
||||
const isEmptyText = (node: HostNode): boolean =>
|
||||
"text" in node
|
||||
? node.text.length === 0
|
||||
@@ -545,12 +568,14 @@ function convertNode(node: HostNode, parentContext: Context, key: number): React
|
||||
const children = convertChildren(node.children, childContext(context, converted, true));
|
||||
const textStyle: FormeStyle = { ...context.textDefaults, ...flowStyle(props, style) };
|
||||
// Forme 0.25 loses the rest of the page (boxes at y -1.8e308) when a row with a text as a direct child breaks
|
||||
// across pages. The text sits in a box that takes its place in the row.
|
||||
if (context.rowParent && !context.inText) {
|
||||
// across pages. The text sits in a box that takes its place in the row; a text with a background, border or
|
||||
// padding sits in a box that paints them (see `TEXT_BOX_KEYS`).
|
||||
const paintsBox = Object.keys(textStyle).some((property) => TEXT_BOX_KEYS.has(property));
|
||||
if ((context.rowParent || paintsBox) && !context.inText) {
|
||||
const box: Record<string, unknown> = {};
|
||||
const text: Record<string, unknown> = {};
|
||||
for (const [property, value] of Object.entries(textStyle))
|
||||
(ROW_ITEM_KEYS.has(property) ? box : text)[property] = value;
|
||||
(ROW_ITEM_KEYS.has(property) || TEXT_BOX_KEYS.has(property) ? box : text)[property] = value;
|
||||
const inner = createElement(FormeText, { style: text as FormeStyle, ...(href ? { href } : {}) }, ...children);
|
||||
tagNode(inner, props, context);
|
||||
const wrapper = createElement(FormeView, { key, style: box as FormeStyle }, inner);
|
||||
|
||||
Reference in New Issue
Block a user