mirror of
https://github.com/wassname/template.git
synced 2026-08-08 11:28:20 +08:00
Project reorganization, add editorconfig and linter
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { body } from "../helpers/layout";
|
||||
|
||||
const T = Template("d-abstract", `
|
||||
<style>
|
||||
d-abstract {
|
||||
display: block;
|
||||
font-size: 23px;
|
||||
line-height: 1.7em;
|
||||
margin-bottom: 140px;
|
||||
}
|
||||
${body("d-abstract")}
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export class Abstract extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Template } from "../mixins/template";
|
||||
|
||||
const T = Template('d-acknowledgements', `
|
||||
<style>
|
||||
::slotted(h3) {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
color: rgba(0,0,0,0.65);
|
||||
line-height: 1em;
|
||||
}
|
||||
::slotted(*) a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
</style>
|
||||
|
||||
<slot></slot>
|
||||
`);
|
||||
|
||||
export class Acknowledgements extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { page } from "../helpers/layout";
|
||||
|
||||
const T = Template("d-appendix", `
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
line-height: 1.7em;
|
||||
margin-bottom: 0;
|
||||
border-top: 1px solid rgba(0,0,0,0.1);
|
||||
color: rgba(0,0,0,0.5);
|
||||
background: rgb(250, 250, 250);
|
||||
padding-top: 36px;
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
|
||||
${page(".l-body")}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="l-body">
|
||||
<slot></slot>
|
||||
</div>
|
||||
`);
|
||||
|
||||
export class Appendix extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import { Controller } from '../controller';
|
||||
|
||||
const T = Template('d-article', `
|
||||
<style></style>
|
||||
`, false);
|
||||
|
||||
|
||||
|
||||
export class Article extends T(HTMLElement) {
|
||||
|
||||
// constructor() {
|
||||
// super();
|
||||
// }
|
||||
|
||||
connectedCallback() {
|
||||
for (const [functionName, callback] of Object.entries(Controller.listeners)) {
|
||||
if (typeof callback === 'function') {
|
||||
document.addEventListener(functionName, callback);
|
||||
} else {
|
||||
console.error('Controller listeners need to be functions!')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { Mutating } from "../mixins/mutating";
|
||||
import { collectCitations } from './d-cite'
|
||||
import bibtexParse from "bibtex-parse-js";
|
||||
import { bibliography_cite } from "../helpers/citation";
|
||||
|
||||
const T = Template('d-bibliography', `
|
||||
<style>
|
||||
.references {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.title {
|
||||
font-weight: 600;
|
||||
}
|
||||
ol {
|
||||
padding: 0 0 0 18px;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
color: rgba(0,0,0,0.65);
|
||||
line-height: 1em;
|
||||
}
|
||||
a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
</style>
|
||||
|
||||
<h3>References</h3>
|
||||
<ol></ol>
|
||||
`);
|
||||
|
||||
export function parseBibtex(bibtex) {
|
||||
const bibliography = new Map();
|
||||
const parsedEntries = bibtexParse.toJSON(bibtex);
|
||||
for (const entry of parsedEntries) {
|
||||
// normalize tags; note entryTags is an object, not Map
|
||||
for (const tag in entry.entryTags) {
|
||||
let value = entry.entryTags[tag];
|
||||
value = value.replace(/[\t\n ]+/g, " ");
|
||||
value = value.replace(/{\\["^`\.'acu~Hvs]( )?([a-zA-Z])}/g,
|
||||
(full, x, char) => char);
|
||||
value = value.replace(/{\\([a-zA-Z])}/g,
|
||||
(full, char) => char);
|
||||
entry.entryTags[tag] = value;
|
||||
}
|
||||
entry.entryTags.type = entry.entryType;
|
||||
// add to bibliography
|
||||
bibliography.set(entry.citationKey, entry.entryTags);
|
||||
}
|
||||
return bibliography;
|
||||
}
|
||||
|
||||
export class Bibliography extends T(HTMLElement) {
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
// set up mutation observer
|
||||
const options = {childList: true, subtree: true};
|
||||
const observer = new MutationObserver( (mutations) => {
|
||||
observer.disconnect();
|
||||
this.parseIfPossible();
|
||||
observer.observe(this, options);
|
||||
});
|
||||
// ...and listen for changes
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
parseIfPossible() {
|
||||
if (this.firstElementChild && this.firstElementChild.tagName === 'SCRIPT') {
|
||||
const newBibtex = this.firstElementChild.textContent;
|
||||
if (this.bibtex !== newBibtex) {
|
||||
this.bibtex = newBibtex;
|
||||
const bibliography = parseBibtex(this.bibtex);
|
||||
this.notify(bibliography);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connectedCallback() {
|
||||
this.list = this.root.querySelector('ol');
|
||||
// bibliography is initially hidden
|
||||
this.root.host.style.display = 'none';
|
||||
// this.parseIfPossible();
|
||||
// Store.subscribeTo('citations', (citations) => {
|
||||
// // ensure citations list is visible
|
||||
// this.root.host.style.display = 'initial';
|
||||
// this.list.innerHTML = '';
|
||||
// for (const key of citations) {
|
||||
// const bibliography = Store.get('bibliography');
|
||||
// const entry = bibliography.get(key);
|
||||
// // construct and append list item to show citation
|
||||
// const listItem = document.createElement('li');
|
||||
// listItem.id = key;
|
||||
// listItem.innerHTML = bibliography_cite(entry);
|
||||
// this.list.appendChild(listItem);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
notify(bibliography) {
|
||||
const options = { detail: bibliography, bubbles: true };
|
||||
const event = new CustomEvent('onBibliographyChanged', options);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
set entries(newEntries) {
|
||||
this.root.host.style.display = 'initial';
|
||||
this.list.innerHTML = '';
|
||||
|
||||
for (const [key, entry] of newEntries) {
|
||||
const listItem = document.createElement('li');
|
||||
listItem.id = key;
|
||||
listItem.innerHTML = bibliography_cite(entry);
|
||||
this.list.appendChild(listItem);
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
// compute and store bibliography
|
||||
// FrontMatter.bibliography = parseBibtex(this.bibtex);
|
||||
// this.notify();
|
||||
// Store.set('bibliography', bibliography);
|
||||
// compute and store citations
|
||||
// const citations = collectCitations();
|
||||
// Store.set('citations', citations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { page } from "../helpers/layout";
|
||||
|
||||
const T = Template("d-byline", `
|
||||
<style>
|
||||
d-byline {
|
||||
box-sizing: border-box;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
display: block;
|
||||
/* border-top: 1px solid rgba(0, 0, 0, 0.1);*/
|
||||
/* border-bottom: 1px solid rgba(0, 0, 0, 0.1);*/
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
${page(".byline")}
|
||||
d-article.centered {
|
||||
text-align: center;
|
||||
}
|
||||
a,
|
||||
d-article a {
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
text-decoration: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
d-article a:hover {
|
||||
text-decoration: underline;
|
||||
border-bottom: none;
|
||||
}
|
||||
.authors {
|
||||
text-align: left;
|
||||
}
|
||||
.name {
|
||||
font-weight: 600;
|
||||
display: inline;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.affiliation {
|
||||
display: inline;
|
||||
}
|
||||
.date {
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
.year, .month {
|
||||
display: inline;
|
||||
}
|
||||
.citation {
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
.citation div {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
d-byline {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
.authors {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.author {
|
||||
display: inline-block;
|
||||
margin-right: 12px;
|
||||
/*padding-left: 20px;*/
|
||||
/*border-left: 1px solid #ddd;*/
|
||||
}
|
||||
|
||||
.affiliation {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.author:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.date {
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-left: 15px;
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
.year, .month {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.citation {
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.15);
|
||||
padding-left: 15px;
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
.citation div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class='byline'>
|
||||
</div>
|
||||
`, false);
|
||||
|
||||
export function bylineTemplate(frontMatter) {
|
||||
return `
|
||||
<div class="authors">
|
||||
${frontMatter.authors.map( author => `<div class="author">
|
||||
${author.personalURL ?
|
||||
`<a class="name" href="${author.personalURL}">${author.name}</a>`
|
||||
:
|
||||
`<div class="name">${author.name}</div>`
|
||||
}
|
||||
${author.affiliationURL ?
|
||||
`<a class="affiliation" href="${author.affiliationURL}">${author.affiliation}</a>`
|
||||
:
|
||||
`<div class="affiliation">${author.affiliation}</div>`
|
||||
}
|
||||
</div>`).join('\n')}
|
||||
</div>
|
||||
<div class="date">
|
||||
<div class="month">${frontMatter.publishedMonth}. ${frontMatter.publishedDay}</div>
|
||||
<div class="year">${frontMatter.publishedYear}</div>
|
||||
</div>
|
||||
<a class="citation" href="#citation">
|
||||
<div>Citation:</div>
|
||||
<div>${frontMatter.concatenatedAuthors}, ${frontMatter.publishedYear}</div>
|
||||
</a>
|
||||
`;
|
||||
}
|
||||
|
||||
export class Byline extends T(HTMLElement) {
|
||||
|
||||
set frontMatter(frontMatter) {
|
||||
const container = this.querySelector('.byline');
|
||||
container.innerHTML = bylineTemplate(frontMatter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { hover_cite } from "../helpers/citation";
|
||||
import { HoverBox } from "../helpers/hover-box";
|
||||
|
||||
const T = Template('d-cite', `
|
||||
<style>
|
||||
.citation {
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
}
|
||||
.citation-number {
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Roboto", Helvetica, sans-serif;
|
||||
font-size: 75%;
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
display: inline-block;
|
||||
line-height: 1.1em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
figcaption .citation-number {
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
top: -2px;
|
||||
line-height: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="display: none;" id="hover-box" class="dt-hover-box">
|
||||
</div>
|
||||
|
||||
<span id="citation-" class="citation">
|
||||
<slot></slot>
|
||||
<span class="citation-number"></span>
|
||||
</span>
|
||||
`);
|
||||
|
||||
export function collectCitations() {
|
||||
const citations = new Set();
|
||||
const citeTags = document.querySelectorAll('d-cite');
|
||||
for (const tag of citeTags) {
|
||||
const keys = tag.getAttribute('key').split(',');
|
||||
for (const key of keys) {
|
||||
citations.add(key);
|
||||
}
|
||||
}
|
||||
return [...citations];
|
||||
}
|
||||
|
||||
export class Cite extends T(HTMLElement) {
|
||||
|
||||
/* Lifecycle */
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
// Cite.currentId += 1;
|
||||
// this.citeId = Cite.currentId;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// this.notify();
|
||||
|
||||
this.hoverDiv = this.root.querySelector('.dt-hover-box');
|
||||
this.outerSpan = this.root.querySelector('#citation-');
|
||||
this.innerSpan = this.root.querySelector('.citation-number');
|
||||
// this.outerSpan.id = `citation-${this.citeId}`;
|
||||
// this.hoverDiv.id = `dt-cite-hover-box-${this.citeId}`;
|
||||
HoverBox.get_box(this.hoverDiv).bind(this.outerSpan);
|
||||
|
||||
}
|
||||
|
||||
/* Observed Attributes */
|
||||
|
||||
// renderCitationNumbers(citations) {
|
||||
// const numbers = this._keys.map( (key) => {
|
||||
// const index = citations.indexOf(key);
|
||||
// return index == -1 ? '?' : index + 1 + '';
|
||||
// });
|
||||
// const text = "[" + numbers.join(", ") + "]";
|
||||
// this.innerSpan.textContent = text;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/* observe 'key' attribute */
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['key'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
const eventName = oldValue ? 'onCiteKeyChanged' : 'onCiteKeyCreated';
|
||||
const keys = newValue.split(',');
|
||||
const options = { detail: [this, keys], bubbles: true };
|
||||
const event = new CustomEvent(eventName, options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
set key(value) {
|
||||
this.setAttribute('key', value);
|
||||
}
|
||||
|
||||
get key() {
|
||||
return this.getAttribute('key');
|
||||
}
|
||||
|
||||
get keys() {
|
||||
return this.getAttribute('key').split(',');
|
||||
}
|
||||
|
||||
/* Setters & Rendering */
|
||||
|
||||
set numbers(numbers) {
|
||||
const numberStrings = numbers.map( index => {
|
||||
return index == -1 ? '?' : index + 1 + '';
|
||||
});
|
||||
const textContent = "[" + numberStrings.join(", ") + "]";
|
||||
const innerSpan = this.root.querySelector('.citation-number');
|
||||
innerSpan.textContent = textContent;
|
||||
}
|
||||
|
||||
set entries(entries) {
|
||||
const div = this.root.querySelector('#hover-box');
|
||||
div.innerHTML = entries.map(hover_cite).join('<br><br>');
|
||||
}
|
||||
|
||||
// renderContent() {
|
||||
// const bibliography = document.querySelector('d-bibliography');
|
||||
// if (bibliography && bibliography.finishedLoading) {
|
||||
// customElements.whenDefined('d-bibliography').then( () => {
|
||||
// const keys = this.key.split(",");
|
||||
//
|
||||
// // set up hidden hover box
|
||||
// const div = this.root.querySelector('.dt-hover-box');
|
||||
// div.innerHTML = keys.map( (key) => {
|
||||
// return bibliography.getEntry(key);
|
||||
// }).map(hover_cite).join('<br><br>');
|
||||
// div.id ='dt-cite-hover-box-' + this.citeId;
|
||||
//
|
||||
// // set up visible citation marker
|
||||
// const outerSpan = this.root.querySelector('#citation-');
|
||||
// outerSpan.id = `citation-${this.citeId}`;
|
||||
// // outerSpan.setAttribute('data-hover', dataHoverString); // directly tell HoverBox instead?
|
||||
// const innerSpan = this.root.querySelector('.citation-number');
|
||||
// innerSpan.textContent = inline_cite_short(keys, bibliography);
|
||||
//
|
||||
// HoverBox.get_box(div).bind(outerSpan);
|
||||
// });
|
||||
// } else {
|
||||
// console.error(`You used a d-cite tag (${key}) without including a d-bibliography tag in your article. We can't lookup your citation this way.`)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import Prism from "prismjs";
|
||||
import "prismjs/components/prism-python";
|
||||
import "prismjs/components/prism-clike";
|
||||
import css from "prismjs/themes/prism.css";
|
||||
|
||||
import { Template } from "../mixins/template.js"
|
||||
import { Mutating } from "../mixins/mutating.js"
|
||||
|
||||
const T = Template("d-code", `
|
||||
<style>
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 2px;
|
||||
padding: 4px 7px;
|
||||
font-size: 15px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: block;
|
||||
background: white;
|
||||
border-left: 3px solid rgba(0, 0, 0, 0.05);
|
||||
padding: 0 0 0 24px;
|
||||
}
|
||||
|
||||
${css}
|
||||
</style>
|
||||
|
||||
<code id="code-container"></code>
|
||||
|
||||
`);
|
||||
|
||||
export class Code extends Mutating(T(HTMLElement)) {
|
||||
|
||||
renderContent() {
|
||||
|
||||
// check if language can be highlighted
|
||||
this.languageName = this.getAttribute('language');
|
||||
if (!this.languageName) {
|
||||
console.warn(`You need to provide a language attribute to your <d-code> block to let us know how to highlight your code; e.g.:\n <d-code language="python">zeros = np.zeros(shape)</d-code>.`);
|
||||
return;
|
||||
}
|
||||
const language = Prism.languages[this.languageName];
|
||||
if (language == undefined) {
|
||||
console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}".`);
|
||||
return;
|
||||
}
|
||||
|
||||
let content = this.textContent;
|
||||
const codeTag = this.shadowRoot.querySelector("#code-container");
|
||||
|
||||
if (this.hasAttribute("block")) {
|
||||
// normalize the tab indents
|
||||
content = content.replace(/\n/, "");
|
||||
const tabs = content.match(/\s*/);
|
||||
content = content.replace(new RegExp("\n" + tabs, "g"), "\n");
|
||||
content = content.trim();
|
||||
// wrap code block in pre tag if needed
|
||||
if (codeTag.parentNode instanceof ShadowRoot) {
|
||||
const preTag = document.createElement("pre");
|
||||
this.shadowRoot.removeChild(codeTag)
|
||||
preTag.appendChild(codeTag);
|
||||
this.shadowRoot.appendChild(preTag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
codeTag.className = `language-${this.languageName}`;
|
||||
codeTag.innerHTML = Prism.highlight(content, language);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Template } from '../mixins/template';
|
||||
|
||||
const T = Template('d-footnote-list', `
|
||||
<style>
|
||||
ol {
|
||||
padding: 0 0 0 18px;
|
||||
}
|
||||
li {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
color: rgba(0,0,0,0.65);
|
||||
line-height: 1em;
|
||||
}
|
||||
a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
a.footnote-backlink {
|
||||
color: rgba(0,0,0,0.3);
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<h3>Footnotes</h3>
|
||||
<ol></ol>
|
||||
`);
|
||||
|
||||
export class FootnoteList extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
this.list = this.root.querySelector('ol');
|
||||
// footnotes list is initially hidden
|
||||
this.root.host.style.display = 'none';
|
||||
// look through document and register existing footnotes
|
||||
// Store.subscribeTo('footnotes', (footnote) => {
|
||||
// this.renderFootnote(footnote);
|
||||
// });
|
||||
}
|
||||
|
||||
// TODO: could optimize this to accept individual footnotes?
|
||||
set footnotes(footnotes) {
|
||||
this.list.innerHTML = '';
|
||||
if (footnotes.length) {
|
||||
// ensure footnote list is visible
|
||||
this.root.host.style.display = 'initial';
|
||||
|
||||
for (const footnote of footnotes) {
|
||||
// construct and append list item to show footnote
|
||||
const listItem = document.createElement('li');
|
||||
listItem.id = footnote.id + '-listing';
|
||||
listItem.innerHTML = footnote.innerHTML;
|
||||
|
||||
const backlink = document.createElement('a');
|
||||
backlink.setAttribute('class', 'footnote-backlink');
|
||||
backlink.textContent = '[↩]';
|
||||
backlink.href = '#' + footnote.id;
|
||||
|
||||
listItem.appendChild(backlink);
|
||||
this.list.appendChild(listItem);
|
||||
}
|
||||
} else {
|
||||
// ensure footnote list is invisible
|
||||
this.shadowRoot.host.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Template } from "../mixins/template.js";
|
||||
import { HoverBox } from "../helpers/hover-box";
|
||||
// import { Store } from './store';
|
||||
|
||||
const T = Template("d-footnote", `
|
||||
<style>
|
||||
|
||||
d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div style="display: none;" class="dt-hover-box">
|
||||
<slot id='slot'></slot>
|
||||
</div>
|
||||
|
||||
<sup><span id="fn-" data-hover-ref="" style="cursor:pointer"></span></sup>
|
||||
|
||||
`);
|
||||
|
||||
export class Footnote extends T(HTMLElement) {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver(this.notify);
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
notify() {
|
||||
const options = { detail: this, bubbles: true };
|
||||
const event = new CustomEvent('onFootnoteChanged', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// listen and notify about changes to slotted content
|
||||
// const slot = this.shadowRoot.querySelector('#slot');
|
||||
// slot.addEventListener('slotchange', this.notify);
|
||||
|
||||
// create numeric ID
|
||||
Footnote.currentFootnoteId += 1;
|
||||
const IdString = Footnote.currentFootnoteId.toString();
|
||||
this.root.host.id = 'd-footnote-' + IdString;
|
||||
|
||||
// set up hidden hover box
|
||||
const div = this.root.querySelector('.dt-hover-box');
|
||||
div.id = 'dt-fn-hover-box-' + IdString;
|
||||
|
||||
// set up visible footnote marker
|
||||
const span = this.root.querySelector('#fn-');
|
||||
span.setAttribute('id', 'fn-' + IdString);
|
||||
span.setAttribute('data-hover-ref', div.id);
|
||||
span.textContent = IdString;
|
||||
|
||||
HoverBox.get_box(div).bind(span);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Footnote.currentFootnoteId = 0;
|
||||
@@ -0,0 +1,36 @@
|
||||
import ymlParse from "js-yaml";
|
||||
|
||||
export class FrontMatter extends HTMLElement {
|
||||
|
||||
static get is() { return "d-front-matter"; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver( (mutation) => {
|
||||
const data = this.parse();
|
||||
this.notify(data);
|
||||
});
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
parse(){
|
||||
const scriptTag = this.querySelector("script");
|
||||
if (scriptTag) {
|
||||
const yml = scriptTag.textContent;
|
||||
const data = ymlParse.safeLoad(yml);
|
||||
return data;
|
||||
} else {
|
||||
console.error('You added a frontmatter tag but did not provide a script tag with front matter data in it. Please take a look at our templates.')
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
notify(data) {
|
||||
const options = { detail: data, bubbles: true };
|
||||
const event = new CustomEvent('onFrontMatterChanged', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import katex from "katex";
|
||||
import { Mutating } from "../mixins/mutating.js"
|
||||
import { Template } from "../mixins/template.js"
|
||||
import katexCSS from "../../node_modules/katex/dist/katex.min.css"
|
||||
|
||||
const T = Template("d-math", `
|
||||
<style>
|
||||
|
||||
d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
${katexCSS}
|
||||
|
||||
</style>
|
||||
|
||||
<span id="katex-container"></span>
|
||||
`);
|
||||
|
||||
export class DMath extends Mutating(T(HTMLElement)) {
|
||||
|
||||
renderContent() {
|
||||
const options = { displayMode: this.hasAttribute("block") };
|
||||
const container = this.root.querySelector("#katex-container");
|
||||
katex.render(this.textContent, container, options);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { body } from "../helpers/layout";
|
||||
|
||||
const T = Template("d-references", `
|
||||
<style>
|
||||
d-references {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export class References extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Template } from "../mixins/template";
|
||||
import { page } from "../helpers/layout";
|
||||
|
||||
const T = Template("d-title", `
|
||||
<style>
|
||||
|
||||
:host {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
::slotted(h1) {
|
||||
padding-top: 140px;
|
||||
padding-bottom: 24px;
|
||||
margin: 0;
|
||||
line-height: 1em;
|
||||
font-size: 48px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
d-byline {
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
${page("::slotted(h1), ::slotted(h2)")}
|
||||
|
||||
</style>
|
||||
|
||||
<slot></slot>
|
||||
`);
|
||||
|
||||
export class Title extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import {Template} from "../mixins/template";
|
||||
|
||||
const T = Template("d-toc", `
|
||||
<style>
|
||||
d-toc {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export class TOC extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user