fix(pdf): render truck as vector, fix back logo coloring
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Failing after 1m21s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Failing after 1m21s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
This commit is contained in:
9898
lib/TruckBlueprint.tsx
Normal file
9898
lib/TruckBlueprint.tsx
Normal file
File diff suppressed because one or more lines are too long
@@ -16,6 +16,7 @@ import {
|
||||
Circle,
|
||||
} from '@react-pdf/renderer';
|
||||
import * as path from 'path';
|
||||
import { TruckBlueprint } from './TruckBlueprint';
|
||||
|
||||
// Register embedded fonts so Ghostscript -dNoOutputFonts can convert them to
|
||||
// outlines (curves). Built-in PDF fonts like Helvetica are NEVER embedded and
|
||||
@@ -89,9 +90,6 @@ const styles = StyleSheet.create({
|
||||
frontBackgroundImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'contain',
|
||||
objectPositionX: 'center',
|
||||
objectPositionY: 'center',
|
||||
opacity: 0.4, // Less transparent, more contrast
|
||||
},
|
||||
frontContainer: {
|
||||
@@ -362,16 +360,25 @@ const VectorLogo = ({
|
||||
paths,
|
||||
style,
|
||||
overrideColor,
|
||||
overrideWhiteColor,
|
||||
}: {
|
||||
paths: { d: string; fill: string }[];
|
||||
style: any;
|
||||
overrideColor?: string;
|
||||
overrideWhiteColor?: string;
|
||||
}) => (
|
||||
<Svg viewBox="0 0 295 99" style={style}>
|
||||
<G {...({ fillRule: 'evenodd', clipRule: 'evenodd' } as any)}>
|
||||
{paths.map((p, i) => (
|
||||
<Path key={i} d={p.d} fill={overrideColor || p.fill} />
|
||||
))}
|
||||
{paths.map((p, i) => {
|
||||
let fill = overrideColor || p.fill;
|
||||
if (
|
||||
overrideWhiteColor &&
|
||||
(p.fill === 'white' || p.fill === '#ffffff' || p.fill === '#fff')
|
||||
) {
|
||||
fill = overrideWhiteColor;
|
||||
}
|
||||
return <Path key={i} d={p.d} fill={fill} />;
|
||||
})}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
@@ -704,8 +711,7 @@ export const PDFBusinessCard: React.FC<PDFBusinessCardProps> = ({
|
||||
style={[styles.pageBleed, isWhiteVariant && { backgroundColor: '#ffffff' }]}
|
||||
>
|
||||
<View style={styles.truckWrapper}>
|
||||
<Image
|
||||
src={bgImagePath}
|
||||
<TruckBlueprint
|
||||
style={[styles.frontBackgroundImage, isWhiteVariant && { opacity: 0.2 }]}
|
||||
/>
|
||||
</View>
|
||||
@@ -766,7 +772,11 @@ export const PDFBusinessCard: React.FC<PDFBusinessCardProps> = ({
|
||||
<Page size={[258, 173]} style={styles.pageBleedBack}>
|
||||
<View style={styles.backContainer}>
|
||||
<View style={styles.backHeader}>
|
||||
<VectorLogo paths={logoBluePaths} style={styles.backLogo} overrideColor={COLORS.blue} />
|
||||
<VectorLogo
|
||||
paths={logoWhitePaths}
|
||||
style={styles.backLogo}
|
||||
overrideWhiteColor={COLORS.blue}
|
||||
/>
|
||||
<View style={styles.accentLineHorizontal} />
|
||||
</View>
|
||||
|
||||
|
||||
64
scripts/svg-to-react-pdf.ts
Normal file
64
scripts/svg-to-react-pdf.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import fs from 'fs';
|
||||
|
||||
const svgFile = process.argv[2];
|
||||
const outFile = process.argv[3];
|
||||
|
||||
let content = fs.readFileSync(svgFile, 'utf8');
|
||||
|
||||
content = content.replace(/<\?xml.*\?>/g, '');
|
||||
content = content.replace(/<!DOCTYPE.*>/g, '');
|
||||
content = content.replace(/xmlns:xlink="[^"]+"/g, '');
|
||||
content = content.replace(/xmlns:serif="[^"]+"/g, '');
|
||||
content = content.replace(/xml:space="preserve"/g, '');
|
||||
content = content.replace(/xmlns="[^"]+"/g, '');
|
||||
content = content.replace(/version="[^"]+"/g, '');
|
||||
|
||||
// Convert attributes to camelCase
|
||||
content = content.replace(/fill-rule/g, 'fillRule');
|
||||
content = content.replace(/clip-rule/g, 'clipRule');
|
||||
content = content.replace(/stroke-linejoin/g, 'strokeLinejoin');
|
||||
content = content.replace(/stroke-miterlimit/g, 'strokeMiterlimit');
|
||||
|
||||
// Convert style="fill:#xxxx;fill-rule:nonzero;" to fill="#xxxx" fillRule="nonzero"
|
||||
content = content.replace(/style="([^"]+)"/g, (match, styleStr) => {
|
||||
const parts = styleStr.split(';').filter(Boolean);
|
||||
let attrs = [];
|
||||
for (const part of parts) {
|
||||
const [key, val] = part.split(':');
|
||||
if (key === 'fill') attrs.push(`fill="${val}"`);
|
||||
if (key === 'fillRule' || key === 'fill-rule') attrs.push(`fillRule="${val}"`);
|
||||
if (key === 'clipRule' || key === 'clip-rule') attrs.push(`clipRule="${val}"`);
|
||||
if (key === 'strokeLinejoin' || key === 'stroke-linejoin')
|
||||
attrs.push(`strokeLinejoin="${val}"`);
|
||||
if (key === 'strokeMiterlimit' || key === 'stroke-miterlimit')
|
||||
attrs.push(`strokeMiterlimit="${val}"`);
|
||||
}
|
||||
return attrs.join(' ');
|
||||
});
|
||||
|
||||
// React components
|
||||
content = content.replace(/<svg/g, '<Svg');
|
||||
content = content.replace(/<\/svg>/g, '</Svg>');
|
||||
content = content.replace(/<g/g, '<G');
|
||||
content = content.replace(/<\/g>/g, '</G>');
|
||||
content = content.replace(/<path/g, '<Path');
|
||||
content = content.replace(/<\/path>/g, '</Path>');
|
||||
|
||||
// In React PDF, width/height on Svg can be removed and controlled via style.
|
||||
content = content.replace(/width="100%" height="100%" /, '');
|
||||
|
||||
const final = `
|
||||
import React from 'react';
|
||||
import { Svg, G, Path } from '@react-pdf/renderer';
|
||||
|
||||
export const TruckBlueprint = ({ style, opacity = 1 }: { style?: any, opacity?: number }) => (
|
||||
<Svg viewBox="0 0 1615 974" style={[style, { opacity }]}>
|
||||
<G fillRule="evenodd" clipRule="evenodd" strokeLinejoin="round" strokeMiterlimit="2">
|
||||
${content.match(/<G[\s\S]*<\/G>/)?.[0] || content}
|
||||
</G>
|
||||
</Svg>
|
||||
);
|
||||
`;
|
||||
|
||||
fs.writeFileSync(outFile, final);
|
||||
console.log('Done!');
|
||||
Reference in New Issue
Block a user