← 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,'&').replace(/</g,'<').replace(/>/g,'>');
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);