mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 00:03:27 +10:00
- include more local fonts, such as Times New Roman and Arial (fixes #2170)
- remove embedding fonts to PDF as it wasn't doing anything
This commit is contained in:
@ -11,23 +11,28 @@ import { useResumeStore } from "@/client/stores/resume";
|
||||
|
||||
import { SectionIcon } from "../shared/section-icon";
|
||||
|
||||
const localFonts = ["Arial", "Cambria", "Garamond", "Times New Roman"];
|
||||
|
||||
const fontSuggestions = [
|
||||
"Open Sans",
|
||||
"Merriweather",
|
||||
"Roboto Condensed",
|
||||
"Playfair Display",
|
||||
"Lato",
|
||||
"Lora",
|
||||
"PT Sans",
|
||||
"PT Serif",
|
||||
...localFonts,
|
||||
"IBM Plex Sans",
|
||||
"IBM Plex Serif",
|
||||
"Lato",
|
||||
"Lora",
|
||||
"Merriweather",
|
||||
"Open Sans",
|
||||
"Playfair Display",
|
||||
"PT Sans",
|
||||
"PT Serif",
|
||||
"Roboto Condensed",
|
||||
];
|
||||
|
||||
const families: ComboboxOption[] = fonts.map((font) => ({
|
||||
const families = fonts.map((font) => ({
|
||||
value: font.family,
|
||||
label: font.family,
|
||||
}));
|
||||
})) satisfies ComboboxOption[];
|
||||
|
||||
families.push(...localFonts.map((font) => ({ value: font, label: font })));
|
||||
|
||||
export const TypographySection = () => {
|
||||
const [subsets, setSubsets] = useState<ComboboxOption[]>([]);
|
||||
@ -52,10 +57,14 @@ export const TypographySection = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const subsets = fonts.find((font) => font.family === typography.font.family)?.subsets ?? [];
|
||||
setSubsets(subsets.map((subset) => ({ value: subset, label: subset })));
|
||||
if (subsets.length > 0) {
|
||||
setSubsets(subsets.map((subset) => ({ value: subset, label: subset })));
|
||||
}
|
||||
|
||||
const variants = fonts.find((font) => font.family === typography.font.family)?.variants ?? [];
|
||||
setVariants(variants.map((variant) => ({ value: variant, label: variant })));
|
||||
if (variants.length > 0) {
|
||||
setVariants(variants.map((variant) => ({ value: variant, label: variant })));
|
||||
}
|
||||
}, [typography.font.family]);
|
||||
|
||||
return (
|
||||
@ -69,31 +78,33 @@ export const TypographySection = () => {
|
||||
|
||||
<main className="grid gap-y-6">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
{fontSuggestions.map((font) => (
|
||||
<Button
|
||||
key={font}
|
||||
variant="outline"
|
||||
style={{ fontFamily: font }}
|
||||
disabled={typography.font.family === font}
|
||||
className={cn(
|
||||
"flex h-12 items-center justify-center overflow-hidden rounded border text-center text-xs ring-primary transition-colors hover:bg-secondary-accent focus:outline-none focus:ring-1 disabled:opacity-100 lg:text-sm",
|
||||
typography.font.family === font && "ring-1",
|
||||
)}
|
||||
onClick={() => {
|
||||
setValue("metadata.typography.font.family", font);
|
||||
setValue("metadata.typography.font.subset", "latin");
|
||||
setValue("metadata.typography.font.variants", ["regular"]);
|
||||
}}
|
||||
>
|
||||
{font}
|
||||
</Button>
|
||||
))}
|
||||
{fontSuggestions
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.map((font) => (
|
||||
<Button
|
||||
key={font}
|
||||
variant="outline"
|
||||
style={{ fontFamily: font }}
|
||||
disabled={typography.font.family === font}
|
||||
className={cn(
|
||||
"flex h-12 items-center justify-center overflow-hidden rounded border text-center text-xs ring-primary transition-colors hover:bg-secondary-accent focus:outline-none focus:ring-1 disabled:opacity-100 lg:text-sm",
|
||||
typography.font.family === font && "ring-1",
|
||||
)}
|
||||
onClick={() => {
|
||||
setValue("metadata.typography.font.family", font);
|
||||
setValue("metadata.typography.font.subset", "latin");
|
||||
setValue("metadata.typography.font.variants", ["regular"]);
|
||||
}}
|
||||
>
|
||||
{font}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label>{t`Font Family`}</Label>
|
||||
<Combobox
|
||||
options={families}
|
||||
options={families.sort((a, b) => a.label.localeCompare(b.label))}
|
||||
value={typography.font.family}
|
||||
searchPlaceholder={t`Search for a font family`}
|
||||
onValueChange={(value) => {
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
import { HttpService } from "@nestjs/axios";
|
||||
import { Injectable, InternalServerErrorException, Logger } from "@nestjs/common";
|
||||
import { ConfigService } from "@nestjs/config";
|
||||
import fontkit from "@pdf-lib/fontkit";
|
||||
import { ResumeDto } from "@reactive-resume/dto";
|
||||
import { ErrorMessage, getFontUrls } from "@reactive-resume/utils";
|
||||
import { ErrorMessage } from "@reactive-resume/utils";
|
||||
import retry from "async-retry";
|
||||
import { PDFDocument } from "pdf-lib";
|
||||
import { connect } from "puppeteer";
|
||||
@ -150,7 +149,7 @@ export class PrinterService {
|
||||
return temporaryHtml_;
|
||||
}, pageElement);
|
||||
|
||||
// Apply custom CSS if enabled
|
||||
// Apply custom CSS, if enabled
|
||||
const css = resume.data.metadata.css;
|
||||
|
||||
if (css.visible) {
|
||||
@ -177,24 +176,6 @@ export class PrinterService {
|
||||
|
||||
// Using 'pdf-lib', merge all the pages from their buffers into a single PDF
|
||||
const pdf = await PDFDocument.create();
|
||||
pdf.registerFontkit(fontkit);
|
||||
|
||||
// Get information about fonts used in the resume from the metadata
|
||||
const fontData = resume.data.metadata.typography.font;
|
||||
const fontUrls = getFontUrls(fontData.family, fontData.variants);
|
||||
|
||||
// Load all the fonts from the URLs using HttpService
|
||||
const responses = await Promise.all(
|
||||
fontUrls.map((url) =>
|
||||
this.httpService.axiosRef.get(url, {
|
||||
responseType: "arraybuffer",
|
||||
}),
|
||||
),
|
||||
);
|
||||
const fontsBuffer = responses.map((response) => response.data as ArrayBuffer);
|
||||
|
||||
// Embed all the fonts in the PDF
|
||||
await Promise.all(fontsBuffer.map((buffer) => pdf.embedFont(buffer)));
|
||||
|
||||
for (const element of pagesBuffer) {
|
||||
const page = await PDFDocument.load(element);
|
||||
|
||||
@ -145,7 +145,6 @@
|
||||
"@nestjs/swagger": "^7.4.2",
|
||||
"@nestjs/terminus": "^10.3.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"@phosphor-icons/react": "^2.1.7",
|
||||
"@prisma/client": "^5.22.0",
|
||||
"@radix-ui/react-accordion": "^1.2.2",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -74,9 +74,6 @@ importers:
|
||||
'@paralleldrive/cuid2':
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@pdf-lib/fontkit':
|
||||
specifier: ^1.1.1
|
||||
version: 1.1.1
|
||||
'@phosphor-icons/react':
|
||||
specifier: ^2.1.7
|
||||
version: 2.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@ -2976,9 +2973,6 @@ packages:
|
||||
'@paralleldrive/cuid2@2.2.2':
|
||||
resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==}
|
||||
|
||||
'@pdf-lib/fontkit@1.1.1':
|
||||
resolution: {integrity: sha512-KjMd7grNapIWS/Dm0gvfHEilSyAmeLvrEGVcqLGi0VYebuqqzTbgF29efCx7tvx+IEbG3zQciRSWl3GkUSvjZg==}
|
||||
|
||||
'@pdf-lib/standard-fonts@1.0.0':
|
||||
resolution: {integrity: sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==}
|
||||
|
||||
@ -14607,10 +14601,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@noble/hashes': 1.3.3
|
||||
|
||||
'@pdf-lib/fontkit@1.1.1':
|
||||
dependencies:
|
||||
pako: 1.0.11
|
||||
|
||||
'@pdf-lib/standard-fonts@1.0.0':
|
||||
dependencies:
|
||||
pako: 1.0.11
|
||||
|
||||
Reference in New Issue
Block a user