Add function to use official font
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
// ==UserScript==
|
// ==UserScript==
|
||||||
// @name Game Datacards - Improved
|
// @name Game Datacards - Improved
|
||||||
// @namespace local
|
// @namespace local
|
||||||
// @version 1.0
|
// @version 1.1
|
||||||
// @description Adds card image export/import (ZIP) to the header and a button to rotate card backs for printing
|
// @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/*
|
// @match *://game-datacards.eu/*
|
||||||
// @grant none
|
// @grant none
|
||||||
// @run-at document-idle
|
// @run-at document-idle
|
||||||
@@ -145,6 +145,9 @@
|
|||||||
const EXPORT_ICON =
|
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>';
|
'<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 =
|
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>';
|
'<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.title = title;
|
||||||
b.setAttribute('aria-label', title);
|
b.setAttribute('aria-label', title);
|
||||||
b.innerHTML = iconSvg;
|
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;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,14 +176,120 @@
|
|||||||
group.className = 'app-header-group';
|
group.className = 'app-header-group';
|
||||||
group.appendChild(mkBtn('gdc-img-export', 'Export card images', EXPORT_ICON, doExport));
|
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-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,
|
// Insert the group right before the settings button's group,
|
||||||
// so the buttons sit to the left of the cog.
|
// so the buttons sit to the left of the cog.
|
||||||
const settingsGroup = settingsBtn.closest('.app-header-group');
|
const settingsGroup = settingsBtn.closest('.app-header-group');
|
||||||
settingsGroup.parentNode.insertBefore(group, settingsGroup);
|
settingsGroup.parentNode.insertBefore(group, settingsGroup);
|
||||||
|
syncCardFontButton();
|
||||||
return true;
|
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
|
// Rotate card backs for printing
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -240,6 +352,8 @@
|
|||||||
|
|
||||||
// The app renders after load, and the print sidebar only exists on the print
|
// 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.
|
// view, so keep watching the DOM until both mount points have been handled.
|
||||||
|
applyCardFont(isCardFontEnabled());
|
||||||
|
|
||||||
var headerDone = addHeaderButtons();
|
var headerDone = addHeaderButtons();
|
||||||
var sidebarDone = addRotateButton();
|
var sidebarDone = addRotateButton();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user