← back to Designerwallcoverings

scripts/brands-page/gen-wordmarks.cjs

81 lines

const fs=require('fs'),path=require('path');
const VL=process.env.HOME+'/Projects/Designer-Wallcoverings/vendor-logos';

// Brands that get a generated luxe SVG wordmark (DTD verdict B, 2026-06-14).
// label: display text. sans:true -> uppercase Montserrat (modern/house labels);
// else Playfair serif. line2 forces a manual break for long two-part names.
const WM = {
  'AS Creation':            { label:'AS Création',           sans:true },
  'Atomic 50 Ceilings':     { label:'Atomic 50',             sub:'CEILINGS', sans:true },
  'Backdrop':               { label:'Backdrop',              sans:true },
  'British Walls':          { label:'British Walls',         sans:true },
  'Clarence House':         { label:'Clarence House' },
  'Dedar':                  { label:'Dedar' },
  'Designer Wallcoverings': { label:'Designer',              sub:'WALLCOVERINGS' },
  'Dolce & Gabbana':        { label:'Dolce & Gabbana' },
  'DW Bespoke Studio':      { label:'DW Bespoke',            sub:'STUDIO', sans:true },
  'DW Exclusive Wallpaper': { label:'DW Exclusive',          sub:'WALLPAPER', sans:true },
  'Fentucci':               { label:'Fentucci' },
  'Glitter Walls':          { label:'Glitter Walls',         sans:true },
  'LA Walls':               { label:'LA Walls',              sans:true },
  'LEED Walls':             { label:'LEED Walls',            sans:true },
  'Novasuede':              { label:'Novasuede',             sans:true },
  'OLIVIA AND POPP':        { label:'Olivia & Popp' },
  'Peg Norriss':            { label:'Peg Norriss' },
  'PR Faux Leather':        { label:'PR Faux',               sub:'LEATHER', sans:true },
  'Primo Leathers':         { label:'Primo Leathers',        sans:true },
  'Retro Walls':            { label:'Retro Walls',           sans:true },
  'Sacha Walckhoff':        { label:'Sacha Walckhoff' },
  'Sancar':                 { label:'Sancar' },
  'Steve Abrams Studios':   { label:'Steve Abrams',          sub:'STUDIOS' },
  'SUGARBOO':               { label:'Sugarboo',              sans:true },
  'Surface Stick':          { label:'Surface Stick',         sans:true },
  'Ultrasuede':             { label:'Ultrasuede',            sans:true },
  'Wallpaper NYC':          { label:'Wallpaper',             sub:'NYC', sans:true },
  'Zeuxis Parrhasius at DW':{ label:'Zeuxis',                sub:'PARRHASIUS' },
  'Phillipe Romano':        { label:'Phillipe Romano' },
  'Hollywood Wallcoverings':{ label:'Hollywood',             sub:'WALLCOVERINGS' },
  'Malibu Wallpaper':       { label:'Malibu',                sub:'WALLPAPER', sans:true },
  'Jeffrey Stevens':        { label:'Jeffrey Stevens' },
  'Marimekko':              { label:'Marimekko',             sans:true },
  'Artmura':                { label:'Artmura',               sans:true },
};

const INK='#221f1c';
const esc=s=>s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
function fitSize(text, max, min, widthPx, sans){
  // rough em-width estimate; uppercase+tracked sans runs wider than serif
  const per = sans ? 0.82 : 0.6;
  let s=max;
  while(s>min && text.length*s*per > widthPx) s-=1;
  return s;
}
function svg(cfg){
  const W=420, H=160, cx=W/2;
  const serif="'Playfair Display', Georgia, 'Times New Roman', serif";
  const sans="'Montserrat', 'Helvetica Neue', Arial, sans-serif";
  const main=esc(cfg.label);
  const fam=cfg.sans?sans:serif;
  const tracking=cfg.sans?'0.16em':'0.01em';
  const transform=cfg.sans?'uppercase':'none';
  const fontMain=fitSize(cfg.label, cfg.sans?40:52, 22, W-72, cfg.sans);
  const hasSub=!!cfg.sub;
  const mainY=hasSub?70:88;
  let parts=`<text x="${cx}" y="${mainY}" text-anchor="middle" font-family="${fam}" font-weight="600" font-size="${fontMain}" letter-spacing="${tracking}" fill="${INK}" style="text-transform:${transform}">${main}</text>`;
  if(hasSub){
    parts+=`\n  <line x1="${cx-46}" y1="92" x2="${cx+46}" y2="92" stroke="${INK}" stroke-width="1" opacity="0.5"/>`;
    parts+=`\n  <text x="${cx}" y="120" text-anchor="middle" font-family="${sans}" font-weight="600" font-size="17" letter-spacing="0.34em" fill="${INK}" style="text-transform:uppercase">${esc(cfg.sub)}</text>`;
  }
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${W} ${H}" width="${W}" height="${H}" role="img">
  ${parts}
</svg>`;
}

let n=0;
for(const [brand,cfg] of Object.entries(WM)){
  const fname='wm-'+brand.toLowerCase().normalize('NFD').replace(/[^a-z0-9]+/g,'-').replace(/(^-|-$)/g,'')+'.svg';
  fs.writeFileSync(path.join(VL,fname), svg(cfg));
  n++;
}
console.log('generated',n,'wordmark SVGs into',VL);