Add function to use official font

This commit is contained in:
2026-07-22 18:45:23 +02:00
parent 0c47bc48a6
commit 2b735cc546
+117 -3
View File
@@ -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 =
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" x2="12" y1="15" y2="3"></line></svg>';
const FONT_ICON =
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"></polyline><line x1="9" x2="15" y1="20" y2="20"></line><line x1="12" x2="12" y1="4" y2="20"></line></svg>';
const IMPORT_ICON =
'<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" x2="12" y1="3" y2="15"></line></svg>';
@@ -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();