keep original assignment font

This commit is contained in:
Guy Sandler 2026-09-21 15:45:07 -07:00
parent bf1cccef75
commit a6fbe396ec
4 changed files with 64 additions and 2 deletions

View File

@ -1070,6 +1070,10 @@
<h3 class="header-small" id="fontsDropdown" style="cursor:pointer; display:flex; align-items:center; gap:8px;"> <h3 class="header-small" id="fontsDropdown" style="cursor:pointer; display:flex; align-items:center; gap:8px;">
Dashboard Font Dashboard Font
<img id="fontsDropdownArrow" style="transform:rotate(180deg);" src="../icon/dropdownArrow.svg" width="16px" height="16px"> <img id="fontsDropdownArrow" style="transform:rotate(180deg);" src="../icon/dropdownArrow.svg" width="16px" height="16px">
<span style="margin-left:auto; display:flex; align-items:center; gap:6px; cursor:pointer;">
<input type="checkbox" id="custom_font_skip_p" name="custom_font_skip_p">
<label for="custom_font_skip_p" class="sub-text" style="cursor:pointer;">Keep original assignment font</label>
</span>
</h3> </h3>
<div id="quick-fonts"></div> <div id="quick-fonts"></div>

View File

@ -87,6 +87,7 @@ chrome.runtime.onInstalled.addListener(function () {
"todo_progress_rings": "rings", "todo_progress_rings": "rings",
"todo_confetti": true, "todo_confetti": true,
"todo_show_scores": false, "todo_show_scores": false,
"custom_font_skip_p": false,
"device_dark": false, "device_dark": false,
"cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 }, "cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 },
// "show_updates": false, // "show_updates": false,

View File

@ -998,6 +998,7 @@ function applyOptionsChanges(changes) {
calculateGPA2(); calculateGPA2();
break; break;
case "custom_font": case "custom_font":
case "custom_font_skip_p":
loadCustomFont(); loadCustomFont();
break; break;
case "remlogo": case "remlogo":
@ -6415,6 +6416,49 @@ function loadDashboardNotes() {
Custom font Custom font
*/ */
// "Keep original assignment font": Canvas sets its font (Lato) on <body>
// via author CSS, and the custom-font rule's `*` selector overrides it. To
// keep <p> original we (a) carve p + its descendants out of the custom rule
// and (b) pin them back to the font body had BEFORE the custom rule landed —
// plain `inherit` wouldn't work because p's ancestors still carry the custom
// font via `*`. The pre-custom font is captured once from body's computed
// style (before our <style> is first injected), with Canvas's default Lato
// stack as fallback.
let originalPageFontFamily = null;
const CANVAS_DEFAULT_FONT_STACK = '"Lato Extended", Lato, "Helvetica Neue", Helvetica, Arial, sans-serif';
function captureOriginalPageFont() {
if (originalPageFontFamily) return;
// Too late to capture once our rule is live: body's computed style would
// already be the custom font.
if (document.querySelector("#custom_font")) return;
try {
const family = getComputedStyle(document.body || document.documentElement).fontFamily;
if (family) originalPageFontFamily = family;
} catch (_) { /* keep fallback */ }
}
function originalPageFontOrFallback() {
return originalPageFontFamily || CANVAS_DEFAULT_FONT_STACK;
}
function customFontRules() {
if (options.custom_font_skip_p !== true) {
return `${customFontSelector()} {font-family: ${options.custom_font.family}!important}`;
}
return `${customFontSelector()} {font-family: ${options.custom_font.family}!important}\n`
+ `p, p * {font-family: ${originalPageFontOrFallback()}!important}`;
}
// Selector for the custom font rule. With "Keep original assignment font"
// on, <p> (and everything inside one) is carved out with :not() so the
// paragraph override rule below is the only thing styling them.
function customFontSelector() {
return options.custom_font_skip_p === true
? "*:not(p):not(p *), input, a, button, h1, h2, h3, h4, h5, h6, span"
: "*, input, a, button, h1, h2, h3, h4, h5, h6, p, span";
}
function loadCustomFont() { function loadCustomFont() {
// Quiz safe mode: don't override fonts on quiz pages. // Quiz safe mode: don't override fonts on quiz pages.
if (quizSafeModeActive()) return; if (quizSafeModeActive()) return;
@ -6423,13 +6467,15 @@ function loadCustomFont() {
let load = () => { let load = () => {
if (options.custom_font.link !== "") { if (options.custom_font.link !== "") {
// Capture the original font before the custom rule is injected.
captureOriginalPageFont();
document.head.appendChild(style); document.head.appendChild(style);
link.href = `https://fonts.googleapis.com/css2?family=${options.custom_font.link}&display=swap`; link.href = `https://fonts.googleapis.com/css2?family=${options.custom_font.link}&display=swap`;
link.rel = "stylesheet"; link.rel = "stylesheet";
document.head.appendChild(link); document.head.appendChild(link);
} }
style.textContent = options.custom_font.link === "" ? "" : `*, input, a, button, h1, h2, h3, h4, h5, h6, p, span {font-family: ${options.custom_font.family}!important}`; style.textContent = options.custom_font.link === "" ? "" : customFontRules();
} }
let createEls = () => { let createEls = () => {

View File

@ -18,6 +18,7 @@ const syncedSubOptions = [
"auto_dark", "auto_dark",
"auto_dark_start", "auto_dark_start",
"auto_dark_end", "auto_dark_end",
"custom_font_skip_p",
"num_assignments", "num_assignments",
"assignment_date_format", "assignment_date_format",
"todo_hr24", "todo_hr24",
@ -136,6 +137,7 @@ const defaultOptions = {
// "hide_completed": false, // "hide_completed": false,
"num_todo_items": 10, "num_todo_items": 10,
"custom_font": { "link": "", "family": "" }, "custom_font": { "link": "", "family": "" },
"custom_font_skip_p": false,
"hover_preview": true, "hover_preview": true,
"full_width": null, "full_width": null,
"remlogo": null, "remlogo": null,
@ -962,6 +964,7 @@ function setup() {
"gpa_calc_prepend", "gpa_calc_prepend",
"auto_dark", "auto_dark",
"assignment_date_format", "assignment_date_format",
"custom_font_skip_p",
"todo_hr24", "todo_hr24",
"todo_separate_scrollbar", "todo_separate_scrollbar",
"todo_alternate_colors", "todo_alternate_colors",
@ -1428,7 +1431,7 @@ function setup() {
break; break;
} }
case "export-font": case "export-font":
final = { ...final, ...(await getExport(storage, ["custom_font"])) }; final = { ...final, ...(await getExport(storage, ["custom_font", "custom_font_skip_p"])) };
break; break;
case "export-background": case "export-background":
final = { ...final, ...(await getExport(storage, exportBackground)) }; final = { ...final, ...(await getExport(storage, exportBackground)) };
@ -1702,6 +1705,13 @@ function setup() {
chrome.storage.local.set({ [fontsDropdownStateKey]: nextOpen }); chrome.storage.local.set({ [fontsDropdownStateKey]: nextOpen });
}); });
// The "Keep original assignment font" toggle sits inline in the dropdown
// header; clicking it must not also collapse/expand the font dropdown.
const skipPToggle = document.getElementById("custom_font_skip_p");
if (skipPToggle) {
skipPToggle.closest("span").addEventListener("click", (e) => e.stopPropagation());
}
} }
function applyGPAPreset(bounds) { function applyGPAPreset(bounds) {
@ -1874,6 +1884,7 @@ function saveCurrentTheme() {
"custom_cards": current["custom_cards"], "custom_cards": current["custom_cards"],
"card_colors": current["card_colors"] === null ? [current["dark_preset"]["links"]] : current["card_colors"], "card_colors": current["card_colors"] === null ? [current["dark_preset"]["links"]] : current["card_colors"],
"custom_font": current["custom_font"], "custom_font": current["custom_font"],
"custom_font_skip_p": current["custom_font_skip_p"],
"better_todo": current["better_todo"], "better_todo": current["better_todo"],
"todo_hide_feedback": current["todo_hide_feedback"], "todo_hide_feedback": current["todo_hide_feedback"],
"todo_hide_read": current["todo_hide_read"] !== false, "todo_hide_read": current["todo_hide_read"] !== false,