mirror of
https://github.com/zenlm/logo.git
synced 2026-07-26 22:08:56 +00:00
brand isolation: build.ts is now brand-neutral (no hardcoded brand names — all from package.json); drop dead generator.ts/generate-showcase.ts and cross-brand aliases; publish 0.1.3
Enforces one-brand-per-repo: the shared build.ts carries no brand name (byte- identical everywhere, driven by package.json "brand"); removed the unused generator.ts/generate-showcase.ts (leftover, carried foreign-brand output paths); genericized the animated-mark provenance and README brand-package examples. Each package now names only its own brand.
This commit is contained in:
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="640" viewBox="0 0 1280 640" role="img" aria-label="Zen brand assets">
|
||||
<rect width="1280" height="640" fill="#0A0A0A"/>
|
||||
<svg x="120" y="200" width="240" height="240" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M66.22 83.26 A37 37 0 1 1 85.57 60.20" fill="none" stroke="#ffffff" stroke-width="11" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<text x="440" y="316" font-family="Inter,system-ui,-apple-system,sans-serif" font-size="94" font-weight="800" letter-spacing="-3" fill="#ffffff">Zen</text>
|
||||
<text x="443" y="366" font-family="Inter,system-ui,sans-serif" font-size="27" fill="#ffffff" opacity=".62">Official brand marks — SVG, PNG, ICO, favicons & app icons.</text>
|
||||
<rect x="443" y="390" width="710" height="2" rx="1" fill="#ffffff" opacity=".85"/>
|
||||
<text x="443" y="440" font-family="Inter,system-ui,sans-serif" font-size="23" font-weight="600" fill="#ffffff" opacity=".45">github.com/zenlm</text>
|
||||
<text x="1160" y="440" text-anchor="end" font-family="Inter,system-ui,sans-serif" font-size="23" font-weight="600" fill="#ffffff" opacity=".45">zenlm.org</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
Vendored
+4
-4
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Hanzo Logo Assets Showcase</title>
|
||||
<title>Zen Logo Assets Showcase</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-dark: #111;
|
||||
@@ -107,7 +107,7 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🎨 Hanzo Logo Assets</h1>
|
||||
<h1>🎨 Zen Logo Assets</h1>
|
||||
<p class="subtitle">Every brand mark, format, and size.</p>
|
||||
|
||||
<section class="section">
|
||||
@@ -244,14 +244,14 @@
|
||||
<p style="margin-bottom:10px;font-size:14px;">Light Menu Bar</p>
|
||||
<div class="menubar-demo">
|
||||
<img src="menubar/menubar-16.png" alt="Menu bar icon" style="width:16px;height:16px;">
|
||||
<span style="font-size:13px;color:#333;">Hanzo</span>
|
||||
<span style="font-size:13px;color:#333;">Zen</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p style="margin-bottom:10px;font-size:14px;">Dark Menu Bar</p>
|
||||
<div class="menubar-demo dark">
|
||||
<img src="menubar/iconTemplate.png" alt="Menu bar icon" style="width:16px;height:16px;filter:invert(1);">
|
||||
<span style="font-size:13px;color:#fff;">Hanzo</span>
|
||||
<span style="font-size:13px;color:#fff;">Zen</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@zenlm/logo",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.3",
|
||||
"description": "Official Zen ensō logo — animated, brand-neutral SVG",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+21
-11
@@ -1,8 +1,11 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Zen Logo Build Script
|
||||
* Generates all required icons for Zen ecosystem
|
||||
* Logo Build Script
|
||||
* Generates every brand icon, favicon, and social asset from the canonical
|
||||
* mark. Brand identity (name, tagline, github, domain) is read from
|
||||
* package.json "brand" — this file names no brand, so it is byte-identical
|
||||
* across every logo package.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
@@ -150,15 +153,19 @@ function readBrand(): Brand {
|
||||
let pkg: any = {};
|
||||
try { pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); } catch { /* defaults */ }
|
||||
const b = pkg.brand || {};
|
||||
const scope = (pkg.name || '').replace(/^@/, '').split('/')[0]; // e.g. hanzo
|
||||
const scope = (pkg.name || '').replace(/^@/, '').split('/')[0]; // package scope
|
||||
return {
|
||||
name: b.name || (scope ? scope.charAt(0).toUpperCase() + scope.slice(1) : 'Brand'),
|
||||
tagline: b.tagline || 'Official brand marks — SVG, PNG, ICO, favicons & app icons.',
|
||||
github: b.github || 'hanzoai',
|
||||
domain: b.domain || 'hanzo.ai',
|
||||
github: b.github || scope,
|
||||
domain: b.domain || '',
|
||||
};
|
||||
}
|
||||
|
||||
// Read once at load — every display string below is driven by this, so the
|
||||
// file carries no brand name of its own.
|
||||
const BRAND = readBrand();
|
||||
|
||||
// generateHero composes the README hero card (1280×640): the brand's own white
|
||||
// mark + the real brand NAME (not the "logo" placeholder the template shipped)
|
||||
// + a full tagline + github/domain footer. Written to .github/hero.svg, which
|
||||
@@ -184,11 +191,14 @@ function generateHero(whiteMark: string): void {
|
||||
`;
|
||||
fs.mkdirSync('.github', { recursive: true });
|
||||
fs.writeFileSync('.github/hero.svg', hero);
|
||||
console.log(`✓ .github/hero.svg (${brand.name})`);
|
||||
// Also ship the hero inside dist/ so it resolves on the npm page via a CDN
|
||||
// (jsdelivr) URL even for packages that aren't backed by a public git repo.
|
||||
fs.writeFileSync('dist/hero.svg', hero);
|
||||
console.log(`✓ .github/hero.svg + dist/hero.svg (${brand.name})`);
|
||||
}
|
||||
|
||||
async function buildAll(): Promise<void> {
|
||||
console.log('🎨 Hanzo Logo Builder\n');
|
||||
console.log(`🎨 ${BRAND.name} Logo Builder\n`);
|
||||
|
||||
const colorSVG = getColorSVG();
|
||||
const monoSVG = getMonoSVG();
|
||||
@@ -354,7 +364,7 @@ function generateShowcase(): void {
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Hanzo Logo Assets Showcase</title>
|
||||
<title>${BRAND.name} Logo Assets Showcase</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg-dark: #111;
|
||||
@@ -458,7 +468,7 @@ function generateShowcase(): void {
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🎨 Hanzo Logo Assets</h1>
|
||||
<h1>🎨 ${BRAND.name} Logo Assets</h1>
|
||||
<p class="subtitle">Every brand mark, format, and size.</p>
|
||||
|
||||
<section class="section">
|
||||
@@ -595,14 +605,14 @@ function generateShowcase(): void {
|
||||
<p style="margin-bottom:10px;font-size:14px;">Light Menu Bar</p>
|
||||
<div class="menubar-demo">
|
||||
<img src="menubar/menubar-16.png" alt="Menu bar icon" style="width:16px;height:16px;">
|
||||
<span style="font-size:13px;color:#333;">Hanzo</span>
|
||||
<span style="font-size:13px;color:#333;">${BRAND.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p style="margin-bottom:10px;font-size:14px;">Dark Menu Bar</p>
|
||||
<div class="menubar-demo dark">
|
||||
<img src="menubar/iconTemplate.png" alt="Menu bar icon" style="width:16px;height:16px;filter:invert(1);">
|
||||
<span style="font-size:13px;color:#fff;">Hanzo</span>
|
||||
<span style="font-size:13px;color:#fff;">${BRAND.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import sharp from 'sharp';
|
||||
import { getColorSVG, getMonoSVG } from './logos';
|
||||
|
||||
/**
|
||||
* Generate a PNG icon from SVG
|
||||
*/
|
||||
export async function generateIcon(
|
||||
svgString: string,
|
||||
outputPath: string,
|
||||
size: number
|
||||
): Promise<void> {
|
||||
const dir = path.dirname(outputPath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
await sharp(Buffer.from(svgString))
|
||||
.resize(size, size)
|
||||
.png()
|
||||
.toFile(outputPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate all standard icons
|
||||
*/
|
||||
export async function generateAllIcons(outputDir: string = 'dist/icons'): Promise<void> {
|
||||
const colorSVG = getColorSVG();
|
||||
const monoSVG = getMonoSVG();
|
||||
|
||||
// Standard sizes
|
||||
const sizes = [16, 32, 64, 128, 256, 512, 1024];
|
||||
|
||||
console.log('Generating icons...');
|
||||
|
||||
for (const size of sizes) {
|
||||
await generateIcon(colorSVG, path.join(outputDir, `zen-${size}.png`), size);
|
||||
await generateIcon(monoSVG, path.join(outputDir, `zen-mono-${size}.png`), size);
|
||||
}
|
||||
|
||||
// Generate @2x versions for macOS
|
||||
const macSizes = [
|
||||
{ base: 16, scale: 2 },
|
||||
{ base: 32, scale: 2 },
|
||||
{ base: 128, scale: 2 },
|
||||
{ base: 256, scale: 2 },
|
||||
{ base: 512, scale: 2 }
|
||||
];
|
||||
|
||||
for (const { base, scale } of macSizes) {
|
||||
await generateIcon(
|
||||
colorSVG,
|
||||
path.join(outputDir, `zen-${base}@${scale}x.png`),
|
||||
base * scale
|
||||
);
|
||||
}
|
||||
|
||||
// Menu bar templates
|
||||
await generateIcon(monoSVG, path.join(outputDir, 'iconTemplate.png'), 16);
|
||||
await generateIcon(monoSVG, path.join(outputDir, 'iconTemplate@2x.png'), 32);
|
||||
await generateIcon(monoSVG, path.join(outputDir, 'iconTemplate@3x.png'), 48);
|
||||
|
||||
console.log('✅ Icons generated successfully!');
|
||||
}
|
||||
Reference in New Issue
Block a user