mirror of
https://github.com/element-hq/synapse
synced 2024-08-19 04:30:53 +00:00
156 lines
4.4 KiB
JavaScript
156 lines
4.4 KiB
JavaScript
/*
|
|
* doctools.js
|
|
* ~~~~~~~~~~~
|
|
*
|
|
* Base JavaScript utilities for all Sphinx HTML documentation.
|
|
*
|
|
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
|
|
* :license: BSD, see LICENSE for details.
|
|
*
|
|
*/
|
|
"use strict";
|
|
|
|
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
|
|
"TEXTAREA",
|
|
"INPUT",
|
|
"SELECT",
|
|
"BUTTON",
|
|
]);
|
|
|
|
const _ready = (callback) => {
|
|
if (document.readyState !== "loading") {
|
|
callback();
|
|
} else {
|
|
document.addEventListener("DOMContentLoaded", callback);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Small JavaScript module for the documentation.
|
|
*/
|
|
const Documentation = {
|
|
init: () => {
|
|
Documentation.initDomainIndexTable();
|
|
Documentation.initOnKeyListeners();
|
|
},
|
|
|
|
/**
|
|
* i18n support
|
|
*/
|
|
TRANSLATIONS: {},
|
|
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
|
|
LOCALE: "unknown",
|
|
|
|
// gettext and ngettext don't access this so that the functions
|
|
// can safely bound to a different name (_ = Documentation.gettext)
|
|
gettext: (string) => {
|
|
const translated = Documentation.TRANSLATIONS[string];
|
|
switch (typeof translated) {
|
|
case "undefined":
|
|
return string; // no translation
|
|
case "string":
|
|
return translated; // translation exists
|
|
default:
|
|
return translated[0]; // (singular, plural) translation tuple exists
|
|
}
|
|
},
|
|
|
|
ngettext: (singular, plural, n) => {
|
|
const translated = Documentation.TRANSLATIONS[singular];
|
|
if (typeof translated !== "undefined")
|
|
return translated[Documentation.PLURAL_EXPR(n)];
|
|
return n === 1 ? singular : plural;
|
|
},
|
|
|
|
addTranslations: (catalog) => {
|
|
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
|
|
Documentation.PLURAL_EXPR = new Function(
|
|
"n",
|
|
`return (${catalog.plural_expr})`
|
|
);
|
|
Documentation.LOCALE = catalog.locale;
|
|
},
|
|
|
|
/**
|
|
* helper function to focus on search bar
|
|
*/
|
|
focusSearchBar: () => {
|
|
document.querySelectorAll("input[name=q]")[0]?.focus();
|
|
},
|
|
|
|
/**
|
|
* Initialise the domain index toggle buttons
|
|
*/
|
|
initDomainIndexTable: () => {
|
|
const toggler = (el) => {
|
|
const idNumber = el.id.substr(7);
|
|
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
|
|
if (el.src.substr(-9) === "minus.png") {
|
|
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
|
|
toggledRows.forEach((el) => (el.style.display = "none"));
|
|
} else {
|
|
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
|
|
toggledRows.forEach((el) => (el.style.display = ""));
|
|
}
|
|
};
|
|
|
|
const togglerElements = document.querySelectorAll("img.toggler");
|
|
togglerElements.forEach((el) =>
|
|
el.addEventListener("click", (event) => toggler(event.currentTarget))
|
|
);
|
|
togglerElements.forEach((el) => (el.style.display = ""));
|
|
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
|
|
},
|
|
|
|
initOnKeyListeners: () => {
|
|
// only install a listener if it is really needed
|
|
if (
|
|
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
|
|
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
|
)
|
|
return;
|
|
|
|
document.addEventListener("keydown", (event) => {
|
|
// bail for input elements
|
|
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
|
|
// bail with special keys
|
|
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
|
|
|
if (!event.shiftKey) {
|
|
switch (event.key) {
|
|
case "ArrowLeft":
|
|
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
|
|
|
const prevLink = document.querySelector('link[rel="prev"]');
|
|
if (prevLink && prevLink.href) {
|
|
window.location.href = prevLink.href;
|
|
event.preventDefault();
|
|
}
|
|
break;
|
|
case "ArrowRight":
|
|
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
|
|
|
const nextLink = document.querySelector('link[rel="next"]');
|
|
if (nextLink && nextLink.href) {
|
|
window.location.href = nextLink.href;
|
|
event.preventDefault();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// some keyboard layouts may need Shift to get /
|
|
switch (event.key) {
|
|
case "/":
|
|
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
|
|
Documentation.focusSearchBar();
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
},
|
|
};
|
|
|
|
// quick alias for translations
|
|
const _ = Documentation.gettext;
|
|
|
|
_ready(Documentation.init);
|