mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-08 12:04:52 +10:00
refactor(pdf): replace ts-pattern match chains with satisfies Record maps
Two match chains in sections.tsx are replaced with plain lookup maps typed via `satisfies Record<CustomSectionType, ...>` which preserves compile-time exhaustiveness without the ts-pattern dependency. Remove ts-pattern from packages/pdf/package.json. Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa
This commit is contained in:
@@ -28,8 +28,7 @@
|
||||
"node-html-parser": "^8.0.4",
|
||||
"phosphor-icons-react-pdf": "^0.1.3",
|
||||
"react": "^19.2.7",
|
||||
"react-pdf-html": "^2.1.5",
|
||||
"ts-pattern": "^5.9.0"
|
||||
"react-pdf-html": "^2.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-pdf/types": "^2.11.1",
|
||||
|
||||
@@ -3,6 +3,7 @@ import type {
|
||||
AwardItem,
|
||||
CertificationItem,
|
||||
CoverLetterItem,
|
||||
CustomSectionType,
|
||||
EducationItem,
|
||||
ExperienceItem,
|
||||
InterestItem,
|
||||
@@ -22,7 +23,6 @@ import type { ReactNode } from "react";
|
||||
import type { StyleInput, TemplatePlacement } from "./styles";
|
||||
import type { CustomItemSection, ItemSection } from "./types";
|
||||
import { Children, createContext, isValidElement, use } from "react";
|
||||
import { match } from "ts-pattern";
|
||||
import { View } from "#react-pdf-renderer";
|
||||
import { useRender } from "../../context";
|
||||
import { getResumeSectionIcon } from "../../section-icon";
|
||||
@@ -929,51 +929,50 @@ const CustomSection = ({ sectionId, showHeading = true }: CustomSectionProps) =>
|
||||
|
||||
if (!customSection) return null;
|
||||
|
||||
return match(customSection.type)
|
||||
.with("summary", () => (
|
||||
// ponytail: satisfies Record<CustomSectionType,...> gives compile-time exhaustiveness without ts-pattern
|
||||
const customSectionMap = {
|
||||
summary: () => (
|
||||
<CustomSummarySection section={customSection as CustomItemSection<SummaryItem>} showHeading={showHeading} />
|
||||
))
|
||||
.with("profiles", () => (
|
||||
),
|
||||
profiles: () => (
|
||||
<ProfileSection sectionId={sectionId} sectionData={customSection as CustomItemSection<ProfileItem>} />
|
||||
))
|
||||
.with("experience", () => (
|
||||
),
|
||||
experience: () => (
|
||||
<ExperienceSection sectionId={sectionId} sectionData={customSection as CustomItemSection<ExperienceItem>} />
|
||||
))
|
||||
.with("education", () => (
|
||||
),
|
||||
education: () => (
|
||||
<EducationSection sectionId={sectionId} sectionData={customSection as CustomItemSection<EducationItem>} />
|
||||
))
|
||||
.with("projects", () => (
|
||||
),
|
||||
projects: () => (
|
||||
<ProjectsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<ProjectItem>} />
|
||||
))
|
||||
.with("skills", () => (
|
||||
<SkillsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<SkillItem>} />
|
||||
))
|
||||
.with("languages", () => (
|
||||
),
|
||||
skills: () => <SkillsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<SkillItem>} />,
|
||||
languages: () => (
|
||||
<LanguagesSection sectionId={sectionId} sectionData={customSection as CustomItemSection<LanguageItem>} />
|
||||
))
|
||||
.with("interests", () => (
|
||||
),
|
||||
interests: () => (
|
||||
<InterestsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<InterestItem>} />
|
||||
))
|
||||
.with("awards", () => (
|
||||
<AwardsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<AwardItem>} />
|
||||
))
|
||||
.with("certifications", () => (
|
||||
),
|
||||
awards: () => <AwardsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<AwardItem>} />,
|
||||
certifications: () => (
|
||||
<CertificationsSection
|
||||
sectionId={sectionId}
|
||||
sectionData={customSection as CustomItemSection<CertificationItem>}
|
||||
/>
|
||||
))
|
||||
.with("publications", () => (
|
||||
),
|
||||
publications: () => (
|
||||
<PublicationsSection sectionId={sectionId} sectionData={customSection as CustomItemSection<PublicationItem>} />
|
||||
))
|
||||
.with("volunteer", () => (
|
||||
),
|
||||
volunteer: () => (
|
||||
<VolunteerSection sectionId={sectionId} sectionData={customSection as CustomItemSection<VolunteerItem>} />
|
||||
))
|
||||
.with("references", () => (
|
||||
),
|
||||
references: () => (
|
||||
<ReferencesSection sectionId={sectionId} sectionData={customSection as CustomItemSection<ReferenceItem>} />
|
||||
))
|
||||
.with("cover-letter", () => <CoverLetterSection section={customSection as CustomItemSection<CoverLetterItem>} />)
|
||||
.exhaustive();
|
||||
),
|
||||
"cover-letter": () => <CoverLetterSection section={customSection as CustomItemSection<CoverLetterItem>} />,
|
||||
} satisfies Record<CustomSectionType, () => ReactNode>;
|
||||
|
||||
return customSectionMap[customSection.type]();
|
||||
};
|
||||
|
||||
export const Section = ({ section, placement, showHeading = true }: SectionProps) => {
|
||||
@@ -981,26 +980,29 @@ export const Section = ({ section, placement, showHeading = true }: SectionProps
|
||||
|
||||
if (!isSectionVisible(section, data)) return null;
|
||||
|
||||
// ponytail: satisfies exhaustiveness over built-in types; custom IDs fall through to CustomSection
|
||||
const builtInSectionMap = {
|
||||
summary: () => <SummarySection showHeading={showHeading} />,
|
||||
profiles: () => <ProfileSection />,
|
||||
experience: () => <ExperienceSection />,
|
||||
education: () => <EducationSection />,
|
||||
projects: () => <ProjectsSection />,
|
||||
skills: () => <SkillsSection />,
|
||||
languages: () => <LanguagesSection />,
|
||||
interests: () => <InterestsSection />,
|
||||
awards: () => <AwardsSection />,
|
||||
certifications: () => <CertificationsSection />,
|
||||
publications: () => <PublicationsSection />,
|
||||
volunteer: () => <VolunteerSection />,
|
||||
references: () => <ReferencesSection />,
|
||||
} satisfies Record<Exclude<CustomSectionType, "cover-letter">, () => ReactNode>;
|
||||
|
||||
const render = (builtInSectionMap as Record<string, (() => ReactNode) | undefined>)[section];
|
||||
|
||||
return (
|
||||
<TemplatePlacementProvider placement={placement}>
|
||||
<SectionStyleProvider context={getSectionStyleRuleContext(data, section)}>
|
||||
{match(section)
|
||||
.with("summary", () => <SummarySection showHeading={showHeading} />)
|
||||
.with("profiles", () => <ProfileSection />)
|
||||
.with("experience", () => <ExperienceSection />)
|
||||
.with("education", () => <EducationSection />)
|
||||
.with("projects", () => <ProjectsSection />)
|
||||
.with("skills", () => <SkillsSection />)
|
||||
.with("languages", () => <LanguagesSection />)
|
||||
.with("interests", () => <InterestsSection />)
|
||||
.with("awards", () => <AwardsSection />)
|
||||
.with("certifications", () => <CertificationsSection />)
|
||||
.with("publications", () => <PublicationsSection />)
|
||||
.with("volunteer", () => <VolunteerSection />)
|
||||
.with("references", () => <ReferencesSection />)
|
||||
.otherwise(() => (
|
||||
<CustomSection sectionId={section} showHeading={showHeading} />
|
||||
))}
|
||||
{render ? render() : <CustomSection sectionId={section} showHeading={showHeading} />}
|
||||
</SectionStyleProvider>
|
||||
</TemplatePlacementProvider>
|
||||
);
|
||||
|
||||
Generated
-3
@@ -947,9 +947,6 @@ importers:
|
||||
react-pdf-html:
|
||||
specifier: ^2.1.5
|
||||
version: 2.1.5(@react-pdf/renderer@4.5.1(react@19.2.7))(react@19.2.7)
|
||||
ts-pattern:
|
||||
specifier: ^5.9.0
|
||||
version: 5.9.0
|
||||
devDependencies:
|
||||
'@react-pdf/types':
|
||||
specifier: ^2.11.1
|
||||
|
||||
Reference in New Issue
Block a user