Original implementation was only aware of multimarkdown style footnote markup.
This commit includes support for DaringFireball style footnotes
This commit is contained in:
parent
b721f74e17
commit
f25c0e0b57
@ -225,10 +225,19 @@ img[src*="share-buttons"] {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newsfoot-footnote-popover .reversefootnote {
|
.newsfoot-footnote-popover .reversefootnote,
|
||||||
|
.newsfoot-footnote-popover .footnoteBackLink,
|
||||||
|
.newsfoot-footnote-popover .footnote-return {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
a.footnote {
|
|
||||||
|
sup[id^='fn'] {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.footnote,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.05em 0.75em;
|
padding: 0.05em 0.75em;
|
||||||
@ -257,13 +266,17 @@ a.footnote {
|
|||||||
}
|
}
|
||||||
body a.footnote,
|
body a.footnote,
|
||||||
body a.footnote:visited,
|
body a.footnote:visited,
|
||||||
.newsfoot-footnote-popover + a.footnote:hover {
|
.newsfoot-footnote-popover + a.footnote:hover,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
color: white;
|
color: white;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
a.footnote:hover,
|
a.footnote:hover,
|
||||||
.newsfoot-footnote-popover + a.footnote {
|
.newsfoot-footnote-popover + a.footnote,
|
||||||
|
sup > a[href^='#fn']:hover,
|
||||||
|
sup > div > a[href^='#fn']:hover {
|
||||||
background: #666;
|
background: #666;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
@ -284,13 +297,17 @@ a.footnote:hover,
|
|||||||
}
|
}
|
||||||
body a.footnote,
|
body a.footnote,
|
||||||
body a.footnote:visited,
|
body a.footnote:visited,
|
||||||
.newsfoot-footnote-popover + a.footnote:hover {
|
.newsfoot-footnote-popover + a.footnote:hover,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
color: white;
|
color: white;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
a.footnote:hover,
|
a.footnote:hover,
|
||||||
.newsfoot-footnote-popover + a.footnote {
|
.newsfoot-footnote-popover + a.footnote,
|
||||||
|
sup > a[href^='#fn']:hover,
|
||||||
|
sup > div > a[href^='#fn']:hover {
|
||||||
background: #666;
|
background: #666;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
// @ts-check
|
||||||
(function () {
|
(function () {
|
||||||
// @ts-check
|
|
||||||
/** @param {Node | null} el */
|
/** @param {Node | null} el */
|
||||||
const remove = (el) => { if (el) el.parentElement.removeChild(el) };
|
const remove = (el) => { if (el) el.parentElement.removeChild(el) };
|
||||||
|
|
||||||
@ -33,7 +33,7 @@
|
|||||||
const POPOVER_ARROW_CLS = `${clsPrefix}popover-arrow`;
|
const POPOVER_ARROW_CLS = `${clsPrefix}popover-arrow`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Node} content
|
* @param {string} content
|
||||||
* @returns {HTMLElement}
|
* @returns {HTMLElement}
|
||||||
*/
|
*/
|
||||||
function footnoteMarkup(content) {
|
function footnoteMarkup(content) {
|
||||||
@ -42,13 +42,13 @@
|
|||||||
const inner = newEl("div", POPOVER_INNER_CLS);
|
const inner = newEl("div", POPOVER_INNER_CLS);
|
||||||
popover.appendChild(inner);
|
popover.appendChild(inner);
|
||||||
popover.appendChild(arrow);
|
popover.appendChild(arrow);
|
||||||
inner.appendChild(content);
|
inner.innerHTML = content;
|
||||||
return popover;
|
return popover;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Footnote {
|
class Footnote {
|
||||||
/**
|
/**
|
||||||
* @param {Node} content
|
* @param {string} content
|
||||||
* @param {Element} fnref
|
* @param {Element} fnref
|
||||||
*/
|
*/
|
||||||
constructor(content, fnref) {
|
constructor(content, fnref) {
|
||||||
@ -56,6 +56,8 @@
|
|||||||
this.style = window.getComputedStyle(this.popover);
|
this.style = window.getComputedStyle(this.popover);
|
||||||
this.fnref = fnref;
|
this.fnref = fnref;
|
||||||
this.fnref.closest(`.${CONTAINER_CLS}`).insertBefore(this.popover, fnref);
|
this.fnref.closest(`.${CONTAINER_CLS}`).insertBefore(this.popover, fnref);
|
||||||
|
/** @type {HTMLElement} */
|
||||||
|
this.arrow = this.popover.querySelector(`.${POPOVER_ARROW_CLS}`);
|
||||||
this.reposition();
|
this.reposition();
|
||||||
|
|
||||||
/** @type {(ev:MouseEvent) => void} */
|
/** @type {(ev:MouseEvent) => void} */
|
||||||
@ -101,17 +103,10 @@
|
|||||||
offset = (popoverHalfWidth + marginLeft) - center;
|
offset = (popoverHalfWidth + marginLeft) - center;
|
||||||
}
|
}
|
||||||
this.popover.style.transform = `translate(${offset}px)`;
|
this.popover.style.transform = `translate(${offset}px)`;
|
||||||
this.popover.querySelector(`.${POPOVER_ARROW_CLS}`).style.transform = `translate(${-offset}px) rotate(45deg)`;
|
this.arrow.style.transform = `translate(${-offset}px) rotate(45deg)`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {Node} n */
|
|
||||||
function fragFromContents(n) {
|
|
||||||
const frag = document.createDocumentFragment();
|
|
||||||
n.childNodes.forEach((ch) => frag.appendChild(ch));
|
|
||||||
return frag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param {HTMLAnchorElement} a */
|
/** @param {HTMLAnchorElement} a */
|
||||||
function installContainer(a) {
|
function installContainer(a) {
|
||||||
if (!a.parentElement.matches(`.${CONTAINER_CLS}`)) {
|
if (!a.parentElement.matches(`.${CONTAINER_CLS}`)) {
|
||||||
@ -121,22 +116,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function idFromHash(target) {
|
||||||
|
if (!target.hash) return;
|
||||||
|
return target.hash.substring(1);
|
||||||
|
}
|
||||||
|
/** @type {{fnref(target:HTMLAnchorElement): string|undefined}[]} */
|
||||||
|
const footnoteFormats = [
|
||||||
|
{ // Multimarkdown
|
||||||
|
fnref(target) {
|
||||||
|
if (!target.matches(".footnote")) return;
|
||||||
|
return idFromHash(target);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{// Daring Fireball
|
||||||
|
fnref(target) {
|
||||||
|
if (!target.matches("sup > a[href^='#fn'], sup > div > a[href^='#fn']")) return;
|
||||||
|
return idFromHash(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
// Handle clicks on the footnote reference
|
// Handle clicks on the footnote reference
|
||||||
document.addEventListener("click", (ev) => {
|
document.addEventListener("click", (ev) => {
|
||||||
if (!(ev.target && ev.target instanceof HTMLAnchorElement)) return;
|
if (!(ev.target && ev.target instanceof HTMLAnchorElement)) return;
|
||||||
if (!ev.target.matches(".footnote")) return;
|
|
||||||
|
let targetId = undefined;
|
||||||
|
for(const f of footnoteFormats) {
|
||||||
|
targetId = f.fnref(ev.target);
|
||||||
|
if (targetId) break;
|
||||||
|
}
|
||||||
|
if (targetId === undefined) return;
|
||||||
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
const content = document.querySelector(`[id='${ev.target.hash.substring(1)}']`).cloneNode(true);
|
|
||||||
installContainer(ev.target);
|
installContainer(ev.target);
|
||||||
void new Footnote(fragFromContents(content), ev.target);
|
const content = document.querySelector(`[id='${targetId}']`).innerHTML;
|
||||||
|
void new Footnote(content, ev.target);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle clicks on the footnote reverse link
|
// Handle clicks on the footnote reverse link
|
||||||
document.addEventListener("click", (ev) =>
|
document.addEventListener("click", (ev) =>
|
||||||
{
|
{
|
||||||
if (!(ev.target && ev.target instanceof HTMLAnchorElement)) return;
|
if (!(ev.target && ev.target instanceof HTMLAnchorElement)) return;
|
||||||
if (!ev.target.matches(".footnotes .reversefootnote")) return;
|
if (!ev.target.matches(".footnotes .reversefootnote, .footnotes .footnoteBackLink, footnotes .footnote-return")) return;
|
||||||
const hash = ev.target.hash;
|
const hash = ev.target.hash;
|
||||||
if (!hash) return;
|
if (!hash) return;
|
||||||
const fnref = document.getElementById(hash.substring(1));
|
const fnref = document.getElementById(hash.substring(1));
|
||||||
|
@ -201,6 +201,7 @@ img[src*="share-buttons"] {
|
|||||||
border-radius: 0.3em;
|
border-radius: 0.3em;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newsfoot-footnote-popover-arrow {
|
.newsfoot-footnote-popover-arrow {
|
||||||
content: '';
|
content: '';
|
||||||
display: block;
|
display: block;
|
||||||
@ -226,10 +227,19 @@ img[src*="share-buttons"] {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newsfoot-footnote-popover .reversefootnote {
|
.newsfoot-footnote-popover .reversefootnote,
|
||||||
|
.newsfoot-footnote-popover .footnoteBackLink,
|
||||||
|
.newsfoot-footnote-popover .footnote-return {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
a.footnote {
|
|
||||||
|
sup[id^='fn'] {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.footnote,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.05em 0.75em;
|
padding: 0.05em 0.75em;
|
||||||
@ -258,13 +268,17 @@ a.footnote {
|
|||||||
}
|
}
|
||||||
body a.footnote,
|
body a.footnote,
|
||||||
body a.footnote:visited,
|
body a.footnote:visited,
|
||||||
.newsfoot-footnote-popover + a.footnote:hover {
|
.newsfoot-footnote-popover + a.footnote:hover,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
color: white;
|
color: white;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
a.footnote:hover,
|
a.footnote:hover,
|
||||||
.newsfoot-footnote-popover + a.footnote {
|
.newsfoot-footnote-popover + a.footnote,
|
||||||
|
sup > a[href^='#fn']:hover,
|
||||||
|
sup > div > a[href^='#fn']:hover {
|
||||||
background: #666;
|
background: #666;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
@ -285,16 +299,19 @@ a.footnote:hover,
|
|||||||
}
|
}
|
||||||
body a.footnote,
|
body a.footnote,
|
||||||
body a.footnote:visited,
|
body a.footnote:visited,
|
||||||
.newsfoot-footnote-popover + a.footnote:hover {
|
.newsfoot-footnote-popover + a.footnote:hover,
|
||||||
|
sup > a[href^='#fn'],
|
||||||
|
sup > div > a[href^='#fn'] {
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
color: white;
|
color: white;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
a.footnote:hover,
|
a.footnote:hover,
|
||||||
.newsfoot-footnote-popover + a.footnote {
|
.newsfoot-footnote-popover + a.footnote,
|
||||||
|
sup > a[href^='#fn']:hover,
|
||||||
|
sup > div > a[href^='#fn']:hover {
|
||||||
background: #666;
|
background: #666;
|
||||||
transition: background-color 200ms ease-out;
|
transition: background-color 200ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user