mirror of
https://github.com/luxfi/safe-wallet.git
synced 2026-10-30 15:19:21 +00:00
One family. Font stacks name Zen and fall back to the native faces, tokens name the role rather than a face, and the packages that used to supply a face now point at @hanzo/font. Self-hosted @font-face blocks are removed rather than renamed: rewriting the family in one would leave a src pointing at a file this repo no longer ships. @hanzo/font carries the binaries and declares the faces, so the local copies go with the declaration that used them. Comments naming a face we no longer use are deleted, not reworded.
67 lines
3.6 KiB
JavaScript
67 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
import { dirname, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { getWordmarkAdaptiveSVG, getMenuBarSVG as luxMark, getFaviconSVG as luxKeylined } from '@luxfi/logo'
|
|
import { getMenuBarSVG as hanzoMark } from '@hanzo/logo'
|
|
import { getColorSVG as zooMark } from '@zooai/logo'
|
|
import { logoColorSVG as parsMark } from '@parsdao/brand'
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url))
|
|
const webRoot = resolve(here, '..')
|
|
|
|
// Each brand's letterforms are drawn by that brand's own logo package, so this
|
|
// app does not keep a second copy of anyone's artwork to fall out of step with
|
|
// the first. Written before `next build` so the files exist for the dev server
|
|
// and the image alike.
|
|
|
|
// Place a mark inside a larger drawing without touching its coordinates: an
|
|
// inner <svg> keeps its own viewBox and scales into the box it is given. Any
|
|
// size the mark states for itself is dropped — the box decides — and stating
|
|
// it twice would make the file malformed.
|
|
const inset = (svg, box) =>
|
|
svg.replace(
|
|
/^<svg([^>]*)>/,
|
|
(_, attrs) =>
|
|
`<svg x="${box.x}" y="${box.y}" width="${box.w}" height="${box.h}"${attrs.replace(/\s+(?:x|y|width|height)="[^"]*"/g, '')}>`,
|
|
)
|
|
|
|
// A mark drawn in currentColor has no colour of its own, and an SVG loaded as
|
|
// an image is its own document with nothing to inherit from — so it must say
|
|
// what its ink is, and say it again for a dark reader.
|
|
const adapt = (svg) =>
|
|
svg.replace(/^(<svg[^>]*>)/, '$1<style>svg{color:#121312}@media(prefers-color-scheme:dark){svg{color:#fff}}</style>')
|
|
|
|
// Horizontal lockup: the mark, then the name. Ink follows the reader's theme —
|
|
// marks drawn in currentColor track it, marks drawn in brand colour keep theirs.
|
|
const lockup = (mark, name, width) =>
|
|
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} 28" width="${width}" height="28" role="img" aria-label="${name}"><style>svg{color:#121312}.t{fill:#121312;font-family:Zen, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;font-size:19px;font-weight:700;letter-spacing:-.4px}@media(prefers-color-scheme:dark){svg{color:#fff}.t{fill:#fff}}</style>${inset(mark, { x: 0, y: 4, w: 20, h: 20 })}<text class="t" x="30" y="20">${name}</text></svg>`
|
|
|
|
const brands = {
|
|
// Lux draws its own wordmark, so the name is lettered rather than typeset. The
|
|
// mark is the triangle — `getWordmarkSquareSVG` letterboxes the wordmark into a
|
|
// square instead, and its own docstring puts the floor at 32px, which is twice
|
|
// a tab icon. It was reaching the favicon, where "LUX" closed into grey mush.
|
|
lux: {
|
|
'logo.svg': getWordmarkAdaptiveSVG(),
|
|
'mark.svg': adapt(luxMark()),
|
|
// What the tab wears while it waits on a signature. It keeps the keyline
|
|
// instead of the theme rule, because an alert should read red on either
|
|
// chrome rather than turn back into the ordinary mark on one of them.
|
|
'mark-alert.svg': luxKeylined().replace('fill="#ffffff"', 'fill="#ff3b30"'),
|
|
},
|
|
zoo: { 'logo.svg': lockup(zooMark(), 'Zoo Safe', 120), 'mark.svg': zooMark() },
|
|
pars: { 'logo.svg': lockup(parsMark, 'Pars Safe', 122), 'mark.svg': parsMark },
|
|
hanzo: { 'logo.svg': lockup(hanzoMark(), 'Hanzo Vault', 150), 'mark.svg': adapt(hanzoMark()) },
|
|
}
|
|
|
|
for (const [slug, marks] of Object.entries(brands)) {
|
|
const outDir = resolve(webRoot, 'public', 'brand', slug)
|
|
mkdirSync(outDir, { recursive: true })
|
|
for (const [name, svg] of Object.entries(marks)) {
|
|
const outPath = resolve(outDir, name)
|
|
writeFileSync(outPath, svg)
|
|
console.log(`Wrote ${outPath}`)
|
|
}
|
|
}
|