@diplodoc/transform
Version:
A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML
214 lines (211 loc) • 8.69 kB
JavaScript
"use strict";
(() => {
// src/js/utils.ts
var getEventTarget = (event) => {
const path = event.composedPath();
return Array.isArray(path) && path.length > 0 ? path[0] : event.target;
};
var isCustom = (event) => {
const target = getEventTarget(event);
return !target || !target.matches;
};
// src/js/term/utils.ts
var Selector = {
TITLE: ".yfm .yfm-term_title",
CONTENT: ".yfm .yfm-term_dfn"
};
var openClass = "open";
var openDefinitionClass = Selector.CONTENT.replace(/\./g, "") + " " + openClass;
var isListenerNeeded = true;
function setDefinitionId(definitionElement, termElement) {
const termId = termElement.getAttribute("id") || Math.random().toString(36).substr(2, 8);
definitionElement == null ? void 0 : definitionElement.setAttribute("term-id", termId);
}
function setDefinitonAriaAttributes(definitionElement, termElement) {
const ariaLive = termElement.getAttribute("aria-live") || "polite";
definitionElement == null ? void 0 : definitionElement.setAttribute("aria-live", ariaLive);
definitionElement == null ? void 0 : definitionElement.setAttribute("aria-modal", "true");
}
function setDefinitionPosition(definitionElement, termElement) {
const {
x: termX,
y: termY,
right: termRight,
left: termLeft,
width: termWidth,
height: termHeight
} = termElement.getBoundingClientRect();
const termParent = termParentElement(termElement);
if (!termParent) {
return;
}
const { right: termParentRight, left: termParentLeft } = termParent.getBoundingClientRect();
if ((termParentRight < termLeft || termParentLeft > termRight) && !isListenerNeeded) {
closeDefinition(definitionElement);
return;
}
if (isListenerNeeded && termParent) {
termParent.addEventListener("scroll", termOnResize);
isListenerNeeded = false;
}
const relativeX = Number(definitionElement.getAttribute("relativeX"));
const relativeY = Number(definitionElement.getAttribute("relativeY"));
if (relativeX === termX && relativeY === termY) {
return;
}
definitionElement.setAttribute("relativeX", String(termX));
definitionElement.setAttribute("relativeY", String(termY));
const offsetTop = termHeight + 5;
const definitionParent = definitionElement.parentElement;
if (!definitionParent) {
return;
}
const { width: definitionWidth } = definitionElement.getBoundingClientRect();
const { left: definitionParentLeft } = definitionParent.getBoundingClientRect();
const definitionLeftCoordinate = Number(getCoords(termElement).left);
const definitionRightCoordinate = definitionWidth + definitionLeftCoordinate;
const definitionOutOfScreenOnLeft = definitionLeftCoordinate - definitionWidth < 0;
const definitionOutOfScreenOnRight = definitionRightCoordinate > document.body.clientWidth;
const isAlignSwapped = definitionOutOfScreenOnRight || document.dir === "rtl";
const fitDefinitionDocument = isAlignSwapped && !definitionOutOfScreenOnLeft ? definitionWidth - termWidth : 0;
const customHeaderTop = getCoords(definitionParent).top - definitionParent.offsetTop;
const offsetRight = 5;
const shiftLeft = definitionOutOfScreenOnRight ? definitionRightCoordinate - document.body.clientWidth + offsetRight : 0;
const offsetLeft = getCoords(termElement).left - definitionParentLeft + definitionParent.offsetLeft - fitDefinitionDocument;
const isShiftLeftNeeded = offsetLeft + definitionWidth >= document.body.clientWidth;
definitionElement.style.top = Number(getCoords(termElement).top + offsetTop - customHeaderTop) + "px";
definitionElement.style.left = Number(offsetLeft - (isShiftLeftNeeded ? shiftLeft : 0)) + "px";
}
function termOnResize() {
const openedDefinition = document.getElementsByClassName(openDefinitionClass)[0];
if (!openedDefinition) {
return;
}
const termId = openedDefinition.getAttribute("term-id") || "";
const termElement = document.getElementById(termId);
if (!termElement) {
return;
}
setDefinitionPosition(openedDefinition, termElement);
}
function termParentElement(term) {
if (!term) {
return null;
}
const closestScrollableParent = term.closest("table") || term.closest("code");
return closestScrollableParent || term.parentElement;
}
function openDefinition(target) {
const openedDefinition = document.getElementsByClassName(openDefinitionClass)[0];
const termId = target.getAttribute("id");
const termKey = target.getAttribute("term-key");
const definitionElement = document.getElementById(termKey + "_element");
const isSameTerm = openedDefinition && termId === openedDefinition.getAttribute("term-id");
if (isSameTerm) {
closeDefinition(openedDefinition);
return;
}
const isTargetDefinitionContent = target.closest(
[Selector.CONTENT.replace(" ", ""), openClass].join(".")
);
if (openedDefinition && !isTargetDefinitionContent) {
closeDefinition(openedDefinition);
}
if (!target.matches(Selector.TITLE) || !definitionElement) {
return;
}
setDefinitionId(definitionElement, target);
setDefinitonAriaAttributes(definitionElement, target);
setDefinitionPosition(definitionElement, target);
definitionElement.classList.toggle(openClass);
trapFocus(definitionElement);
}
function closeDefinition(definition) {
definition.classList.remove(openClass);
const term = getTermByDefinition(definition);
const termParent = termParentElement(term);
if (!termParent) {
return;
}
termParent.removeEventListener("scroll", termOnResize);
isListenerNeeded = true;
}
function getCoords(elem) {
const box = elem.getBoundingClientRect();
const body = document.body;
const docEl = document.documentElement;
const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
const clientTop = docEl.clientTop || body.clientTop || 0;
const clientLeft = docEl.clientLeft || body.clientLeft || 0;
const top = box.top + scrollTop - clientTop;
const left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) };
}
function trapFocus(element) {
const focusableElements = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstFocusableElement = focusableElements[0];
const lastFocusableElement = focusableElements[focusableElements.length - 1];
if (firstFocusableElement) {
firstFocusableElement.focus();
}
element.addEventListener("keydown", function(e) {
const isTabPressed = e.key === "Tab" || e.keyCode === 9;
if (!isTabPressed) {
return;
}
if (e.shiftKey) {
if (document.activeElement === firstFocusableElement) {
lastFocusableElement.focus();
e.preventDefault();
}
} else if (document.activeElement === lastFocusableElement) {
firstFocusableElement.focus();
e.preventDefault();
}
});
}
function getTermByDefinition(definition) {
const termId = definition.getAttribute("term-id");
return termId ? document.getElementById(termId) : null;
}
// src/js/term/index.ts
if (typeof document !== "undefined") {
document.addEventListener("click", (event) => {
if (getEventTarget(event) || !isCustom(event)) {
openDefinition(getEventTarget(event));
}
});
document.addEventListener("keydown", (event) => {
var _a;
const openedDefinition = document.getElementsByClassName(
openDefinitionClass
)[0];
if (event.key === "Enter" && document.activeElement) {
openDefinition(document.activeElement);
}
if (event.key === "Escape" && openedDefinition) {
closeDefinition(openedDefinition);
(_a = getTermByDefinition(openedDefinition)) == null ? void 0 : _a.focus();
}
});
window.addEventListener("resize", () => {
const openedDefinition = document.getElementsByClassName(
openDefinitionClass
)[0];
if (!openedDefinition) {
return;
}
const termId = openedDefinition.getAttribute("term-id") || "";
const termElement = document.getElementById(termId);
if (!termElement) {
openedDefinition.classList.toggle(openClass);
return;
}
setDefinitionPosition(openedDefinition, termElement);
});
}
})();
//# sourceMappingURL=_yfm-only.js.map