refactor: ponytail audit

This commit is contained in:
Amruth Pillai
2026-07-27 20:26:16 +02:00
parent bb1fb3a7d6
commit 9110e86997
157 changed files with 1082 additions and 2177 deletions
@@ -20,10 +20,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -58,14 +56,11 @@ const azurillFeatures = {
sectionTimeline: true,
} satisfies TemplateFeatures;
export const AzurillPage = ({ page, pageIndex }: TemplatePageProps) => {
export const AzurillPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles, featureStyles } = useAzurillTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
@@ -139,22 +134,17 @@ const useAzurillTemplate = (): AzurillTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
...base.page,
flexDirection: "column",
rowGap: metrics.headerGap,
columnGap: metrics.columnGap,
color: foreground,
backgroundColor: background,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
sectionHeading: {
color: primary,
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -70,14 +68,11 @@ const getBronzorSections = ({
return sections;
};
export const BronzorPage = ({ page, pageIndex }: TemplatePageProps) => {
export const BronzorPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { styles, colors } = useBronzorTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
const sections = getBronzorSections({ mainSections, sidebarSections, fullWidth: page.fullWidth });
@@ -136,22 +131,17 @@ const useBronzorTemplate = (): BronzorTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
heading: { ...base.heading, fontWeight: metadata.typography.heading.fontWeights[0] ?? "500" },
page: {
...base.page,
flexDirection: "column",
rowGap: metrics.headerGap,
color: foreground,
backgroundColor: background,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: r.row,
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -47,15 +45,12 @@ type ChikoritaHeaderProps = {
styles: ChikoritaStyles;
};
export const ChikoritaPage = ({ page, pageIndex }: TemplatePageProps) => {
export const ChikoritaPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata, picture } = data;
const { colors, styles } = useChikoritaTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const hasPicture = hasTemplatePicture(picture);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
@@ -153,19 +148,14 @@ const useChikoritaTemplate = (): ChikoritaTemplate => {
};
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
inline: { ...base.inline, columnGap: metrics.gapX(0.25) },
page: {
...base.page,
flexDirection: r.row,
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -27,11 +27,23 @@ const readTemplate = (file: string) => {
};
describe("cover letter PDF layout", () => {
it.each(pageFiles)("%s suppresses the resume header for cover-letter-only documents", (file) => {
it("derives shared page props in the document renderer", () => {
const source = readTemplate("../document.tsx");
expect(source).toContain('from "./templates/shared/cover-letter"');
expect(source).toContain('from "./templates/shared/page-size"');
expect(source).toContain("showHeader={shouldShowResumeHeader");
expect(source).toContain("pageSize={pageSize}");
expect(source).toContain("pageMinHeightStyle={pageMinHeightStyle}");
});
it.each(pageFiles)("%s renders the shared page props", (file) => {
const source = readTemplate(file);
expect(source, basename(file)).toContain('from "../shared/cover-letter"');
expect(source, basename(file)).toContain("shouldShowResumeHeader(data, pageIndex)");
expect(source, basename(file)).not.toContain("const showHeader = pageIndex === 0;");
expect(source, basename(file)).toContain("pageSize, pageMinHeightStyle, showHeader");
expect(source, basename(file)).toContain("<Page size={pageSize}");
expect(source, basename(file)).toContain("showHeader &&");
expect(source, basename(file)).not.toContain('from "../shared/cover-letter"');
expect(source, basename(file)).not.toContain('from "../shared/page-size"');
});
});
@@ -15,11 +15,9 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { getFeaturedSummaryLayout } from "../shared/featured-summary";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -58,14 +56,11 @@ const ditgarFeatures = {
mainItemHeaderBorder: true,
} satisfies TemplateFeatures;
export const DitgarPage = ({ page, pageIndex }: TemplatePageProps) => {
export const DitgarPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useDitgarTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const showSidebar = !page.fullWidth || showHeader;
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
@@ -189,18 +184,13 @@ const useDitgarTemplate = (): DitgarTemplate => {
};
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
...base.page,
flexDirection: r.row,
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
+3 -13
View File
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -52,15 +50,12 @@ type DittoHeaderProps = {
styles: DittoStyles;
};
export const DittoPage = ({ page, pageIndex }: TemplatePageProps) => {
export const DittoPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata, picture } = data;
const { colors, styles } = useDittoTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const hasPicture = hasTemplatePicture(picture);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
@@ -149,7 +144,7 @@ const useDittoTemplate = (): DittoTemplate => {
const metrics = getTemplateMetrics(metadata.page);
const hasPicture = hasTemplatePicture(picture);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
@@ -161,13 +156,8 @@ const useDittoTemplate = (): DittoTemplate => {
marginLeft: -picture.size / 2,
},
page: {
...base.page,
flexDirection: "column",
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -15,11 +15,9 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { getFeaturedSummaryLayout } from "../shared/featured-summary";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -53,14 +51,11 @@ type GengarHeaderProps = {
colors: TemplateColorRoles;
};
export const GengarPage = ({ page, pageIndex }: TemplatePageProps) => {
export const GengarPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useGengarTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const showSidebar = !page.fullWidth || showHeader;
const sidebarSections = filterSections(page.sidebar, data);
const mainSections = filterSections(page.main, data);
@@ -185,18 +180,13 @@ const useGengarTemplate = (): GengarTemplate => {
};
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
...base.page,
flexDirection: r.row,
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -15,10 +15,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -55,14 +53,11 @@ const glalieFeatures = {
stackSidebarItemHeader: true,
} satisfies TemplateFeatures;
export const GlaliePage = ({ page, pageIndex }: TemplatePageProps) => {
export const GlaliePage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useGlalieTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const showSidebar = !page.fullWidth || showHeader;
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -150,18 +145,10 @@ const useGlalieTemplate = (): GlalieTemplate => {
};
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
rowGap: metrics.gapY(0.25),
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -46,14 +44,11 @@ type KakunaHeaderProps = {
styles: KakunaStyles;
};
export const KakunaPage = ({ page, pageIndex }: TemplatePageProps) => {
export const KakunaPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useKakunaTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -119,20 +114,15 @@ const useKakunaTemplate = (): KakunaTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.sectionGap,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -45,14 +43,11 @@ type LaprasHeaderProps = {
styles: LaprasStyles;
};
export const LaprasPage = ({ page, pageIndex }: TemplatePageProps) => {
export const LaprasPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useLaprasTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -121,20 +116,15 @@ const useLaprasTemplate = (): LaprasTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.gapY(1.5),
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -15,10 +15,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -51,14 +49,11 @@ type LeafishHeaderProps = {
styles: LeafishStyles;
};
export const LeafishPage = ({ page, pageIndex }: TemplatePageProps) => {
export const LeafishPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useLeafishTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data).filter((section) => section !== "summary");
const sidebarSections = filterSections(page.sidebar, data).filter((section) => section !== "summary");
@@ -141,18 +136,10 @@ const useLeafishTemplate = (): LeafishTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
rowGap: metrics.gapY(0.25),
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -50,14 +48,11 @@ const meowthFeatures = {
inlineItemHeader: true,
} satisfies TemplateFeatures;
export const MeowthPage = ({ page, pageIndex }: TemplatePageProps) => {
export const MeowthPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useMeowthTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -122,20 +117,15 @@ const useMeowthTemplate = (): MeowthTemplate => {
const primary = rgbaStringToHex(metadata.design.colors.primary);
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.sectionGap,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
inlineItemHeader: {
flexDirection: r.row,
+3 -13
View File
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -45,14 +43,11 @@ type OnyxHeaderProps = {
styles: OnyxStyles;
};
export const OnyxPage = ({ page, pageIndex }: TemplatePageProps) => {
export const OnyxPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useOnyxTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -117,20 +112,15 @@ const useOnyxTemplate = (): OnyxTemplate => {
const primary = rgbaStringToHex(metadata.design.colors.primary);
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.sectionGap,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -55,14 +53,11 @@ const pikachuFeatures = {
stackSidebarItemHeader: true,
} satisfies TemplateFeatures;
export const PikachuPage = ({ page, pageIndex }: TemplatePageProps) => {
export const PikachuPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata, picture } = data;
const { colors, styles } = usePikachuTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const showSidebar = !page.fullWidth;
const hasPicture = hasTemplatePicture(picture);
const mainSections = filterSections(page.main, data);
@@ -171,19 +166,14 @@ const usePikachuTemplate = (): PikachuTemplate => {
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -15,10 +15,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -48,14 +46,11 @@ type RhyhornHeaderProps = {
styles: RhyhornStyles;
};
export const RhyhornPage = ({ page, pageIndex }: TemplatePageProps) => {
export const RhyhornPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useRhyhornTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = filterSections(page.sidebar, data);
@@ -163,20 +158,15 @@ const useRhyhornTemplate = (): RhyhornTemplate => {
const metrics = getTemplateMetrics(metadata.page);
const contactGap = metrics.gapX(0.5);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.sectionGap,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
section: {
flexDirection: "column",
@@ -14,10 +14,8 @@ import {
WebsiteContactItem,
} from "../shared/contact-item";
import { TemplateProvider } from "../shared/context";
import { shouldShowResumeHeader } from "../shared/cover-letter";
import { filterSections } from "../shared/filtering";
import { getTemplateMetrics } from "../shared/metrics";
import { getTemplatePageMinHeightStyle, getTemplatePageSize } from "../shared/page-size";
import { hasTemplatePicture } from "../shared/picture";
import { Heading, Text } from "../shared/primitives";
import { createRtlStyleHelpers } from "../shared/rtl";
@@ -46,14 +44,11 @@ type ScizorHeaderProps = {
styles: ScizorStyles;
};
export const ScizorPage = ({ page, pageIndex }: TemplatePageProps) => {
export const ScizorPage = ({ page, pageSize, pageMinHeightStyle, showHeader }: TemplatePageProps) => {
const data = useRender();
const { metadata } = data;
const { colors, styles } = useScizorTemplate();
const metrics = getTemplateMetrics(metadata.page);
const pageSize = getTemplatePageSize(metadata.page.format);
const pageMinHeightStyle = getTemplatePageMinHeightStyle(metadata.page.format);
const showHeader = shouldShowResumeHeader(data, pageIndex);
const mainSections = filterSections(page.main, data);
const sidebarSections = page.fullWidth ? [] : filterSections(page.sidebar, data);
const sections = [...mainSections, ...sidebarSections];
@@ -111,22 +106,17 @@ const useScizorTemplate = (): ScizorTemplate => {
const divider = "#D8DCE2";
const colors: TemplateColorRoles = { foreground, background, primary };
const metrics = getTemplateMetrics(metadata.page);
const base = createBaseTemplateStyles({ metadata, foreground, r, metrics, picture });
const base = createBaseTemplateStyles({ metadata, foreground, background, r, metrics, picture });
const baseStyles = StyleSheet.create({
...base,
page: {
color: foreground,
backgroundColor: background,
...base.page,
borderTopWidth: metrics.gapY(0.45),
borderTopColor: primary,
paddingHorizontal: metrics.page.paddingHorizontal,
paddingVertical: metrics.page.paddingVertical,
rowGap: metrics.sectionGap,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
},
heading: { ...base.heading, fontWeight: metadata.typography.heading.fontWeights.at(-1) ?? "700" },
bold: { fontWeight: metadata.typography.body.fontWeights.at(-1) ?? "700", color: foreground },
@@ -7,6 +7,7 @@ import { rgbaStringToHex } from "@reactive-resume/utils/color";
type BaseTemplateStylesInput = {
metadata: ResumeData["metadata"];
foreground: string;
background: string;
r: ReturnType<typeof createRtlStyleHelpers>;
metrics: ReturnType<typeof getTemplateMetrics>;
picture: Picture;
@@ -20,7 +21,14 @@ type BaseTemplateStylesInput = {
* ponytail: factory returns plain objects, not StyleSheet.create'd; each template does one
* StyleSheet.create pass so the final resolved styles are identical to before.
*/
export function createBaseTemplateStyles({ metadata, foreground, r, metrics, picture }: BaseTemplateStylesInput) {
export function createBaseTemplateStyles({
metadata,
foreground,
background,
r,
metrics,
picture,
}: BaseTemplateStylesInput) {
const bodyText = {
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
@@ -31,6 +39,15 @@ export function createBaseTemplateStyles({ metadata, foreground, r, metrics, pic
} satisfies Style;
return {
page: {
color: foreground,
backgroundColor: background,
fontFamily: metadata.typography.body.fontFamily,
fontSize: metadata.typography.body.fontSize,
lineHeight: metadata.typography.body.lineHeight,
direction: r.pageDirection,
} satisfies Style,
/** The canonical body text style; alias for `text` in StyleSheet slots. */
text: bodyText,
@@ -14,6 +14,14 @@ describe("ExperienceSection", () => {
});
});
describe("ItemTitle", () => {
it("renders award titles without the bold style", () => {
expect(source).toContain("const ItemTitle = ({ children, website, bold = true }: ItemTitleProps)");
expect(source).toContain("const title = bold ? <Bold>{children}</Bold> : <Text>{children}</Text>;");
expect(source).toContain("<ItemTitle website={item.website} bold={false}>");
});
});
describe("SectionShell", () => {
it("keeps section and heading style rules when section heading icons are hidden", () => {
expect(source).toContain("<View style={composeStyles(sectionStyle, sectionRuleStyle)} {...breakProps}>");
@@ -90,6 +90,7 @@ type ItemWebsite = {
type ItemTitleProps = {
children: ReactNode;
website: ItemWebsite;
bold?: boolean;
};
type ItemWebsiteLinkProps = {
@@ -383,9 +384,9 @@ const SectionItemHeader = ({ children }: SectionItemHeaderProps) => {
return <View style={composeStyles(sectionItemHeaderStyle)}>{children}</View>;
};
const ItemTitle = ({ children, website }: ItemTitleProps) => {
const ItemTitle = ({ children, website, bold = true }: ItemTitleProps) => {
const inlineWebsiteUrl = getInlineItemWebsiteUrl(website);
const title = <Bold>{children}</Bold>;
const title = bold ? <Bold>{children}</Bold> : <Text>{children}</Text>;
if (!inlineWebsiteUrl) return title;