mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 02:04:31 +10:00
fix(pdf): preserve first character of section headings by adding left padding (#3386)
* fix(pdf): add left padding to section heading text to prevent first-character clipping Closes #3380 * fix(pdf): apply heading padding default after style composition Apply paddingLeft: 1 only when no composed style fragment already defines it, so an explicit paddingLeft from a template or style rule is preserved. Keep the fallback for an empty style list. * fix(pdf): keep heading safety padding on text only --------- Co-authored-by: Amruth Pillai <im.amruth@gmail.com>
This commit is contained in:
co-authored by
Amruth Pillai
parent
ea3980cba0
commit
e0c2f6d88a
@@ -239,6 +239,21 @@ describe("semantic issue fixtures", () => {
|
||||
expect(mergedStyle(findText(document, "Analytical Engines")).fontWeight).not.toBe("400");
|
||||
});
|
||||
|
||||
it("preserves the first character of a section heading with a leading text padding (#3380)", async () => {
|
||||
const data = buildIssueFixture();
|
||||
data.sections.experience.title = "Experience";
|
||||
data.metadata.page.hideSectionIcons = false;
|
||||
|
||||
const element = createElement(ResumeDocument, { data, template: "onyx" }) as unknown as Parameters<typeof pdf>[0];
|
||||
const instance = pdf(element);
|
||||
await vi.waitFor(() => expect(instance.container.document).not.toBeNull());
|
||||
const document = instance.container.document as HostNode;
|
||||
const heading = findText(document, "Experience");
|
||||
|
||||
expect(heading).toBeDefined();
|
||||
expect(mergedStyle(heading).paddingLeft).toBe(1);
|
||||
});
|
||||
|
||||
it("renders descriptor filtering and stable item order instead of remapping raw arrays", async () => {
|
||||
const data = buildIssueFixture();
|
||||
data.sections.skills.items = ["First", "Hidden", "Last"].map((name, index) => ({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { getSectionHeadingTextStyle } from "./sections";
|
||||
|
||||
const source = readFileSync(fileURLToPath(new URL("./sections.tsx", import.meta.url)), "utf8");
|
||||
|
||||
@@ -24,6 +25,11 @@ describe("ItemTitle", () => {
|
||||
});
|
||||
|
||||
describe("SectionShell", () => {
|
||||
it("keeps heading text safety padding separate from container padding", () => {
|
||||
expect(getSectionHeadingTextStyle({ paddingLeft: 0 })).toEqual([{ paddingLeft: 1 }]);
|
||||
expect(getSectionHeadingTextStyle({ paddingLeft: 6 })).toEqual([{ paddingLeft: 1 }]);
|
||||
});
|
||||
|
||||
it("keeps section and heading style rules when section heading icons are hidden", () => {
|
||||
expect(source).toContain(
|
||||
"const resolvedSectionStyle = composeStyles(sectionStyle, sectionRuleStyle, resolved.style)",
|
||||
|
||||
@@ -188,8 +188,8 @@ const defaultSectionHeadingContainerStyle = {
|
||||
columnGap: 4,
|
||||
} satisfies Style;
|
||||
|
||||
const getSectionHeadingTextStyle = (...styles: StyleInput[]): Style[] =>
|
||||
composeStyles(...styles).map(
|
||||
export const getSectionHeadingTextStyle = (...styles: StyleInput[]): Style[] => {
|
||||
const textStyles = composeStyles(...styles).map(
|
||||
({
|
||||
borderBottomWidth: _borderBottomWidth,
|
||||
borderLeftWidth: _borderLeftWidth,
|
||||
@@ -211,6 +211,13 @@ const getSectionHeadingTextStyle = (...styles: StyleInput[]): Style[] =>
|
||||
}) => textStyle,
|
||||
);
|
||||
|
||||
if (textStyles.length === 0) return [{ paddingLeft: 1 }];
|
||||
|
||||
const lastIndex = textStyles.length - 1;
|
||||
const lastTextStyle: Style = { ...textStyles[lastIndex], paddingLeft: 1 };
|
||||
return [...textStyles.slice(0, lastIndex), lastTextStyle];
|
||||
};
|
||||
|
||||
const useSectionItemsContext = () => use(SectionItemsContext);
|
||||
|
||||
export const SemanticTextRuns = ({
|
||||
|
||||
Reference in New Issue
Block a user