ISMIS Helper: cross-browser build, CI, PDF fixes, Chrome download fix
build-extension / build (push) Successful in 37s
build-extension / build (push) Successful in 37s
Squash merge of feat/ismis-helper into prod.
This commit was merged in pull request #1.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
// Cross-browser API namespace. Firefox provides Promise-based `browser.*`;
|
||||
// Chrome MV3 exposes `browser.*` too, but some builds only populate the
|
||||
// `chrome.*` global. Alias to whichever is present.
|
||||
if (typeof browser === 'undefined' || browser == null) {
|
||||
var browser = (typeof chrome !== 'undefined' ? chrome : {});
|
||||
}
|
||||
|
||||
function errMsg(err) {
|
||||
return String((err && err.message) || err);
|
||||
}
|
||||
|
||||
// Build a download URL from PDF bytes. Chrome MV3 runs the background as a
|
||||
// service worker, where URL.createObjectURL is NOT available, so we use a
|
||||
// base64 data URL (works in both Firefox and Chrome). PDFs here are small
|
||||
// (~150KB), well within data-URL length limits.
|
||||
function pdfDataUrl(bytes) {
|
||||
let binary = '';
|
||||
const chunk = 0x8000;
|
||||
for (let i = 0; i < bytes.length; i += chunk) {
|
||||
binary += String.fromCharCode.apply(null, bytes.subarray(i, i + chunk));
|
||||
}
|
||||
return 'data:application/pdf;base64,' + btoa(binary);
|
||||
}
|
||||
|
||||
browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
if (msg && msg.type === 'generate-pdf') {
|
||||
generatePdf(msg.data)
|
||||
.then(() => sendResponse({ ok: true }))
|
||||
.catch((err) => sendResponse({ ok: false, error: errMsg(err) }));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
function formatPeriod(period) {
|
||||
if (!period) return '';
|
||||
return String(period)
|
||||
.replace(/\b1ST\b/g, '1st')
|
||||
.replace(/\b2ND\b/g, '2nd')
|
||||
.replace(/\b3RD\b/g, '3rd')
|
||||
.replace(/\b(\d+)TH\b/g, '$1th')
|
||||
.toLowerCase()
|
||||
.replace(/^./, (c) => c.toUpperCase());
|
||||
}
|
||||
|
||||
async function generatePdf(data) {
|
||||
const bytes = await ISMIStools.buildStudyLoadPdf(data);
|
||||
// Chrome MV3 background is a service worker (no URL.createObjectURL), so we
|
||||
// use a base64 data URL that works in both browsers.
|
||||
const url = pdfDataUrl(bytes);
|
||||
const header = data.header || {};
|
||||
const year = parseInt(data.year, 10);
|
||||
const period = formatPeriod(data.period || header.semester || '');
|
||||
const compactProgram = ISMIStools.compactProgram(header.program || '');
|
||||
const schoolYear = Number.isFinite(year) ? `${year}-${year + 1}` : '';
|
||||
const parts = [
|
||||
header.studentId || (header.fullName ? header.fullName.replace(/\s+/g, ' ') : ''),
|
||||
compactProgram,
|
||||
schoolYear ? 'S.Y. ' + schoolYear : '',
|
||||
period,
|
||||
'Study Load'
|
||||
].filter(Boolean);
|
||||
const filename = parts.join(' - ') + '.pdf';
|
||||
const fallback = 'Study Load - ' + (header.fullName || 'Student') + '.pdf';
|
||||
const safeFilename = filename || fallback;
|
||||
|
||||
try {
|
||||
const id = await browser.downloads.download({ url, filename: safeFilename, saveAs: true });
|
||||
const onChanged = (delta) => {
|
||||
if (delta.id === id && delta.state && (delta.state.current === 'complete' || delta.state.current === 'interrupted')) {
|
||||
browser.downloads.onChanged.removeListener(onChanged);
|
||||
}
|
||||
};
|
||||
browser.downloads.onChanged.addListener(onChanged);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user