196 lines
5.7 KiB
JavaScript
196 lines
5.7 KiB
JavaScript
(() => {
|
|
"use strict";
|
|
|
|
const ROOT_CLASS = "lildra-active";
|
|
const STYLE_ID = "lildra-style";
|
|
const TITLE_BAR_ID = "lildra-title-bar";
|
|
const TITLE_ID = "lildra-title";
|
|
const VERSION_LABEL_ID = "lildra-version-label";
|
|
const STATE_KEY = "__lildraState";
|
|
|
|
const existingState = window[STATE_KEY];
|
|
if (existingState) {
|
|
existingState.remove();
|
|
return;
|
|
}
|
|
|
|
function isSupportedRoute() {
|
|
return location.protocol === "https:" &&
|
|
/^\/courses\/[^/]+\/(?:pages|wiki)\/[^/]+\/?$/.test(location.pathname);
|
|
}
|
|
|
|
function isCanvasContentPage() {
|
|
return isSupportedRoute() && Boolean(
|
|
document.querySelector("#application #wrapper") &&
|
|
document.querySelector("#wiki_page_show")
|
|
);
|
|
}
|
|
|
|
if (!isCanvasContentPage()) return;
|
|
|
|
function getPageTitle() {
|
|
const selectors = [
|
|
"#breadcrumbs [aria-current='page'] .ellipsible",
|
|
"#breadcrumbs [aria-current='page']",
|
|
"#wiki_page_show .page-title",
|
|
"#content h1.page-title",
|
|
"#mobile-header .mobile-header-title div:last-child"
|
|
];
|
|
|
|
for (const selector of selectors) {
|
|
const title = document.querySelector(selector)?.textContent?.trim();
|
|
if (title) return title;
|
|
}
|
|
|
|
const browserTitle = document.title.trim();
|
|
const separator = browserTitle.lastIndexOf(":");
|
|
return separator > 0 ? browserTitle.slice(0, separator).trim() : browserTitle;
|
|
}
|
|
|
|
const style = document.createElement("style");
|
|
style.id = STYLE_ID;
|
|
style.textContent = `
|
|
html.${ROOT_CLASS} #header,
|
|
html.${ROOT_CLASS} #mobile-header,
|
|
html.${ROOT_CLASS} #mobileContextNavContainer,
|
|
html.${ROOT_CLASS} .ic-app-nav-toggle-and-crumbs,
|
|
html.${ROOT_CLASS} #left-side {
|
|
display: none !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #wrapper,
|
|
html.${ROOT_CLASS} body.primary-nav-expanded #wrapper,
|
|
html.${ROOT_CLASS} body.course-menu-expanded #wrapper,
|
|
html.${ROOT_CLASS} body.with-left-side #wrapper {
|
|
margin-left: 0 !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #wrapper {
|
|
box-sizing: border-box !important;
|
|
padding-top: 42px !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #main {
|
|
box-sizing: border-box !important;
|
|
width: calc(100% - 32px) !important;
|
|
max-width: 1100px !important;
|
|
margin-right: auto !important;
|
|
margin-left: auto !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #${TITLE_BAR_ID} {
|
|
position: fixed !important;
|
|
top: 0 !important;
|
|
right: 0 !important;
|
|
left: 0 !important;
|
|
z-index: 2147483646 !important;
|
|
box-sizing: border-box !important;
|
|
display: flex !important;
|
|
align-items: center !important;
|
|
justify-content: center !important;
|
|
height: 42px !important;
|
|
padding: 0 18px !important;
|
|
background: #fff !important;
|
|
border-bottom: 1px solid rgb(0 0 0 / 14%) !important;
|
|
box-shadow: 0 1px 3px rgb(0 0 0 / 7%) !important;
|
|
color: #1d2733 !important;
|
|
font: 700 16px/1 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #${TITLE_ID} {
|
|
min-width: 0 !important;
|
|
overflow: hidden !important;
|
|
text-align: center !important;
|
|
text-overflow: ellipsis !important;
|
|
white-space: nowrap !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #${VERSION_LABEL_ID} {
|
|
position: fixed !important;
|
|
right: 10px !important;
|
|
bottom: 8px !important;
|
|
z-index: 2147483646 !important;
|
|
padding: 3px 6px !important;
|
|
border-radius: 4px !important;
|
|
background: rgb(255 255 255 / 88%) !important;
|
|
box-shadow: 0 1px 3px rgb(0 0 0 / 10%) !important;
|
|
color: #5f259f !important;
|
|
font: 700 11px/1 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
|
pointer-events: none !important;
|
|
}
|
|
|
|
@media (max-width: 700px) {
|
|
html.${ROOT_CLASS} #wrapper {
|
|
padding-top: 38px !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #main {
|
|
width: calc(100% - 20px) !important;
|
|
}
|
|
|
|
html.${ROOT_CLASS} #${TITLE_BAR_ID} {
|
|
height: 38px !important;
|
|
padding: 0 10px !important;
|
|
font-size: 14px !important;
|
|
}
|
|
}
|
|
`;
|
|
|
|
const titleBar = document.createElement("div");
|
|
titleBar.id = TITLE_BAR_ID;
|
|
titleBar.setAttribute("aria-hidden", "true");
|
|
|
|
const title = document.createElement("div");
|
|
title.id = TITLE_ID;
|
|
title.textContent = getPageTitle();
|
|
titleBar.append(title);
|
|
|
|
const versionLabel = document.createElement("div");
|
|
versionLabel.id = VERSION_LABEL_ID;
|
|
versionLabel.setAttribute("aria-hidden", "true");
|
|
versionLabel.textContent = `Lildra v${chrome.runtime.getManifest().version}`;
|
|
|
|
let updatePending = false;
|
|
let updateFrame = 0;
|
|
const observer = new MutationObserver(() => {
|
|
if (updatePending) return;
|
|
updatePending = true;
|
|
|
|
updateFrame = requestAnimationFrame(() => {
|
|
updateFrame = 0;
|
|
updatePending = false;
|
|
if (!isSupportedRoute()) {
|
|
remove();
|
|
return;
|
|
}
|
|
|
|
const nextTitle = getPageTitle();
|
|
if (nextTitle && title.textContent !== nextTitle) title.textContent = nextTitle;
|
|
});
|
|
});
|
|
|
|
function remove() {
|
|
observer.disconnect();
|
|
if (updateFrame) cancelAnimationFrame(updateFrame);
|
|
document.documentElement.classList.remove(ROOT_CLASS);
|
|
style.remove();
|
|
titleBar.remove();
|
|
versionLabel.remove();
|
|
delete window[STATE_KEY];
|
|
}
|
|
|
|
window[STATE_KEY] = { remove };
|
|
document.documentElement.append(style);
|
|
document.body.append(titleBar, versionLabel);
|
|
document.documentElement.classList.add(ROOT_CLASS);
|
|
observer.observe(document.querySelector("#application"), {
|
|
childList: true,
|
|
subtree: true,
|
|
characterData: true
|
|
});
|
|
observer.observe(document.querySelector("head > title"), {
|
|
childList: true,
|
|
characterData: true
|
|
});
|
|
})();
|