improvement: logo and name svgs updated and replaced.
This commit is contained in:
117
frontend/scripts/build-brand-components.mjs
Normal file
117
frontend/scripts/build-brand-components.mjs
Normal file
@@ -0,0 +1,117 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const brand = path.join(root, 'src/assets/brand');
|
||||
|
||||
function stripBom(s) {
|
||||
return s.replace(/^\uFEFF/, '');
|
||||
}
|
||||
|
||||
function svgToInner(svg) {
|
||||
return svg
|
||||
.replace(/<\?xml[^>]*>/, '')
|
||||
.replace(/<svg[^>]*>/, '')
|
||||
.replace(/<\/svg>\s*$/, '')
|
||||
.replace(/<title>[^<]*<\/title>\s*/, '')
|
||||
.trim()
|
||||
.replace(/fill-rule=/g, 'fillRule=');
|
||||
}
|
||||
|
||||
const wordmark = stripBom(fs.readFileSync(path.join(brand, 'wordmark.svg'), 'utf8'));
|
||||
const logo = stripBom(fs.readFileSync(path.join(brand, 'logo.svg'), 'utf8'));
|
||||
const wmInner = svgToInner(wordmark);
|
||||
const lgInner = svgToInner(logo);
|
||||
|
||||
const wordmarkTsx = `import type { CSSProperties } from 'react';
|
||||
|
||||
export const BRAND_NAME = 'Nudentic';
|
||||
|
||||
type BrandWordmarkProps = {
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
decorative?: boolean;
|
||||
};
|
||||
|
||||
/** Official wordmark from \`src/assets/brand/wordmark.svg\`. Re-run \`scripts/build-brand-components.mjs\` after editing the SVG. */
|
||||
export function BrandWordmark({ className, style, decorative }: BrandWordmarkProps) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 345 70"
|
||||
className={className}
|
||||
style={{ display: 'inline-block', height: '1em', width: 'auto', overflow: 'visible', ...style }}
|
||||
role={decorative ? undefined : 'img'}
|
||||
aria-label={decorative ? undefined : BRAND_NAME}
|
||||
aria-hidden={decorative || undefined}
|
||||
>
|
||||
${wmInner}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
const logoTsx = `import type { CSSProperties } from 'react';
|
||||
import { BRAND_NAME } from '@/components/ui/shared/BrandWordmark';
|
||||
|
||||
type BrandLogoProps = {
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
decorative?: boolean;
|
||||
};
|
||||
|
||||
/** Official mark from \`src/assets/brand/logo.svg\`. Re-run \`scripts/build-brand-components.mjs\` after editing the SVG. */
|
||||
export function BrandLogo({ className, style, decorative }: BrandLogoProps) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 4294 3630"
|
||||
className={className}
|
||||
style={{ display: 'inline-block', height: '1.15em', width: 'auto', overflow: 'visible', ...style }}
|
||||
role={decorative ? undefined : 'img'}
|
||||
aria-label={decorative ? undefined : BRAND_NAME}
|
||||
aria-hidden={decorative || undefined}
|
||||
>
|
||||
${lgInner}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
const lockupTsx = `import type { CSSProperties } from 'react';
|
||||
import { BrandLogo } from '@/components/ui/shared/BrandLogo';
|
||||
import { BrandWordmark, BRAND_NAME } from '@/components/ui/shared/BrandWordmark';
|
||||
|
||||
type BrandLockupProps = {
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
};
|
||||
|
||||
/** Logo + wordmark. Size via font-size / text-* on this wrapper (\`em\` on the SVGs). */
|
||||
export function BrandLockup({ className, style }: BrandLockupProps) {
|
||||
return (
|
||||
<span
|
||||
dir="ltr"
|
||||
className={className}
|
||||
style={{ display: 'inline-flex', alignItems: 'center', gap: '0.35em', ...style }}
|
||||
role="img"
|
||||
aria-label={BRAND_NAME}
|
||||
>
|
||||
<BrandLogo decorative />
|
||||
<BrandWordmark decorative />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
fs.writeFileSync(path.join(root, 'src/components/ui/shared/BrandWordmark.tsx'), wordmarkTsx);
|
||||
fs.writeFileSync(path.join(root, 'src/components/ui/shared/BrandLogo.tsx'), logoTsx);
|
||||
fs.writeFileSync(path.join(root, 'src/components/ui/shared/BrandLockup.tsx'), lockupTsx);
|
||||
|
||||
const icon = logo
|
||||
.replaceAll('fill="currentColor"', 'fill="#0f172a"')
|
||||
.replace(/<title>[^<]*<\/title>\s*/, '');
|
||||
fs.writeFileSync(path.join(root, 'src/app/icon.svg'), icon);
|
||||
|
||||
console.log('brand components + icon.svg written');
|
||||
Reference in New Issue
Block a user