4,554
edits
No edit summary |
No edit summary |
||
Line 1,053: | Line 1,053: | ||
$(document).off('click.print', '#print-button'); | $(document).off('click.print', '#print-button'); | ||
// Warm the font cache in the PARENT document (no Date.now; you already version via ?v=) | |||
function preloadFontForPrint() { | function preloadFontForPrint() { | ||
var link = document.createElement('link'); | var link = document.createElement('link'); | ||
Line 1,058: | Line 1,059: | ||
link.as = 'font'; | link.as = 'font'; | ||
link.type = 'font/woff2'; | link.type = 'font/woff2'; | ||
link.href = '/fonts/HALColant-TextRegular.woff2?v=20250820 | link.href = '/fonts/HALColant-TextRegular.woff2?v=20250820'; | ||
link.crossOrigin = 'anonymous'; | link.crossOrigin = 'anonymous'; | ||
document.head.appendChild(link); | document.head.appendChild(link); | ||
// keep it; no need to remove immediately | |||
} | } | ||
$(document).on('click.print', '#print-button', function () { | $(document).on('click.print', '#print-button', function () { | ||
preloadFontForPrint(); | |||
var title = window.currentEntryTitle; // e.g. "090" | |||
if (!title) { console.warn('[print] no currentEntryTitle'); window.print(); return; } | |||
var pageUrl = mw.util.getUrl(title); | |||
var pageUrlFresh = pageUrl + (pageUrl.indexOf('?') > -1 ? '&' : '?') + '_=' + Date.now(); | |||
console.log('[print] fetching page HTML:', pageUrlFresh); | |||
$.get(pageUrlFresh).done(function (html) { | |||
var $tmp = $('<div>').html(html); | |||
var $print = $tmp.find('.print-only').first(); | |||
console.log('[print] .print-only found:', $print.length); | |||
if (!$print.length) { console.warn('[print] no .print-only found; fallback print'); window.print(); return; } | |||
var iframe = document.createElement('iframe'); | |||
iframe.style.position = 'fixed'; | |||
iframe.style.right = '0'; | |||
iframe.style.bottom = '0'; | |||
iframe.style.width = '0'; | |||
iframe.style.height = '0'; | |||
iframe.style.border = '0'; | |||
document.body.appendChild(iframe); | |||
var doc = iframe.contentDocument || iframe.contentWindow.document; | |||
doc.open(); | |||
doc.write('<!doctype html><html><head><meta charset="utf-8"><title>Print</title></head><body></body></html>'); | |||
doc.close(); | |||
// 1) Inject PRINT CSS with onload so we can await it | |||
var printCssUrl = '/index.php?title=MediaWiki:Print.css&action=raw&ctype=text/css'; | |||
var printCssFresh = printCssUrl + (printCssUrl.indexOf('?') > -1 ? '&' : '?') + '_=' + Date.now(); | |||
var linkCss = doc.createElement('link'); | |||
linkCss.rel = 'stylesheet'; | |||
linkCss.href = printCssFresh; | |||
}). | var cssLoaded = new Promise(function(resolve, reject){ | ||
linkCss.onload = function(){ resolve(); }; | |||
linkCss.onerror = function(){ console.warn('[print] CSS failed to load'); resolve(); }; // don’t block print entirely | |||
}); | |||
// 2) Preload the font INSIDE the iframe too (best chance Chrome has it in time) | |||
var linkFont = doc.createElement('link'); | |||
linkFont.rel = 'preload'; | |||
linkFont.as = 'font'; | |||
linkFont.type = 'font/woff2'; | |||
linkFont.href = '/fonts/HALColant-TextRegular.woff2?v=20250820'; | |||
linkFont.crossOrigin = 'anonymous'; | |||
doc.head.appendChild(linkFont); | |||
doc.head.appendChild(linkCss); | |||
// 3) Inject the printable HTML | |||
doc.body.innerHTML = $print.prop('outerHTML'); | |||
// 4) Wait for images (decode) + fonts + css | |||
function waitImages() { | |||
var imgs = Array.from(doc.images || []); | |||
if (!imgs.length) return Promise.resolve(); | |||
return Promise.all(imgs.map(function(img){ | |||
// decode() is best; fallback to load/error | |||
if (img.decode) { | |||
return img.decode().catch(function(){ /* ignore */ }); | |||
} | |||
return new Promise(function(res){ if (img.complete) return res(); img.onload = img.onerror = function(){ res(); }; }); | |||
})); | |||
} | |||
function waitFonts(timeoutMs) { | |||
// If fonts API missing (older engine), resolve immediately | |||
if (!doc.fonts || !doc.fonts.ready) return Promise.resolve(); | |||
var ready = doc.fonts.ready; | |||
if (typeof Promise.race !== 'function') return ready; | |||
// timeout guard so we never hang | |||
var t = new Promise(function(res){ setTimeout(res, timeoutMs || 1200); }); | |||
return Promise.race([ready, t]); | |||
} | |||
function nextFrame() { | |||
return new Promise(function(res){ (iframe.contentWindow.requestAnimationFrame || setTimeout)(res, 0); }); | |||
} | |||
Promise.all([ | |||
cssLoaded, | |||
waitImages(), | |||
waitFonts(1200), | |||
nextFrame(), // settle layout | |||
]).then(function(){ | |||
try { iframe.contentWindow.focus(); iframe.contentWindow.print(); } | |||
finally { setTimeout(function () { document.body.removeChild(iframe); }, 500); } | |||
}); | }); | ||
}).fail(function (xhr) { | |||
console.warn('[print] fetch failed:', xhr && xhr.status, xhr && xhr.statusText); | |||
window.print(); | |||
}); | }); | ||
}); | |||