From 2b735cc5463974e7fa78245fe9dfca8be73917be Mon Sep 17 00:00:00 2001 From: luxick Date: Wed, 22 Jul 2026 18:45:23 +0200 Subject: [PATCH] Add function to use official font --- js/game-datcards-improved.user.js | 120 +++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/js/game-datcards-improved.user.js b/js/game-datcards-improved.user.js index 99aebf9..cb96723 100644 --- a/js/game-datcards-improved.user.js +++ b/js/game-datcards-improved.user.js @@ -1,8 +1,8 @@ // ==UserScript== // @name Game Datacards - Improved // @namespace local -// @version 1.0 -// @description Adds card image export/import (ZIP) to the header and a button to rotate card backs for printing +// @version 1.1 +// @description Adds card image export/import (ZIP) to the header, a button to rotate card backs for printing and a toggle for the official 10th edition card font // @match *://game-datacards.eu/* // @grant none // @run-at document-idle @@ -145,6 +145,9 @@ const EXPORT_ICON = ''; + const FONT_ICON = + ''; + const IMPORT_ICON = ''; @@ -155,7 +158,10 @@ b.title = title; b.setAttribute('aria-label', title); b.innerHTML = iconSvg; - b.onclick = () => fn().catch((e) => alert('Error: ' + e.message)); + b.onclick = () => { + const r = fn(); + if (r && typeof r.catch === 'function') r.catch((e) => alert('Error: ' + e.message)); + }; return b; } @@ -170,14 +176,120 @@ group.className = 'app-header-group'; group.appendChild(mkBtn('gdc-img-export', 'Export card images', EXPORT_ICON, doExport)); group.appendChild(mkBtn('gdc-img-import', 'Import card images', IMPORT_ICON, doImport)); + group.appendChild(mkBtn('gdc-card-font', 'Card font: Conduit ITC', FONT_ICON, toggleCardFont)); // Insert the group right before the settings button's group, // so the buttons sit to the left of the cog. const settingsGroup = settingsBtn.closest('.app-header-group'); settingsGroup.parentNode.insertBefore(group, settingsGroup); + syncCardFontButton(); return true; } + // --------------------------------------------------------------------------- + // Official 10th edition card font + // --------------------------------------------------------------------------- + + // The font has to be installed locally; the extra names cover the different + // family names the foundry/converters use for the same face. + const CARD_FONT = "'ConduitITCStd', 'Conduit ITC Std', 'ConduitITC Std', 'Conduit ITC'"; + const FONT_STYLE_ID = 'gdc-card-font'; + const FONT_PREF_KEY = 'gdc-card-font-enabled'; + + // Sizes below are the official ones for a full size card. The app draws cards + // scaled by --card-scaling-factor, so every size is scaled along with it. + function pt(size) { + return `calc(${size}pt * var(--card-scaling-factor, 1))`; + } + + function cardFontCss() { + return ` + .unit, .unit * { font-family: ${CARD_FONT}, sans-serif !important; } + + /* Unit name: extra bold 15pt */ + .unit .name_container .name { + font-weight: 800 !important; + font-size: ${pt(15)} !important; + } + + /* Unit description: light italic 8pt */ + .unit .name_container .subname, + .unit .header .description { + font-weight: 300 !important; + font-style: italic !important; + font-size: ${pt(8)} !important; + } + + /* Unit values: bold 14pt */ + .unit .stats_container .value, + .unit .stats_container .value-text { + font-weight: 700 !important; + font-size: ${pt(14)} !important; + } + + /* General weapon and abilities text: regular or bold 7.5pt */ + .unit .stats_container .caption, + .unit .invul .title, + .unit .heading .title, + .unit .ability .name, + .unit .ability .title, + .unit .footer .title, + .unit .footer .value { + font-weight: 700 !important; + font-size: ${pt(7.5)} !important; + } + + .unit .weapon .value, + .unit .ability .value, + .unit .ability .description, + .unit .description-container .description { + font-weight: 400 !important; + font-size: ${pt(7.5)} !important; + } + + /* Weapon abilities (the keyword/rule chips): bold 5.5pt */ + .unit .keyword-button, + .unit .keyword-button span, + .unit .rule-button, + .unit .rule-button span { + font-weight: 700 !important; + font-size: ${pt(5.5)} !important; + } + `; + } + + function isCardFontEnabled() { + return localStorage.getItem(FONT_PREF_KEY) === '1'; + } + + function applyCardFont(enabled) { + const existing = document.getElementById(FONT_STYLE_ID); + if (!enabled) { + if (existing) existing.remove(); + return; + } + const style = existing || document.createElement('style'); + style.id = FONT_STYLE_ID; + style.textContent = cardFontCss(); + if (!existing) document.head.appendChild(style); + } + + function syncCardFontButton() { + const btn = document.getElementById('gdc-card-font'); + if (!btn) return; + const on = isCardFontEnabled(); + btn.style.color = on ? '#e8b923' : ''; + btn.title = on ? 'Card font: Conduit ITC (on)' : 'Card font: Conduit ITC (off)'; + btn.setAttribute('aria-pressed', on ? 'true' : 'false'); + } + + function toggleCardFont() { + const next = !isCardFontEnabled(); + localStorage.setItem(FONT_PREF_KEY, next ? '1' : '0'); + applyCardFont(next); + syncCardFontButton(); + } + // --------------------------------------------------------------------------- // Rotate card backs for printing // --------------------------------------------------------------------------- @@ -240,6 +352,8 @@ // The app renders after load, and the print sidebar only exists on the print // view, so keep watching the DOM until both mount points have been handled. + applyCardFont(isCardFontEnabled()); + var headerDone = addHeaderButtons(); var sidebarDone = addRotateButton();