discourse/plugins/footnote/assets/javascripts/initializers/inline-footnotes.js
dependabot[bot] e7d3c344d1
Build(deps-dev): Bump the lint group across 1 directory with 4 updates (#33881)
Bumps the lint group with 4 updates in the / directory:
[@discourse/lint-configs](https://github.com/discourse/lint-configs),
[ember-template-lint](https://github.com/ember-template-lint/ember-template-lint),
[eslint](https://github.com/eslint/eslint) and
[stylelint](https://github.com/stylelint/stylelint).


Updates `@discourse/lint-configs` from 2.22.0 to 2.28.0
- [Commits](https://github.com/discourse/lint-configs/commits)

Updates `ember-template-lint` from 7.7.0 to 7.9.1
- [Release
notes](https://github.com/ember-template-lint/ember-template-lint/releases)
-
[Changelog](https://github.com/ember-template-lint/ember-template-lint/blob/master/CHANGELOG.md)
-
[Commits](https://github.com/ember-template-lint/ember-template-lint/commits)

Updates `eslint` from 9.27.0 to 9.32.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.27.0...v9.32.0)

Updates `stylelint` from 16.19.1 to 16.22.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
-
[Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
-
[Commits](https://github.com/stylelint/stylelint/compare/16.19.1...16.22.0)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Discourse CI <ci@ci.invalid>
Co-authored-by: Jarek Radosz <jarek@cvx.dev>
2025-07-28 18:02:41 +02:00

139 lines
3.8 KiB
JavaScript
Vendored

import { createPopper } from "@popperjs/core";
import { iconHTML } from "discourse/lib/icon-library";
import { withPluginApi } from "discourse/lib/plugin-api";
let inlineFootnotePopper;
function applyInlineFootnotes(elem) {
const footnoteRefs = elem.querySelectorAll("sup.footnote-ref");
footnoteRefs.forEach((footnoteRef) => {
const refLink = footnoteRef.querySelector("a");
if (!refLink) {
return;
}
const expandableFootnote = document.createElement("a");
expandableFootnote.classList.add("expand-footnote");
expandableFootnote.innerHTML = iconHTML("ellipsis");
expandableFootnote.href = "";
expandableFootnote.role = "button";
expandableFootnote.dataset.footnoteId = refLink.getAttribute("href");
footnoteRef.after(expandableFootnote);
});
if (footnoteRefs.length) {
elem.classList.add("inline-footnotes");
}
}
function buildTooltip() {
const template = document.createElement("template");
template.innerHTML = `
<div id="footnote-tooltip" role="tooltip">
<div class="footnote-tooltip-content"></div>
<div id="arrow" data-popper-arrow></div>
</div>
`.trim();
return template.content.firstChild;
}
function footnoteEventHandler(event) {
const tooltip = document.getElementById("footnote-tooltip");
const displayedFootnoteId = tooltip?.dataset.footnoteId;
const expandableFootnote = event.target;
const footnoteId = expandableFootnote.dataset.footnoteId;
inlineFootnotePopper?.destroy();
tooltip?.removeAttribute("data-show");
tooltip?.removeAttribute("data-footnote-id");
if (!event.target.classList.contains("expand-footnote")) {
// dismissing the tooltip by clicking outside
return;
}
event.preventDefault();
event.stopPropagation();
if (displayedFootnoteId === footnoteId) {
// dismissing the tooltip by clicking the footnote button
return;
}
// append footnote to tooltip body
const footnoteContent = tooltip.querySelector(".footnote-tooltip-content");
let cooked = expandableFootnote.closest(".cooked");
if (cooked.dataset.refPostId != null) {
// For full screen tables, redirect
cooked = document.querySelector(
`article[data-post-id="${cooked.dataset.refPostId}"] .cooked`
);
}
const newContent = cooked.querySelector(footnoteId);
footnoteContent.innerHTML = newContent.innerHTML;
// display tooltip
tooltip.dataset.show = "";
tooltip.dataset.footnoteId = footnoteId;
// setup popper
inlineFootnotePopper?.destroy();
inlineFootnotePopper = createPopper(expandableFootnote, tooltip, {
modifiers: [
{
name: "arrow",
options: { element: tooltip.querySelector("#arrow") },
},
{
name: "preventOverflow",
options: {
altAxis: true,
padding: 5,
},
},
{
name: "offset",
options: {
offset: [0, 12],
},
},
],
});
}
export default {
name: "inline-footnotes",
initialize(container) {
if (!container.lookup("service:site-settings").display_footnotes_inline) {
return;
}
document.body.append(buildTooltip());
window.addEventListener("click", footnoteEventHandler, true);
withPluginApi((api) => {
api.decorateCookedElement((elem) => applyInlineFootnotes(elem), {
onlyStream: true,
id: "inline-footnotes",
});
api.onPageChange(() => {
inlineFootnotePopper?.destroy();
const tooltip = document.getElementById("footnote-tooltip");
tooltip?.removeAttribute("data-show");
tooltip?.removeAttribute("data-footnote-id");
});
});
},
teardown() {
inlineFootnotePopper?.destroy();
window.removeEventListener("click", footnoteEventHandler);
document.getElementById("footnote-tooltip")?.remove();
},
};