mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-10-03 02:04:31 +10:00
fix(pdf): apply opacity to rating icons (#3412)
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { renderToBuffer } from "@react-pdf/renderer";
|
||||
import { getDocument, OPS } from "pdfjs-dist/legacy/build/pdf.mjs";
|
||||
import { act, createElement } from "react";
|
||||
import { defaultResumeData } from "@reactive-resume/schema/resume/default";
|
||||
import { ResumeDocument } from "../../document";
|
||||
|
||||
const renderLevel = async (level: number, css = "") => {
|
||||
const data = structuredClone(defaultResumeData);
|
||||
data.basics.name = "Audit";
|
||||
data.metadata.typography.body.fontFamily = "Helvetica";
|
||||
data.metadata.typography.heading.fontFamily = "Helvetica";
|
||||
data.metadata.layout.pages = [{ fullWidth: true, main: ["skills"], sidebar: [] }];
|
||||
data.metadata.design.level = { type: "icon", icon: "star" };
|
||||
data.metadata.stylesheet = { mode: "semantic", source: { languageVersion: 1, text: `@version 1; ${css}` } };
|
||||
data.sections.skills.items = [
|
||||
{ id: "skill", hidden: false, name: "Skill", proficiency: "Expert", level, keywords: [], icon: "", iconColor: "" },
|
||||
];
|
||||
const element = createElement(ResumeDocument, { data, template: "scizor" }) as unknown as Parameters<
|
||||
typeof renderToBuffer
|
||||
>[0];
|
||||
let bytes: Uint8Array = new Uint8Array();
|
||||
await act(async () => {
|
||||
bytes = new Uint8Array(await renderToBuffer(element));
|
||||
});
|
||||
const loadingTask = getDocument({ data: bytes, useSystemFonts: true });
|
||||
try {
|
||||
const document = await loadingTask.promise;
|
||||
const page = await document.getPage(1);
|
||||
const operators = await page.getOperatorList();
|
||||
return operators.fnArray.flatMap((fn, index) => (fn === OPS.setGState ? operators.argsArray[index][0] : []));
|
||||
} finally {
|
||||
await loadingTask.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
describe("PDF icon opacity (#3352)", () => {
|
||||
it.each([1, 3, 4])("writes inactive level %i opacity to PDF graphics state", async (level) => {
|
||||
const states = await renderLevel(level);
|
||||
expect(states).toContainEqual(["ca", 0.35]);
|
||||
expect(states).toContainEqual(["CA", 0.35]);
|
||||
});
|
||||
it("honors semantic icon opacity overrides, including zero", async () => {
|
||||
const states = await renderLevel(
|
||||
3,
|
||||
'level icon[role~="active"] { opacity: 0.2; } level icon[role~="inactive"] { opacity: 0; }',
|
||||
);
|
||||
expect(states).toContainEqual(["ca", 0.2]);
|
||||
expect(states).toContainEqual(["CA", 0.2]);
|
||||
expect(states).toContainEqual(["ca", 0]);
|
||||
expect(states).toContainEqual(["CA", 0]);
|
||||
expect(states).not.toContainEqual(["ca", 0.35]);
|
||||
});
|
||||
it.each([0, 5])("does not dim fully active or hidden level %i", async (level) => {
|
||||
expect(await renderLevel(level)).not.toContainEqual(["ca", 0.35]);
|
||||
});
|
||||
});
|
||||
@@ -305,6 +305,9 @@ export const Icon = ({
|
||||
const resolvedNodeKey = nodeKey ?? (parentKey ? semanticNodeKeys.icon(parentKey, "item") : undefined);
|
||||
const resolved = useResolvedNode(resolvedNodeKey);
|
||||
const visible = useSemanticNodeVisible(resolvedNodeKey);
|
||||
const resolvedStyle = composeStyles(composedStyle, resolved.style);
|
||||
// React PDF inherits SVG opacity from props, not the root SVG style.
|
||||
const { opacity } = mergeStyles(resolvedStyle);
|
||||
const resolvedSize =
|
||||
resolveIconSize({
|
||||
size: sizeProp,
|
||||
@@ -318,7 +321,8 @@ export const Icon = ({
|
||||
{...iconProps}
|
||||
{...props}
|
||||
{...(resolvedSize === undefined ? {} : { size: resolvedSize })}
|
||||
style={composeStyles(composedStyle, resolved.style)}
|
||||
{...(opacity === undefined ? {} : { opacity })}
|
||||
style={resolvedStyle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user