mirror of
https://github.com/wassname/template.git
synced 2026-09-12 13:00:27 +08:00
Switch to central controller for distributed control flow
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import { FrontMatter } from '../transforms/data';
|
||||
import { collectCitations } from './d-cite';
|
||||
|
||||
const frontMatter = new FrontMatter();
|
||||
|
||||
// set up global controller object
|
||||
/* functions whose names start with 'on' will be registered as listeners on d-article */
|
||||
export const Controller = {
|
||||
|
||||
frontMatter: frontMatter,
|
||||
waitingOn: {
|
||||
bibliography: [],
|
||||
citations: [],
|
||||
},
|
||||
listeners: {
|
||||
|
||||
onCiteKeyCreated(event) {
|
||||
const [citeTag, keys] = event.detail;
|
||||
|
||||
// ensure we have citations
|
||||
if (frontMatter.citations.length === 0) {
|
||||
console.debug('onCiteKeyCreated, but unresolved dependency ("citations"). Enqueing.');
|
||||
Controller.waitingOn.citations.push(() => Controller.listeners.onCiteKeyCreated(event));
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure we have a loaded bibliography
|
||||
if (frontMatter.bibliography.size === 0) {
|
||||
console.debug('onCiteKeyCreated, but unresolved dependency ("bibliography"). Enqueing.');
|
||||
Controller.waitingOn.bibliography.push(() => Controller.listeners.onCiteKeyCreated(event));
|
||||
return;
|
||||
}
|
||||
|
||||
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
|
||||
citeTag.numbers = numbers;
|
||||
const entries = keys.map( key => frontMatter.bibliography.get(key) );
|
||||
citeTag.entries = entries;
|
||||
},
|
||||
|
||||
onCiteKeyChanged(event) {
|
||||
const [citeTag, keys] = event.detail;
|
||||
|
||||
// update citations
|
||||
frontMatter.citations = collectCitations();
|
||||
for (const waitingCallback of Controller.waitingOn.citations) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
// update bibliography
|
||||
const bibliographyTag = document.querySelector('d-bibliography');
|
||||
const bibliographyEntries = new Map(frontMatter.citations.map( citationKey => {
|
||||
return [citationKey, frontMatter.bibliography.get(citationKey)];
|
||||
}));
|
||||
bibliographyTag.entries = bibliographyEntries;
|
||||
|
||||
const citeTags = document.querySelectorAll('d-cite');
|
||||
for (const citeTag of citeTags) {
|
||||
const keys = citeTag.keys;
|
||||
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
|
||||
citeTag.numbers = numbers;
|
||||
const entries = keys.map( key => frontMatter.bibliography.get(key) );
|
||||
citeTag.entries = entries;
|
||||
}
|
||||
|
||||
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
|
||||
citeTag.numbers = numbers;
|
||||
const entries = keys.map( key => frontMatter.bibliography.get(key) );
|
||||
citeTag.entries = entries;
|
||||
},
|
||||
|
||||
onBibliographyChanged(event) {
|
||||
const bibliographyTag = event.target;
|
||||
const bibliography = event.detail;
|
||||
|
||||
frontMatter.bibliography = bibliography;
|
||||
for (const waitingCallback of Controller.waitingOn.bibliography) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
// ensure we have citations
|
||||
if (frontMatter.citations.length === 0) {
|
||||
console.debug('onBibliographyChanged, but unresolved dependency ("citations"). Enqueing.');
|
||||
Controller.waitingOn.citations.push(() => Controller.listeners.onBibliographyChanged(event));
|
||||
return;
|
||||
}
|
||||
|
||||
const entries = new Map(frontMatter.citations.map( citationKey => {
|
||||
return [citationKey, frontMatter.bibliography.get(citationKey)];
|
||||
}));
|
||||
bibliographyTag.entries = entries;
|
||||
},
|
||||
|
||||
onFootnoteChanged(event) {
|
||||
const footnote = event.detail;
|
||||
//TODO: optimize to only update current footnote
|
||||
const footnotesList = document.querySelector('d-footnote-list');
|
||||
if (footnotesList) {
|
||||
const footnotes = document.querySelectorAll('d-footnote');
|
||||
footnotesList.footnotes = footnotes;
|
||||
}
|
||||
},
|
||||
|
||||
onFrontMatterChanged(event) {
|
||||
const data = event.detail;
|
||||
frontMatter.mergeFromYMLFrontmatter(data);
|
||||
|
||||
const appendix = document.querySelector('distill-appendix');
|
||||
appendix.frontMatter = frontMatter;
|
||||
},
|
||||
|
||||
DOMContentLoaded(event) {
|
||||
console.debug('DOMContentLoaded.');
|
||||
|
||||
const frontMatterTag = document.querySelector('d-front-matter');
|
||||
const data = frontMatterTag.parse();
|
||||
frontMatter.mergeFromYMLFrontmatter(data);
|
||||
const appendix = document.querySelector('distill-appendix');
|
||||
appendix.frontMatter = frontMatter;
|
||||
|
||||
console.debug('Resolving "citations" dependency due to initial DOM load.');
|
||||
frontMatter.citations = collectCitations();
|
||||
for (const waitingCallback of Controller.waitingOn.citations) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
const footnotesList = document.querySelector('d-footnote-list');
|
||||
if (footnotesList) {
|
||||
const footnotes = document.querySelectorAll('d-footnote');
|
||||
footnotesList.footnotes = footnotes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}, // listeners
|
||||
|
||||
update: {
|
||||
cite(element) {
|
||||
|
||||
},
|
||||
footnoteList(element) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // Controller
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Template} from "../mixins/template";
|
||||
import {body} from "./layout";
|
||||
import { Template } from "../mixins/template";
|
||||
import { body } from "./layout";
|
||||
|
||||
const T = Template("d-abstract", `
|
||||
<style>
|
||||
@@ -13,8 +13,6 @@ const T = Template("d-abstract", `
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export default class Abstract extends T(HTMLElement) {
|
||||
static get is() { return "d-abstract"; }
|
||||
}
|
||||
export class Abstract extends T(HTMLElement) {
|
||||
|
||||
customElements.define(Abstract.is, Abstract);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Template } from "../mixins/template";
|
||||
|
||||
const name = 'd-acknowledgements';
|
||||
|
||||
const T = Template(name, `
|
||||
const T = Template('d-acknowledgements', `
|
||||
<style>
|
||||
::slotted(h3) {
|
||||
font-size: 15px;
|
||||
@@ -20,10 +18,6 @@ const T = Template(name, `
|
||||
<slot></slot>
|
||||
`);
|
||||
|
||||
export default class Acknowledgements extends T(HTMLElement) {
|
||||
|
||||
static get is() { return name; }
|
||||
export class Acknowledgements extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
|
||||
customElements.define(name, Acknowledgements);
|
||||
|
||||
@@ -25,10 +25,6 @@ ${page(".l-body")}
|
||||
</div>
|
||||
`);
|
||||
|
||||
export default class Appendix extends T(HTMLElement) {
|
||||
|
||||
static get is() { return "d-appendix"; }
|
||||
export class Appendix extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
|
||||
customElements.define(Appendix.is, Appendix);
|
||||
|
||||
+22
-205
@@ -1,209 +1,26 @@
|
||||
import {Template} from "../mixins/template";
|
||||
import { Template } from '../mixins/template';
|
||||
import { Controller } from './controller';
|
||||
|
||||
const T = Template("d-article", `
|
||||
<style>
|
||||
d-article {
|
||||
display: block;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
padding-top: 36px;
|
||||
padding-bottom: 72px;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
line-height: 1.6em;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H2 */
|
||||
|
||||
d-article h2 {
|
||||
font-weight: 400;
|
||||
font-size: 26px;
|
||||
line-height: 1.25em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article h2 {
|
||||
margin-top: 2em;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
d-article h1 + h2 {
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 8px;
|
||||
font-style: normal;
|
||||
}
|
||||
@media(min-width: 1080px) {
|
||||
.centered h1 + h2 {
|
||||
text-align: center;
|
||||
}
|
||||
d-article h1 + h2 {
|
||||
margin-top: 12px;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H3 */
|
||||
|
||||
d-article h3 {
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 18px;
|
||||
font-style: italic;
|
||||
}
|
||||
d-article h1 + h3 {
|
||||
margin-top: 48px;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article h3 {
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H4 */
|
||||
|
||||
d-article h4 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
d-article a {
|
||||
color: inherit;
|
||||
}
|
||||
d-article p,
|
||||
d-article ul,
|
||||
d-article ol {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
d-article p b,
|
||||
d-article ul b,
|
||||
d-article ol b {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
d-article a {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
|
||||
text-decoration: none;
|
||||
}
|
||||
d-article a:hover {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
d-article .link {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
d-article ul,
|
||||
d-article ol {
|
||||
padding-left: 24px;
|
||||
}
|
||||
d-article li {
|
||||
margin-bottom: 24px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
d-article pre {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
d-article hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
d-article section {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
/* Figure */
|
||||
|
||||
d-article figure {
|
||||
position: relative;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article figure {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
}
|
||||
d-article figure img {
|
||||
width: 100%;
|
||||
}
|
||||
d-article figure svg text,
|
||||
d-article figure svg tspan {
|
||||
}
|
||||
d-article figure figcaption {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article figure figcaption {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
d-article figure.external img {
|
||||
background: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
d-article figure figcaption a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
/*d-article figure figcaption::before {
|
||||
position: relative;
|
||||
display: block;
|
||||
top: -20px;
|
||||
content: "";
|
||||
width: 25px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.3);
|
||||
}*/
|
||||
d-article span.equation-mimic {
|
||||
font-family: georgia;
|
||||
font-size: 115%;
|
||||
font-style: italic;
|
||||
}
|
||||
d-article figure figcaption b {
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 1.0);
|
||||
}
|
||||
d-article > d-code,
|
||||
d-article section > d-code {
|
||||
display: block;
|
||||
}
|
||||
d-article > d-math[block],
|
||||
d-article section > d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
d-article .citation {
|
||||
color: #668;
|
||||
cursor: pointer;
|
||||
}
|
||||
d-include {
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
const T = Template('d-article', `
|
||||
<style></style>
|
||||
`, false);
|
||||
|
||||
export default class Article extends T(HTMLElement) {
|
||||
static get is() { return "d-article"; }
|
||||
}
|
||||
|
||||
customElements.define(Article.is, Article);
|
||||
|
||||
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!')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import bibtexParse from "bibtex-parse-js";
|
||||
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 "./citation";
|
||||
|
||||
const name = 'd-bibliography';
|
||||
const T = Template(name, `
|
||||
const T = Template('d-bibliography', `
|
||||
<style>
|
||||
.references {
|
||||
font-size: 12px;
|
||||
@@ -35,7 +36,7 @@ const T = Template(name, `
|
||||
<ol></ol>
|
||||
`);
|
||||
|
||||
function parseBibtex(bibtex) {
|
||||
export function parseBibtex(bibtex) {
|
||||
const bibliography = new Map();
|
||||
const parsedEntries = bibtexParse.toJSON(bibtex);
|
||||
for (const entry of parsedEntries) {
|
||||
@@ -56,66 +57,80 @@ function parseBibtex(bibtex) {
|
||||
return bibliography;
|
||||
}
|
||||
|
||||
export default class Bibliography extends T(HTMLElement) {
|
||||
export class Bibliography extends T(HTMLElement) {
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.citations = new Array();
|
||||
this.finishedLoading = false;
|
||||
// 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';
|
||||
// parse bibliography
|
||||
const scriptTag = this.querySelector("script");
|
||||
if (scriptTag) {
|
||||
this.bibliography = parseBibtex(scriptTag.textContent);
|
||||
this.finishedLoading = true;
|
||||
// look through document and register existing citations
|
||||
document.querySelectorAll('d-cite')
|
||||
.forEach(citation => this.registerCitation(citation));
|
||||
} else {
|
||||
console.error("No script tag with bibtex found in d-bibliography tag!")
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getEntry(key) {
|
||||
return this.bibliography.get(key);
|
||||
}
|
||||
|
||||
hasEntry(key) {
|
||||
return this.bibliography.has(key);
|
||||
}
|
||||
|
||||
getIndex(key) {
|
||||
return this.citations.indexOf(key);
|
||||
}
|
||||
|
||||
registerCitation(citation) {
|
||||
// a d-cite element may cite multiple sources
|
||||
const keyString = citation.getAttribute("key");
|
||||
const keys = keyString ? keyString.split(",") : [];
|
||||
for (const key of keys) {
|
||||
if (!this.bibliography.has(key)) {
|
||||
console.error("Citation key '" + key + "' is not present in bibliography!")
|
||||
} else if (this.citations.indexOf(key) === -1) {
|
||||
this.citations.push(key);
|
||||
const entry = this.getEntry(key);
|
||||
// ensure citations list is visible
|
||||
this.root.host.style.display = 'initial';
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define(Bibliography.is, Bibliography);
|
||||
|
||||
+6
-15
@@ -55,13 +55,8 @@ const T = Template("d-byline", `
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
{
|
||||
:host {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
@@ -152,17 +147,13 @@ const mustacheTemplate = `
|
||||
{{/citation}}
|
||||
`;
|
||||
|
||||
export default class Byline extends T(HTMLElement) {
|
||||
|
||||
static get is() { return "d-byline"; }
|
||||
export class Byline extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
const frontmatter = document.querySelector('d-front-matter');
|
||||
const container = this.root.querySelector('.byline');
|
||||
container.innerHTML = mustache.render(mustacheTemplate, frontmatter.data);
|
||||
console.log(frontmatter.data)
|
||||
// const frontmatter = document.querySelector('d-front-matter');
|
||||
// const container = this.root.querySelector('.byline');
|
||||
// container.innerHTML = mustache.render(mustacheTemplate, frontmatter.data);
|
||||
// // console.log(frontmatter.data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define(Byline.is, Byline);
|
||||
|
||||
+94
-50
@@ -28,7 +28,7 @@ const T = Template('d-cite', `
|
||||
}
|
||||
</style>
|
||||
|
||||
<div style="display: none;" class="dt-hover-box">
|
||||
<div style="display: none;" id="hover-box" class="dt-hover-box">
|
||||
</div>
|
||||
|
||||
<span id="citation-" class="citation">
|
||||
@@ -37,76 +37,120 @@ const T = Template('d-cite', `
|
||||
</span>
|
||||
`);
|
||||
|
||||
|
||||
function inline_cite_short(keys, bibliography) {
|
||||
function cite_string(key) {
|
||||
if (bibliography.hasEntry(key)){
|
||||
return (bibliography.getIndex(key)+1).toString();
|
||||
} else {
|
||||
return "?";
|
||||
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 "[" + keys.map(cite_string).join(", ") + "]";
|
||||
return [...citations];
|
||||
}
|
||||
|
||||
export class Cite extends T(HTMLElement) {
|
||||
|
||||
export default class Cite extends T(HTMLElement) {
|
||||
/* Lifecycle */
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this._key = null;
|
||||
|
||||
Cite.currentId += 1;
|
||||
this.citeId = Cite.currentId;
|
||||
// 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) {
|
||||
// name will always be "key" due to observedAttributes
|
||||
this._key = newValue;
|
||||
this.renderContent();
|
||||
}
|
||||
|
||||
get key() {
|
||||
return this._key;
|
||||
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);
|
||||
}
|
||||
|
||||
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.`)
|
||||
}
|
||||
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.`)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
Cite.currentId = 0;
|
||||
|
||||
customElements.define(Cite.is, Cite);
|
||||
|
||||
@@ -6,9 +6,7 @@ import css from "prismjs/themes/prism.css";
|
||||
import { Template } from "../mixins/template.js"
|
||||
import { Mutating } from "../mixins/mutating.js"
|
||||
|
||||
|
||||
|
||||
const templateString = `
|
||||
const T = Template("d-code", `
|
||||
<style>
|
||||
|
||||
code {
|
||||
@@ -32,11 +30,9 @@ ${css}
|
||||
|
||||
<code id="code-container"></code>
|
||||
|
||||
`
|
||||
`);
|
||||
|
||||
const Templated = Template("d-code", templateString);
|
||||
|
||||
export class Code extends Mutating(Templated(HTMLElement)) {
|
||||
export class Code extends Mutating(T(HTMLElement)) {
|
||||
|
||||
renderContent() {
|
||||
|
||||
@@ -76,5 +72,3 @@ export class Code extends Mutating(Templated(HTMLElement)) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define("d-code", Code);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Template } from "../mixins/template";
|
||||
// import { Store } from './store';
|
||||
|
||||
const name = 'd-footnote-list';
|
||||
const T = Template(name, `
|
||||
const T = Template('d-footnote-list', `
|
||||
<style>
|
||||
ol {
|
||||
padding: 0 0 0 18px;
|
||||
@@ -33,40 +33,47 @@ a.footnote-backlink {
|
||||
<ol></ol>
|
||||
`);
|
||||
|
||||
export default class FootnoteList extends T(HTMLElement) {
|
||||
|
||||
static get is() { return name; }
|
||||
export class FootnoteList extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
this.list = this.root.querySelector('ol');
|
||||
this.footnotes = new Map();
|
||||
// footnotes list is initially hidden
|
||||
this.root.host.style.display = 'none';
|
||||
// look through document and register existing footnotes
|
||||
document.querySelectorAll('d-footnote')
|
||||
.forEach(footnote => this.registerFootnote(footnote));
|
||||
// Store.subscribeTo('footnotes', (footnote) => {
|
||||
// this.renderFootnote(footnote);
|
||||
// });
|
||||
}
|
||||
|
||||
registerFootnote(element) {
|
||||
// check if we already know about this footnote
|
||||
if (!this.footnotes.has(element.id)) {
|
||||
this.footnotes.set(element.id, element);
|
||||
// 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'
|
||||
// construct and append list item to show footnote
|
||||
const listItem = document.createElement('li');
|
||||
listItem.innerHTML = element.innerHTML;
|
||||
const backlink = document.createElement('a');
|
||||
backlink.setAttribute('class', 'footnote-backlink');
|
||||
backlink.textContent = '[↩]';
|
||||
backlink.href = `#${element.id}`;
|
||||
listItem.appendChild(backlink);
|
||||
this.list.appendChild(listItem);
|
||||
} /*else {
|
||||
console.debug('Had already registered footnote ' + element.id + '!')
|
||||
}*/
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
renderFootnote(element) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define(name, FootnoteList);
|
||||
|
||||
+23
-16
@@ -1,7 +1,8 @@
|
||||
import { Template } from "../mixins/template.js"
|
||||
import { HoverBox } from "./hover-box.js"
|
||||
// import { Store } from './store';
|
||||
|
||||
const templateString = `
|
||||
const T = Template("d-footnote", `
|
||||
<style>
|
||||
|
||||
d-math[block] {
|
||||
@@ -11,18 +12,34 @@ d-math[block] {
|
||||
</style>
|
||||
|
||||
<div style="display: none;" class="dt-hover-box">
|
||||
<slot></slot>
|
||||
<slot id='slot'></slot>
|
||||
</div>
|
||||
|
||||
<sup><span id="fn-" data-hover-ref="" style="cursor:pointer"></span></sup>
|
||||
|
||||
`;
|
||||
`);
|
||||
|
||||
const TemplatedFootnote = Template("d-footnote", templateString);
|
||||
export class Footnote extends T(HTMLElement) {
|
||||
|
||||
export class Footnote extends TemplatedFootnote(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();
|
||||
@@ -37,20 +54,10 @@ export class Footnote extends TemplatedFootnote(HTMLElement) {
|
||||
span.setAttribute('id', 'fn-' + IdString);
|
||||
span.setAttribute('data-hover-ref', div.id);
|
||||
span.textContent = IdString;
|
||||
|
||||
HoverBox.get_box(div).bind(span);
|
||||
|
||||
// register with footnote list should there be one
|
||||
const footnoteList = document.querySelector('d-footnote-list');
|
||||
if (footnoteList) {
|
||||
customElements.whenDefined('d-footnote-list').then(() => {
|
||||
footnoteList.registerFootnote(this);
|
||||
});
|
||||
}
|
||||
HoverBox.get_box(div).bind(span);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Footnote.currentFootnoteId = 0;
|
||||
|
||||
customElements.define("d-footnote", Footnote);
|
||||
|
||||
@@ -1,52 +1,36 @@
|
||||
import ymlParse from "js-yaml";
|
||||
import expandData from "../transforms/expand-data"
|
||||
|
||||
export default class FrontMatter extends HTMLElement {
|
||||
export class FrontMatter extends HTMLElement {
|
||||
|
||||
static get is() { return "d-front-matter"; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.data = {};
|
||||
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver( (mutation) => {
|
||||
const data = this.parse();
|
||||
this.notify(data);
|
||||
});
|
||||
observer.observe(this, options);
|
||||
}
|
||||
connectedCallback() {
|
||||
const el = this.querySelector("script");
|
||||
if (el) {
|
||||
const text = el.textContent;
|
||||
this.parse(ymlParse.safeLoad(text));
|
||||
|
||||
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 {};
|
||||
}
|
||||
}
|
||||
parse(localData) {
|
||||
this.data.title = localData.title ? localData.title : "Untitled";
|
||||
this.data.description = localData.description ? localData.description : "No description.";
|
||||
this.data.publishedDate = localData.published ? new Date(localData.published) : false;
|
||||
|
||||
this.data.authors = localData.authors ? localData.authors : [];
|
||||
|
||||
this.data.authors = this.data.authors.map((author, i) =>{
|
||||
let a = {};
|
||||
let name = Object.keys(author)[0];
|
||||
if ((typeof author) === "string") {
|
||||
name = author;
|
||||
} else {
|
||||
a.personalURL = author[name];
|
||||
}
|
||||
let names = name.split(" ");
|
||||
a.name = name;
|
||||
a.firstName = names.slice(0, names.length - 1).join(" ");
|
||||
a.lastName = names[names.length -1];
|
||||
if (localData.affiliations[i]) {
|
||||
let affiliation = Object.keys(localData.affiliations[i])[0];
|
||||
if ((typeof localData.affiliations[i]) === "string") {
|
||||
affiliation = localData.affiliations[i]
|
||||
} else {
|
||||
a.affiliationURL = localData.affiliations[i][affiliation];
|
||||
}
|
||||
a.affiliation = affiliation;
|
||||
}
|
||||
return a;
|
||||
});
|
||||
|
||||
expandData(null, this.data);
|
||||
notify(data) {
|
||||
const options = { detail: data, bubbles: true };
|
||||
const event = new CustomEvent('onFrontMatterChanged', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(FrontMatter.is, FrontMatter);
|
||||
}
|
||||
|
||||
+8
-10
@@ -1,30 +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 templateString = `
|
||||
const T = Template("d-math", `
|
||||
<style>
|
||||
|
||||
d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
${katexCSS}
|
||||
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css">
|
||||
|
||||
<span id="katex-container"></span>
|
||||
`;
|
||||
`);
|
||||
|
||||
const TemplatedMath = Template("d-math", templateString);
|
||||
|
||||
export class Math extends Mutating(TemplatedMath(HTMLElement)) {
|
||||
export class DMath extends Mutating(T(HTMLElement)) {
|
||||
|
||||
renderContent() {
|
||||
const options = { displayMode: this.hasAttribute("block") };
|
||||
const container = this.shadowRoot.querySelector("#katex-container")
|
||||
const container = this.root.querySelector("#katex-container");
|
||||
katex.render(this.textContent, container, options);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("d-math", Math);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Template} from "../mixins/template";
|
||||
import {body} from "./layout";
|
||||
import { Template } from "../mixins/template";
|
||||
import { body } from "./layout";
|
||||
|
||||
const T = Template("d-references", `
|
||||
<style>
|
||||
@@ -9,11 +9,10 @@ d-references {
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export default class References extends T(HTMLElement) {
|
||||
static get is() { return "d-references"; }
|
||||
export class References extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(References.is, References);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Template} from "../mixins/template";
|
||||
import {page} from "./layout";
|
||||
import { Template } from "../mixins/template";
|
||||
import { page } from "./layout";
|
||||
|
||||
const T = Template("d-title", `
|
||||
<style>
|
||||
@@ -32,9 +32,7 @@ ${page("::slotted(h1), ::slotted(h2)")}
|
||||
<d-byline></d-byline>
|
||||
`);
|
||||
|
||||
export default class Title extends T(HTMLElement) {
|
||||
|
||||
static get is() { return "d-title"; }
|
||||
export class Title extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
@@ -44,5 +42,3 @@ export default class Title extends T(HTMLElement) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define(Title.is, Title);
|
||||
|
||||
+2
-6
@@ -8,10 +8,6 @@ d-toc {
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export default class Toc extends T(HTMLElement) {
|
||||
static get is() {
|
||||
return "d-toc";
|
||||
}
|
||||
}
|
||||
export class TOC extends T(HTMLElement) {
|
||||
|
||||
customElements.define(Toc.is, Toc);
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import {page} from "./layout";
|
||||
import mustache from "mustache";
|
||||
|
||||
let mustacheTemplate = `
|
||||
<style>
|
||||
distill-appendix h3 {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0;
|
||||
color: rgba(0,0,0,0.65);
|
||||
line-height: 1em;
|
||||
}
|
||||
distill-appendix a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
distill-appendix ol,
|
||||
distill-appendix ul {
|
||||
padding-left: 24px;
|
||||
}
|
||||
distill-appendix .citation {
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-left: 18px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
padding: 10px 18px;
|
||||
border-radius: 3px;
|
||||
color: rgba(150, 150, 150, 1);
|
||||
overflow: hidden;
|
||||
margin-top: -12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h3>Updates and Corrections</h3>
|
||||
<p><a href="">View all changes</a> to this article since it was first published. If you see mistakes or want to suggest changes, please <a href="">create an issue on GitHub</a>. </p>
|
||||
|
||||
<h3>Reuse</h3>
|
||||
<p>Diagrams and text are licensed under Creative Commons Attribution <a href="https://creativecommons.org/licenses/by/2.0/">CC-BY 2.0</a> with the <a class="github" href="https://github.com/distillpub/post--augmented-rnns">source available on GitHub</a>, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”.</p>
|
||||
|
||||
<h3>Citation</h3>
|
||||
<p>For attribution in academic contexts, please cite this work as</p>
|
||||
<pre class="citation short">Olah & Carter, "Attention and Augmented Recurrent Neural Networks", Distill, 2016.</pre>
|
||||
<p>BibTeX citation</p>
|
||||
<pre class="citation long">@article{olah2016attention,
|
||||
author = {Olah, Chris and Carter, Shan},
|
||||
title = {Attention and Augmented Recurrent Neural Networks},
|
||||
journal = {Distill},
|
||||
year = {2016},
|
||||
note = {http://distill.pub/2016/augmented-rnns}
|
||||
}</pre>
|
||||
`;
|
||||
|
||||
export default class DistillAppendix extends HTMLElement {
|
||||
static get is() { return "distill-appendix"; }
|
||||
connectedCallback(data) {
|
||||
this.innerHTML = mustache.render(mustacheTemplate, data);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(DistillAppendix.is, DistillAppendix);
|
||||
@@ -94,7 +94,7 @@ HoverBox.prototype.bind = function bind(node) {
|
||||
}
|
||||
// Don't trigger body touchstart event when touching link
|
||||
e.stopPropagation();
|
||||
}.bind(this));
|
||||
}.bind(this), {passive: true});
|
||||
}
|
||||
|
||||
HoverBox.prototype.bindDivEvents = function bindDivEvents(node){
|
||||
@@ -106,7 +106,7 @@ HoverBox.prototype.bindDivEvents = function bindDivEvents(node){
|
||||
this.div.addEventListener("mouseout", function(){this.extendTimeout(250);}.bind(this));
|
||||
|
||||
// Don't trigger body touchstart event when touching within box
|
||||
this.div.addEventListener("touchstart", function(e){e.stopPropagation();});
|
||||
this.div.addEventListener("touchstart", function(e){e.stopPropagation();}, {passive: true});
|
||||
// Close box when touching outside box
|
||||
document.body.addEventListener("touchstart", function(){this.hide();}.bind(this));
|
||||
document.body.addEventListener("touchstart", function(){this.hide();}.bind(this), {passive: true});
|
||||
}
|
||||
|
||||
@@ -44,29 +44,6 @@ export function page(selector) {
|
||||
`;
|
||||
}
|
||||
|
||||
export function pagePadding(selector) {
|
||||
return `${selector} {
|
||||
width: auto;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@media(min-width: 768px) {
|
||||
${selector} {
|
||||
padding-left: 72px;
|
||||
padding-right: 72px;
|
||||
}
|
||||
}
|
||||
@media(min-width: 1080px) {
|
||||
${selector} {
|
||||
width: 984px;
|
||||
padding-left: auto;
|
||||
padding-right: auto;
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
export function screen(selector) {
|
||||
return `${selector} {
|
||||
width: auto;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
class DataStore {
|
||||
|
||||
constructor() {
|
||||
this.collections = new Map();
|
||||
this.subscribers = new Map();
|
||||
}
|
||||
|
||||
get(collectionName) {
|
||||
return this.collections.get(collectionName);
|
||||
}
|
||||
|
||||
set(collectionName, collection) {
|
||||
this.collections.set(collectionName, collection);
|
||||
// notify subscribers
|
||||
if (this.subscribers.has(collectionName)) {
|
||||
const subscribers = this.subscribers.get(collectionName);
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber(collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register(collectionName, element) {
|
||||
// create collection if it doesn't yet exist
|
||||
if (!this.collections.has(collectionName)) {
|
||||
this.collections.set(collectionName, []);
|
||||
}
|
||||
// add new element to collection
|
||||
const collection = this.collections.get(collectionName);
|
||||
collection.push(element);
|
||||
// notify subscribers
|
||||
if (this.subscribers.has(collectionName)) {
|
||||
const subscribers = this.subscribers.get(collectionName);
|
||||
for (const subscriber of subscribers) {
|
||||
subscriber(element, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subscribeTo(collectionName, callback) {
|
||||
// create subscriber collection if it doesn't yet exist
|
||||
if (!this.subscribers.has(collectionName)) {
|
||||
this.subscribers.set(collectionName, []);
|
||||
}
|
||||
// add new callback to list of subscribers
|
||||
const subscribers = this.subscribers.get(collectionName);
|
||||
subscribers.push(callback);
|
||||
// notify subscriber about existing collection entries
|
||||
if (this.collections.has(collectionName)) {
|
||||
const collection = this.collections.get(collectionName);
|
||||
for (const entry of collection) {
|
||||
callback(entry, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// set up store
|
||||
// export const Store = new DataStore();
|
||||
@@ -0,0 +1,197 @@
|
||||
d-article {
|
||||
display: block;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
padding-top: 36px;
|
||||
padding-bottom: 72px;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
line-height: 1.6em;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H2 */
|
||||
|
||||
d-article h2 {
|
||||
font-weight: 400;
|
||||
font-size: 26px;
|
||||
line-height: 1.25em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article h2 {
|
||||
margin-top: 2em;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
d-article h1 + h2 {
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 8px;
|
||||
font-style: normal;
|
||||
}
|
||||
@media(min-width: 1080px) {
|
||||
.centered h1 + h2 {
|
||||
text-align: center;
|
||||
}
|
||||
d-article h1 + h2 {
|
||||
margin-top: 12px;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H3 */
|
||||
|
||||
d-article h3 {
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 18px;
|
||||
font-style: italic;
|
||||
}
|
||||
d-article h1 + h3 {
|
||||
margin-top: 48px;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article h3 {
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H4 */
|
||||
|
||||
d-article h4 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
d-article a {
|
||||
color: inherit;
|
||||
}
|
||||
d-article p,
|
||||
d-article ul,
|
||||
d-article ol {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
d-article p b,
|
||||
d-article ul b,
|
||||
d-article ol b {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
d-article a {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
|
||||
text-decoration: none;
|
||||
}
|
||||
d-article a:hover {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
d-article .link {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
d-article ul,
|
||||
d-article ol {
|
||||
padding-left: 24px;
|
||||
}
|
||||
d-article li {
|
||||
margin-bottom: 24px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
d-article pre {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
d-article hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
d-article section {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
/* Figure */
|
||||
|
||||
d-article figure {
|
||||
position: relative;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article figure {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
}
|
||||
d-article figure img {
|
||||
width: 100%;
|
||||
}
|
||||
d-article figure svg text,
|
||||
d-article figure svg tspan {
|
||||
}
|
||||
d-article figure figcaption {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
d-article figure figcaption {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
d-article figure.external img {
|
||||
background: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
d-article figure figcaption a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
/*d-article figure figcaption::before {
|
||||
position: relative;
|
||||
display: block;
|
||||
top: -20px;
|
||||
content: "";
|
||||
width: 25px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.3);
|
||||
}*/
|
||||
d-article span.equation-mimic {
|
||||
font-family: georgia;
|
||||
font-size: 115%;
|
||||
font-style: italic;
|
||||
}
|
||||
d-article figure figcaption b {
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 1.0);
|
||||
}
|
||||
d-article > d-code,
|
||||
d-article section > d-code {
|
||||
display: block;
|
||||
}
|
||||
d-article > d-math[block],
|
||||
d-article section > d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
d-article .citation {
|
||||
color: #668;
|
||||
cursor: pointer;
|
||||
}
|
||||
d-include {
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ import base from "./styles-base.css";
|
||||
import layout from "./styles-layout.css";
|
||||
import article from "./styles-article.css";
|
||||
import print from "./styles-print.css";
|
||||
import katex from '../node_modules/katex/dist/katex.min.css'
|
||||
|
||||
let s = document.createElement("style");
|
||||
s.textContent = base + layout + print + article;
|
||||
s.textContent = base + layout + print + article + katex;
|
||||
document.querySelector("head").appendChild(s);
|
||||
export default s;
|
||||
|
||||
Reference in New Issue
Block a user