Compare commits

..

1 Commits

Author SHA1 Message Date
Ludwig Schubert a3c9c58c03 2.2.0 2017-10-23 15:47:12 -07:00
31 changed files with 467 additions and 544 deletions
+2 -2
View File
@@ -2,11 +2,11 @@ language: node_js
node_js:
- "node" # latest version
cache:
yarn: true
directories:
- node_modules
script:
- npm run build
- npm test
- yarn build
deploy:
provider: releases
api_key: $GITHUB_OAUTH_TOKEN
+1 -5
View File
@@ -2,12 +2,9 @@
<head>
<script src="../dist/template.v2.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" >
<meta charset="utf8">
</head>
<body>
<distill-header></distill-header>
<d-front-matter>
<script id='distill-front-matter' type="text/json">{
"title": "Why Momentum Really Works",
@@ -42,7 +39,7 @@
</d-front-matter>
<d-title>
<figure style="grid-column: page; margin: 1rem 0;"><img src="momentum.png" style="width:100%; border: 1px solid rgba(0, 0, 0, 0.2);"/></figure>
<p>We often think of Momentum<d-cite key="mercier2011humans"></d-cite> as a means of dampening oscillations and speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p>
<p>We often think of Momentum as a means of dampening oscillations and speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p>
</d-title>
<d-article>
<a class="marker" href="#section-1" id="section-1"><span>1</span></a>
@@ -61,7 +58,6 @@
</d-math>
<a class="marker" href="#section-1.1" id="section-1.1"><span>1.1</span></a>
<h3>Citations</h3>
<p><d-slider style="width: 200px;"></d-slider></p>
<p>We can<d-cite key="mercier2011humans"></d-cite> also cite <d-cite key="gregor2015draw,mercier2011humans"></d-cite> external publications. <d-cite key="dong2014image,dumoulin2016guide,mordvintsev2015inceptionism"></d-cite>. We should also be testing footnotes<d-footnote>This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote. This will become a hoverable footnote.</d-footnote>. There are multiple footnotes, and they appear in the appendix<d-footnote>Given I have coded them right. Also, here's math in a footnote: <d-math>c = \sum_0^i{x}</d-math>. Also, a citation. Box-ception<d-cite key='gregor2015draw'></d-cite>!</d-footnote> as well.</p>
<a class="marker" href="#section-2" id="section-2"><span>2</span></a>
<h2>Displaying code snippets</h2>
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "distill-template",
"version": "2.2.18",
"version": "2.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -3987,11 +3987,11 @@
}
},
"katex": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.8.3.tgz",
"integrity": "sha512-0VKw+G/wvgLKMy4fhhKdPGjXehYF3l3PBRdzkvBivK5wMtAH9xRHImQaGk9gaukBTdOfZ1Biq8kL5vgkUsBT0Q==",
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.7.1.tgz",
"integrity": "sha1-BrtSmO+tBeHnIoA1uo4VkfMGG48=",
"requires": {
"match-at": "0.1.1"
"match-at": "0.1.0"
}
},
"kind-of": {
@@ -4190,9 +4190,9 @@
"dev": true
},
"match-at": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.1.tgz",
"integrity": "sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q=="
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.0.tgz",
"integrity": "sha1-9WHncJ/5oQW4XMYsa47nwVvyTzE="
},
"memory-fs": {
"version": "0.4.1",
@@ -5157,9 +5157,9 @@
}
},
"rollup": {
"version": "0.50.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.50.0.tgz",
"integrity": "sha512-7RqCBQ9iwsOBPkjYgoIaeUij606mSkDMExP0NT7QDI3bqkHYQHrQ83uoNIXwPcQm/vP2VbsUz3kiyZZ1qPlLTQ==",
"version": "0.49.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.49.2.tgz",
"integrity": "sha512-9mySqItSwq5/dXYQyFGrrzqV282EZfz4kSCU2m4e6OjgqLmIsp9zK6qNQ6wbBWR4EhASEqQMBQ/IF45jaNPAtw==",
"dev": true
},
"rollup-plugin-babili": {
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "distill-template",
"version": "2.2.18",
"version": "2.2.0",
"description": "Template for creating Distill articles.",
"main": "dist/template.v2.js",
"bin": {
@@ -12,7 +12,7 @@
"url": "https://github.com/distillpub/distill-template/issues"
},
"scripts": {
"dev": "rollup -c rollup.config.dev.js -w",
"start": "rollup -c rollup.config.dev.js -w",
"serve": "python3 -m http.server --bind 127.0.0.1 8888",
"test": "mocha",
"lint": "eslint",
@@ -34,7 +34,7 @@
"marked": "^0.3.6",
"mocha": "^3.5.3",
"prismjs": "^1.6.0",
"rollup": "^0.50.0",
"rollup": "latest",
"rollup-plugin-babili": "^3.1.0",
"rollup-plugin-buble": "^0.15.0",
"rollup-plugin-commonjs": "^7.0.0",
@@ -61,6 +61,6 @@
"escape-html": "^1.0.3",
"intersection-observer": "^0.4.0",
"jsdom-wc": "^11.0.0-alpha-1",
"katex": "^0.8.3"
"katex": "^0.7.1"
}
}
+10 -26
View File
@@ -2,7 +2,7 @@ import { Controller } from './controller';
/* Transforms */
import { makeStyleTag } from './styles/styles';
import { Polyfills } from './helpers/polyfills';
import { Polyfills, polyfills } from './helpers/polyfills';
/* Components */
import { Abstract } from './components/d-abstract';
@@ -16,7 +16,6 @@ import { Code } from './components/d-code';
import { Footnote } from './components/d-footnote';
import { FootnoteList } from './components/d-footnote-list';
import { FrontMatter } from './components/d-front-matter';
import { HoverBox } from './components/d-hover-box';
import { Title } from './components/d-title';
import { DMath } from './components/d-math';
import { References } from './components/d-references';
@@ -48,25 +47,13 @@ const distillMain = function() {
makeStyleTag(document);
console.info('Runlevel 1: Static Distill styles have been added.');
console.info('Runlevel 1->2.');
window.distillRunlevel += 1;
window.distillRunlevel = 2;
/* 3. Register Controller listener functions */
/* Needs to happen before components to their connected callbacks have a controller to talk to. */
for (const [functionName, callback] of Object.entries(Controller.listeners)) {
if (typeof callback === 'function') {
document.addEventListener(functionName, callback);
} else {
console.error('Runlevel 2: Controller listeners need to be functions!');
}
}
console.info('Runlevel 2: We can now listen to controller events.');
console.info('Runlevel 2->3.');
window.distillRunlevel += 1;
/* 4. Register components */
/* 3. Register components */
/* Article will register controller which takes control from there */
const components = [
Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code,
Footnote, FootnoteList, FrontMatter, HoverBox, Title, DMath, References, TOC, Figure,
Footnote, FootnoteList, FrontMatter, Title, DMath, References, TOC, Figure,
Slider, Interstitial
];
@@ -83,15 +70,12 @@ const distillMain = function() {
customElements.define(component.is, component);
}
console.info('Runlevel 3: Distill Template finished registering custom elements.');
console.info('Runlevel 3->4.');
window.distillRunlevel += 1;
// If template was added after DOMContentLoaded we may have missed that event.
// Controller will check for that case, so trigger the event explicitly:
console.info('Runlevel 2: Distill Template finished registering custom elements.');
console.info('Runlevel 2->3.');
window.distillRunlevel = 3;
console.info('Distill Template initialisation complete.');
Controller.listeners.DOMContentLoaded();
console.info('Runlevel 4: Distill Template initialisation complete.');
};
window.distillRunlevel = 0;
@@ -99,7 +83,7 @@ window.distillRunlevel = 0;
if (Polyfills.browserSupportsAllFeatures()) {
console.info('Runlevel 0: No need for polyfills.');
console.info('Runlevel 0->1.');
window.distillRunlevel += 1;
window.distillRunlevel = 1;
distillMain();
} else {
console.info('Runlevel 0: Distill Template is loading polyfills.');
+2 -1
View File
@@ -1,10 +1,11 @@
import { Template } from '../mixins/template';
import { body } from '../helpers/layout';
const T = Template('d-appendix', `
<style>
d-appendix {
contain: layout style;
contain: content;
font-size: 0.8em;
line-height: 1.7em;
margin-top: 60px;
+19 -2
View File
@@ -1,5 +1,6 @@
// import { Template } from '../mixins/template';
// import { Controller } from '../controller';
import { Template } from '../mixins/template';
import { Controller } from '../controller';
import style from '../styles/d-article.css';
const isOnlyWhitespace = /^\s*$/;
@@ -29,4 +30,20 @@ export class Article extends HTMLElement {
}).observe(this, {childList: true});
}
connectedCallback() {
document.onreadystatechange = function () {
console.log("onreadystatechange:");
console.log(document.readyState);
};
console.info('Article tag connected, we can now listen to controller events.');
console.info('Runlevel 3->4.');
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!');
}
}
}
}
-6
View File
@@ -35,12 +35,6 @@ export class Bibliography extends HTMLElement {
observer.observe(this, options);
}
connectedCallback() {
requestAnimationFrame(() => {
this.parseIfPossible();
});
}
parseIfPossible() {
const scriptTag = this.querySelector('script');
if (!scriptTag) return;
+2 -1
View File
@@ -2,7 +2,8 @@ import { bibliography_cite } from '../helpers/citation';
const styles = `
d-citation-list {
contain: layout style;
contain: content;
overflow: hidden;
}
d-citation-list .references {
+81 -34
View File
@@ -1,5 +1,6 @@
import { Template } from '../mixins/template';
import { hover_cite, bibliography_cite } from '../helpers/citation';
import { HoverBox } from '../helpers/hover-box';
const T = Template('d-cite', `
<style>
@@ -34,28 +35,31 @@ figcaption .citation-number {
line-height: 1em;
}
d-hover-box {
margin-top: 1.9em;
.container {
position: fixed;
width: 100%;
left: 0;
z-index: 10000;
margin-top: 2em;
}
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
ul li {
padding: 15px 10px 15px 10px;
border-bottom: 1px solid rgba(0,0,0,0.1)
}
ul li:last-of-type {
border-bottom: none;
.dt-hover-box {
margin: 0 auto;
width: 400px;
max-width: 700px;
background-color: #FFF;
opacity: 0.95;
border: 1px solid rgba(0, 0, 0, 0.25);
padding: 8px 16px;
border-radius: 3px;
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
}
</style>
<d-hover-box id="hover-box"></d-hover-box>
<div class="container">
<div id="hover-box" class="dt-hover-box"></div>
</div>
<div id="citation-" class="citation"><slot></slot><span class="citation-number"></span></div>
`);
@@ -64,23 +68,43 @@ 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.hoverBox = this.root.querySelector('d-hover-box');
window.customElements.whenDefined('d-hover-box').then(() => {
this.hoverBox.listen(this);
});
// this.outerSpan.id = `citation-${this.citeId}`;
// this.hoverDiv.id = `dt-cite-hover-box-${this.citeId}`;
// console.log(this, this.hoverDiv, this.outerSpan, this.innerSpan);
this.hoverbox = new HoverBox(this.hoverDiv, this.outerSpan);
}
//TODO This causes an infinite loop on firefox with polyfills.
// This is only needed for interactive editing so no priority.
// disconnectedCallback() {
// const options = { detail: [this, this.keys], bubbles: true };
// const event = new CustomEvent('onCiteKeyRemoved', options);
// document.dispatchEvent(event);
disconnectedCallback() {
const options = { detail: [this, this.keys], bubbles: true };
const event = new CustomEvent('onCiteKeyRemoved', options);
document.dispatchEvent(event);
}
/* 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() {
@@ -114,17 +138,40 @@ export class Cite extends T(HTMLElement) {
return index == -1 ? '?' : index + 1 + '';
});
const textContent = '[' + numberStrings.join(', ') + ']';
if (this.innerSpan) {
this.innerSpan.textContent = textContent;
}
const innerSpan = this.root.querySelector('.citation-number');
innerSpan.textContent = textContent;
}
set entries(entries) {
if (this.hoverBox) {
this.hoverBox.innerHTML = `<ul>
${entries.map(hover_cite).map(html => `<li>${html}</li>`).join('\n')}
</ul>`;
}
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.`)
// }
// }
}
+2 -1
View File
@@ -4,7 +4,8 @@ const T = Template('d-footnote-list', `
<style>
d-footnote-list {
contain: layout style;
contain: content;
overflow: hidden;
}
d-footnote-list > * {
+16 -14
View File
@@ -1,4 +1,5 @@
import { Template } from '../mixins/template.js';
import { HoverBox } from '../helpers/hover-box';
const T = Template('d-footnote', `
<style>
@@ -8,6 +9,7 @@ d-math[block] {
}
:host {
position: relative;
}
sup {
@@ -24,7 +26,7 @@ span {
}
.container {
position: absolute;
position: fixed;
width: 100%;
left: 0;
z-index: 10000;
@@ -32,22 +34,23 @@ span {
.dt-hover-box {
margin: 0 auto;
width: 704px;
max-width: 100vw;
width: 400px;
max-width: 700px;
background-color: #FFF;
opacity: 0.95;
border: 1px solid rgba(0, 0, 0, 0.25);
padding: 8px 16px;
border-radius: 3px;
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
</style>
<d-hover-box>
<slot id="slot"></slot>
</d-hover-box>
<div class="container">
<div id="hover-box" class="dt-hover-box">
<slot id="slot"></slot>
</div>
</div>
<sup>
<span id="fn-" data-hover-ref=""></span>
@@ -76,24 +79,23 @@ export class Footnote extends T(HTMLElement) {
// const slot = this.shadowRoot.querySelector('#slot');
// console.warn(slot.textContent);
// slot.addEventListener('slotchange', this.notify);
this.hoverBox = this.root.querySelector('d-hover-box');
window.customElements.whenDefined('d-hover-box').then(() => {
this.hoverBox.listen(this);
});
// create numeric ID
Footnote.currentFootnoteId += 1;
const IdString = Footnote.currentFootnoteId.toString();
this.root.host.id = 'd-footnote-' + IdString;
// set up hidden hover box
const id = 'dt-fn-hover-box-' + IdString;
this.hoverBox.id = id
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', id);
span.setAttribute('data-hover-ref', div.id);
span.textContent = IdString;
this.hoverbox = new HoverBox(div, span);
}
}
-132
View File
@@ -1,132 +0,0 @@
import { Template } from '../mixins/template.js';
const T = Template('d-hover-box', `
<style>
:host {
position: absolute;
width: 100%;
left: 0;
z-index: 10000;
display: none;
}
.container {
position: relative;
width: 704px;
max-width: 100vw;
margin: 0 auto;
}
.panel {
position: absolute;
font-size: 1rem;
line-height: 1.5em;
top: 0;
left: 0;
width: 100%;
border: 1px solid rgba(0, 0, 0, 0.1);
background-color: rgb(250, 250, 250);
box-shadow: 0 0 7px rgba(0, 0, 0, 0.1);
border-radius: 4px;
box-sizing: border-box;
}
</style>
<div class="container">
<div class="panel">
<slot></slot>
</div>
</div>
`);
export class HoverBox extends T(HTMLElement) {
constructor() {
super();
}
connectedCallback() {
}
listen(element) {
// console.log(element)
this.bindDivEvents(this);
this.bindTriggerEvents(element);
// this.style.display = "block";
}
bindDivEvents(element) {
// For mice, same behavior as hovering on links
element.addEventListener('mouseover', () => {
if (!this.visible) this.showAtNode(element);
this.stopTimeout();
});
element.addEventListener('mouseout', () => {
this.extendTimeout(500);
});
// Don't trigger body touchstart event when touching within box
element.addEventListener('touchstart', (event) => {
event.stopPropagation();
}, {passive: true});
// Close box when touching outside box
document.body.addEventListener('touchstart', () => {
this.hide();
}, {passive: true});
}
bindTriggerEvents(node) {
node.addEventListener('mouseover', () => {
if (!this.visible) {
this.showAtNode(node);
}
this.stopTimeout();
});
node.addEventListener('mouseout', () => {
this.extendTimeout(300);
});
node.addEventListener('touchstart', (event) => {
if (this.visible) {
this.hide();
} else {
this.showAtNode(node);
}
// Don't trigger body touchstart event when touching link
event.stopPropagation();
}, {passive: true});
}
show(position) {
this.visible = true;
this.style.display = 'block';
}
showAtNode(node) {
const bbox = node.getBoundingClientRect();
this.show([bbox.right, bbox.bottom]);
}
hide() {
this.visible = false;
this.style.display = 'none';
this.stopTimeout();
}
stopTimeout() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
extendTimeout(time) {
this.stopTimeout();
this.timeout = setTimeout(() => {
this.hide();
}, time);
}
}
+49 -2
View File
@@ -1,3 +1,50 @@
export class Title extends HTMLElement {
static get is() { return 'd-title'; }
import { Template } from '../mixins/template';
const T = Template('d-title', `
<style>
:host {
padding: 4rem 0 1.5rem;
contain: content;
display: block;
}
::slotted(h1) {
grid-column: text;
font-size: 60px;
font-weight: 600;
line-height: 1.05em;
margin: 0 0 1rem;
}
::slotted(p) {
font-weight: 300;
font-size: 1.5rem;
line-height: 1.2em;
grid-column: text;
}
.status {
margin-top: 0px;
font-size: 12px;
color: #009688;
opacity: 0.8;
grid-column: kicker;
}
.status span {
line-height: 1;
display: inline-block;
padding: 6px 0;
border-bottom: 1px solid #80cbc4;
font-size: 11px;
text-transform: uppercase;
}
</style>
<!-- <div class="status"><span>✓ Peer Reviewed</span></div> -->
<slot></slot>
`);
export class Title extends T(HTMLElement) {
}
+1 -1
View File
@@ -20,7 +20,7 @@ export function renderTOC(element, headings) {
<style>
d-toc {
contain: layout style;
contain: content;
display: block;
}
+6 -13
View File
@@ -6,10 +6,6 @@ import optionalComponents from './transforms/optional-components';
const frontMatter = new FrontMatter();
function domContentLoaded() {
return ['interactive', 'complete'].indexOf(document.readyState) !== -1;
}
export const Controller = {
frontMatter: frontMatter,
@@ -42,7 +38,7 @@ export const Controller = {
citeTag.entries = entries;
},
onCiteKeyChanged() {
onCiteKeyChanged(event) {
// const [citeTag, keys] = event.detail;
// update citations
@@ -75,6 +71,7 @@ export const Controller = {
},
onBibliographyChanged(event) {
console.info('BibliographyChanged');
const citationListTag = document.querySelector('d-citation-list');
const bibliography = event.detail;
@@ -124,7 +121,7 @@ export const Controller = {
}
const prerendered = document.body.hasAttribute('distill-prerendered');
if (!prerendered && domContentLoaded()) {
if (!prerendered) {
optionalComponents(document, frontMatter);
const appendix = document.querySelector('distill-appendix');
@@ -145,22 +142,18 @@ export const Controller = {
},
DOMContentLoaded() {
if (Controller.loaded) {
console.warn('Controller received DOMContentLoaded but was already loaded!');
return;
} else if (!domContentLoaded()) {
console.warn('Controller received DOMContentLoaded before appropriate document.readyState!');
if (Controller.loaded || ['interactive', 'complete'].indexOf(document.readyState) === -1) {
return;
} else {
Controller.loaded = true;
console.log('Runlevel 4: Controller running DOMContentLoaded');
console.log('Controller running DOMContentLoaded')
}
const frontMatterTag = document.querySelector('d-front-matter');
const data = parseFrontmatter(frontMatterTag);
Controller.listeners.onFrontMatterChanged({detail: data});
// Resolving "citations" dependency due to initial DOM load
// console.debug('Resolving "citations" dependency due to initial DOM load.');
frontMatter.citations = collect_citations();
frontMatter.citationsCollected = true;
for (const waitingCallback of Controller.waitingOn.citations.slice()) {
+2 -1
View File
@@ -3,7 +3,8 @@ import { serializeFrontmatterToBibtex } from '../helpers/bibtex';
const styles = `
<style>
distill-appendix {
contain: layout style;
contain: content;
overflow: hidden;
}
distill-appendix .citation {
+1 -1
View File
@@ -7,7 +7,7 @@ const T = Template('distill-footer', `
:host {
color: rgba(255, 255, 255, 0.5);
font-weight: 300;
padding: 2rem 0;
padding: 60px 0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
text-align: left;
+6 -2
View File
@@ -72,14 +72,18 @@ distill-header .nav a {
${logo}
Distill
</a>
<nav class="nav">
<div class="nav">
<a href="/about/">About</a>
<a href="/prize/">Prize</a>
<a href="/journal/">Submit</a>
</nav>
</div>
</div>
`, false);
// <div class="nav">
// <a href="https://github.com/distillpub">GitHub</a>
// <!-- https://twitter.com/distillpub -->
// </div>
export class DistillHeader extends T(HTMLElement) {
+1 -2
View File
@@ -28,7 +28,6 @@ export function serializeFrontmatterToBibtex(frontMatter) {
title = {${frontMatter.title}},
journal = {${frontMatter.journal.title}},
year = {${frontMatter.publishedYear}},
note = {${frontMatter.url}},
doi = {${frontMatter.doi}}
note = {${frontMatter.url}}
}`;
}
+5 -15
View File
@@ -40,7 +40,6 @@ export function inline_cite_long(keys){
}
function author_string(ent, template, sep, finalSep){
if (ent.author == null) { return ''; }
var names = ent.author.split(' and ');
let name_strings = names.map(name => {
name = name.trim();
@@ -115,22 +114,13 @@ function doi_string(ent, new_line){
}
}
function title_string(ent) {
return '<span class="title">' + ent.title + '</span> ';
}
export function bibliography_cite(ent, fancy){
if (ent){
var cite = title_string(ent);
var cite = '<span class="title">' + ent.title + '</span> ';
cite += link_string(ent) + '<br>';
if (ent.author) {
cite += author_string(ent, '${L}, ${I}', ', ', ' and ');
if (ent.year || ent.date) {
cite += ', ';
}
}
if (ent.year || ent.date) {
cite += (ent.year || ent.date) + '. ';
cite += author_string(ent, '${L}, ${I}', ', ', ' and ');
if (ent.year || ent.date){
cite += ', ' + (ent.year || ent.date) + '. ';
} else {
cite += '. ';
}
@@ -156,7 +146,7 @@ export function bibliography_cite(ent, fancy){
export function hover_cite(ent){
if (ent){
var cite = '';
cite += '<strong>' + ent.title + '</strong>';
cite += '<b>' + ent.title + '</b>';
cite += link_string(ent);
cite += '<br>';
+109
View File
@@ -0,0 +1,109 @@
function make_hover_css(target_node, pos) {
const pretty = window.innerWidth > 600;
const padding = pretty? 18 : 12;
const outer_padding = pretty ? 18 : 0;
// const bbox = document.querySelector('body').getBoundingClientRect();
const bbox = target_node.offsetParent.getBoundingClientRect();
let left = pos[0] - bbox.left, top = pos[1] - bbox.top;
let width = Math.min(window.innerWidth-2*outer_padding, 648);
left = Math.min(left, window.innerWidth-width-outer_padding);
width = width - 2 * padding;
return (`position: absolute;
background-color: #FFF;
opacity: 0.95;
max-width: ${width}px;
top: ${top}px;
left: ${left}px;
border: 1px solid rgba(0, 0, 0, 0.25);
padding: ${padding}px;
border-radius: ${pretty? 3 : 0}px;
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
z-index: ${1e6};`);
}
export class HoverBox {
constructor(contentHTML, triggerElement) {
this.visible = false;
// div hold teh contents of the box that will become visible
this.div = contentHTML;
this.bindDivEvents(this.div);
// triggerElement holds the element that needs to be hovered etc to show contents
this.triggerElement = triggerElement;
this.bindTriggerEvents(this.triggerElement);
this.hide();
}
bindDivEvents(node) {
// For mice, same behavior as hovering on links
this.div.addEventListener('mouseover', () => {
if (!this.visible) this.showAtNode(node);
this.stopTimeout();
});
this.div.addEventListener('mouseout', () => {
this.extendTimeout(500);
});
// Don't trigger body touchstart event when touching within box
this.div.addEventListener('touchstart', (event) => {
event.stopPropagation();
}, {passive: true});
// Close box when touching outside box
document.body.addEventListener('touchstart', () => {
this.hide();
}, {passive: true});
}
bindTriggerEvents(node) {
node.addEventListener('mouseover', () => {
if (!this.visible) {
this.showAtNode(node);
}
this.stopTimeout();
});
node.addEventListener('mouseout', () => {
this.extendTimeout(500);
});
node.addEventListener('touchstart', (event) => {
if (this.visible) {
this.hide();
} else {
this.showAtNode(node);
}
// Don't trigger body touchstart event when touching link
event.stopPropagation();
}, {passive: true});
}
show(position) {
this.visible = true;
// const css = make_hover_css(this.triggerElement, position);
this.div.setAttribute('style', 'display: block;' );
}
showAtNode(node) {
const bbox = node.getBoundingClientRect();
this.show([bbox.right, bbox.bottom]);
}
hide() {
this.visible = false;
this.div.setAttribute('style', 'display: none;');
this.stopTimeout();
}
stopTimeout() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
extendTimeout(time) {
this.stopTimeout();
this.timeout = setTimeout(() => {
this.hide();
}, time);
}
}
+6 -27
View File
@@ -1,6 +1,5 @@
d-article {
contain: layout style;
overflow-x: hidden;
contain: content;
border-top: 1px solid rgba(0, 0, 0, 0.1);
padding-top: 2rem;
color: rgba(0, 0, 0, 0.8);
@@ -18,7 +17,7 @@ d-article > * {
@media(min-width: 1024px) {
d-article {
font-size: 1.06rem;
font-size: 1rem;
line-height: 1.7em;
}
}
@@ -103,6 +102,7 @@ d-article blockquote {
margin-bottom: 1em;
margin-left: 0;
margin-right: 0;
-webkit-font-smoothing: antialiased;
}
d-article blockquote {
@@ -132,15 +132,11 @@ d-article ol {
}
d-article li {
margin-bottom: 1em;
margin-bottom: 24px;
margin-left: 0;
padding-left: 0;
}
d-article li:last-child {
margin-bottom: 0;
}
d-article pre {
font-size: 14px;
margin-bottom: 20px;
@@ -176,24 +172,6 @@ d-article section > d-math[block] {
display: block;
}
@media (max-width: 768px) {
d-article > d-code,
d-article section > d-code,
d-article > d-math[block],
d-article section > d-math[block] {
overflow-x: scroll;
-ms-overflow-style: none; // IE 10+
overflow: -moz-scrollbars-none; // Firefox
}
d-article > d-code::-webkit-scrollbar,
d-article section > d-code::-webkit-scrollbar,
d-article > d-math[block]::-webkit-scrollbar,
d-article section > d-math[block]::-webkit-scrollbar {
display: none; // Safari and Chrome
}
}
d-article .citation {
color: #668;
cursor: pointer;
@@ -205,7 +183,8 @@ d-include {
}
d-figure {
contain: layout style;
contain: content;
overflow: hidden;
}
/* KaTeX */
+2 -17
View File
@@ -1,35 +1,20 @@
d-byline {
contain: content;
overflow: hidden;
border-top: 1px solid rgba(0, 0, 0, 0.1);
contain: content;
font-size: 0.8rem;
line-height: 1.8em;
padding: 1.5rem 0;
min-height: 1.8em;
}
d-byline .byline {
grid-template-columns: 1fr 1fr;
grid-template-columns: 2fr 1fr 1fr;
grid-column: text;
}
@media(min-width: 768px) {
d-byline .byline {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
d-byline .authors-affiliations {
grid-column-end: span 2;
grid-template-columns: 1fr 1fr;
margin-bottom: 1em;
}
@media(min-width: 768px) {
d-byline .authors-affiliations {
margin-bottom: 0;
}
}
d-byline h3 {
-49
View File
@@ -1,49 +0,0 @@
d-title {
padding: 2rem 0 1.5rem;
contain: layout style;
overflow-x: hidden;
}
@media(min-width: 768px) {
d-title {
padding: 4rem 0 1.5rem;
}
}
d-title h1 {
grid-column: text;
font-size: 40px;
font-weight: 700;
line-height: 1.1em;
margin: 0 0 0.5rem;
}
@media(min-width: 768px) {
d-title h1 {
font-size: 50px;
}
}
d-title p {
font-weight: 300;
font-size: 1.2rem;
line-height: 1.55em;
grid-column: text;
}
d-title .status {
margin-top: 0px;
font-size: 12px;
color: #009688;
opacity: 0.8;
grid-column: kicker;
}
d-title .status span {
line-height: 1;
display: inline-block;
padding: 6px 0;
border-bottom: 1px solid #80cbc4;
font-size: 11px;
text-transform: uppercase;
}
+5 -14
View File
@@ -1,5 +1,5 @@
html {
font-size: 14px;
font-size: 16px;
line-height: 1.6em;
/* font-family: "Libre Franklin", "Helvetica Neue", sans-serif; */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif;
@@ -9,12 +9,6 @@ html {
-webkit-text-size-adjust: 100%;
}
@media(min-width: 768px) {
html {
font-size: 16px;
}
}
body {
margin: 0;
}
@@ -90,7 +84,7 @@ sub {
figure {
position: relative;
margin-bottom: 2.5em;
margin-top: 1.5em;
margin-top: 2.5em;
}
figcaption+figure {
@@ -105,16 +99,14 @@ figure svg text,
figure svg tspan {
}
figcaption,
.figcaption {
figcaption {
color: rgba(0, 0, 0, 0.6);
font-size: 12px;
line-height: 1.5em;
}
@media(min-width: 1024px) {
figcaption,
.figcaption {
figcaption {
font-size: 13px;
}
}
@@ -131,8 +123,7 @@ figcaption a {
color: rgba(0, 0, 0, 0.6);
}
figcaption b,
figcaption strong, {
figcaption b {
font-weight: 600;
color: rgba(0, 0, 0, 1.0);
}
+1 -2
View File
@@ -3,10 +3,9 @@ import layout from './styles-layout.css';
import print from './styles-print.css';
import byline from './d-byline.css';
import article from './d-article.css';
import title from './d-title.css';
import math from './d-math.css';
export const styles = base + layout + title + byline + article + math + print;
export const styles = base + layout + byline + article + math + print;
export function makeStyleTag(dom) {
-1
View File
@@ -95,7 +95,6 @@ export default function(dom, data) {
}
function author_string(ent, template, sep, finalSep){
if (ent.author == null) { return ''; }
var names = ent.author.split(' and ');
let name_strings = names.map(name => {
name = name.trim();
-5
View File
@@ -37,11 +37,6 @@ export default function(dom, data) {
<meta property="description" itemprop="description" content="${escape(data.description)}" />
<meta property="article:published" itemprop="datePublished" content="${data.publishedISODateOnly}" />
<meta property="article:created" itemprop="dateCreated" content="${data.publishedISODateOnly}" />
`);
}
if (data.updatedDate) {
appendHead(`
<meta property="article:modified" itemprop="dateModified" content="${data.updatedDate.toISOString()}" />
`);
}
+36 -67
View File
@@ -1,78 +1,47 @@
const webcomponentPath = 'https://distill.pub/third-party/polyfills/webcomponents-lite.js';
const intersectionObserverPath = 'https://distill.pub/third-party/polyfills/intersection-observer.js';
// const template = `
// if ('IntersectionObserver' in window &&
// 'IntersectionObserverEntry' in window &&
// 'intersectionRatio' in IntersectionObserverEntry.prototype) {
// // Platform supports IntersectionObserver natively! :-)
// if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
// Object.defineProperty(IntersectionObserverEntry.prototype,
// 'isIntersecting', {
// get: function () {
// return this.intersectionRatio > 0;
// }
// });
// }
// } else {
// // Platform does not support webcomponents--loading polyfills synchronously.
// const scriptTag = document.createElement('script');
// scriptTag.src = '${intersectionObserverPath}';
// scriptTag.async = false;
// document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
// }
//
// if ('registerElement' in document &&
// 'import' in document.createElement('link') &&
// 'content' in document.createElement('template')) {
// // Platform supports webcomponents natively! :-)
// } else {
// // Platform does not support webcomponents--loading polyfills synchronously.
// const scriptTag = document.createElement('script');
// scriptTag.src = '${webcomponentPath}';
// scriptTag.async = false;
// document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
// }
//
//
// `;
const template = `
if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window &&
'intersectionRatio' in IntersectionObserverEntry.prototype) {
// Platform supports IntersectionObserver natively! :-)
if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
Object.defineProperty(IntersectionObserverEntry.prototype,
'isIntersecting', {
get: function () {
return this.intersectionRatio > 0;
}
});
}
} else {
// Platform does not support webcomponents--loading polyfills synchronously.
const scriptTag = document.createElement('script');
scriptTag.src = '${intersectionObserverPath}';
scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
}
const addBackIn = `
window.addEventListener('WebComponentsReady', function() {
console.warn('WebComponentsReady');
const loaderTag = document.createElement('script');
loaderTag.src = 'https://distill.pub/template.v2.js';
document.head.insertBefore(loaderTag, document.head.firstChild);
});
if ('registerElement' in document &&
'import' in document.createElement('link') &&
'content' in document.createElement('template')) {
// Platform supports webcomponents natively! :-)
} else {
// Platform does not support webcomponents--loading polyfills synchronously.
const scriptTag = document.createElement('script');
scriptTag.src = '${webcomponentPath}';
scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
}
`;
export default function render(dom) {
// pull out template script tag
const templateTag = dom.querySelector('script[src*="template.v2.js"]');
if (templateTag) {
templateTag.parentNode.removeChild(templateTag);
} else {
console.info('FYI: Did not find template tag when trying to remove it. You may not have added it. Be aware that our polyfills will add it.')
}
// add loader
const loaderTag = dom.createElement('script');
loaderTag.src = 'https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.17/webcomponents-loader.js';
dom.head.insertBefore(loaderTag, dom.head.firstChild);
// add loader event listener to add tempalrte back in
const addTag = dom.createElement('script');
addTag.innerHTML = addBackIn;
dom.head.insertBefore(addTag, dom.head.firstChild);
// create polyfill script tag
// const polyfillScriptTag = dom.createElement('script');
// polyfillScriptTag.innerHTML = template;
// polyfillScriptTag.id = 'polyfills';
const polyfillScriptTag = dom.createElement('script');
polyfillScriptTag.innerHTML = template;
polyfillScriptTag.id = 'polyfills';
// insert at appropriate position--before any other script tag
// const firstScriptTag = dom.head.querySelector('script');
// dom.head.insertBefore(polyfillScriptTag, firstScriptTag);
const firstScriptTag = dom.head.querySelector('script');
dom.head.insertBefore(polyfillScriptTag, firstScriptTag);
}
+87 -86
View File
@@ -2,7 +2,8 @@ import { Template } from '../mixins/template';
import { scaleLinear } from 'd3-scale';
import { range } from 'd3-array';
import { drag } from 'd3-drag';
import { select, event as currentEvent } from 'd3-selection';
import { select } from 'd3-selection';
import {event as currentEvent } from 'd3-selection';
const T = Template('d-slider', `
<style>
@@ -90,14 +91,14 @@ const T = Template('d-slider', `
</style>
<div class='background'>
<div class='track'></div>
<div class='track-fill'></div>
<div class='knob-container'>
<div class='knob-highlight'></div>
<div class='knob'></div>
<div class="background">
<div class="track"></div>
<div class="track-fill"></div>
<div class="knob-container">
<div class="knob-highlight"></div>
<div class="knob"></div>
</div>
<div class='ticks'></div>
<div class="ticks"></div>
</div>
`);
@@ -121,18 +122,18 @@ export class Slider extends T(HTMLElement) {
connectedCallback() {
this.connected = true;
this.setAttribute('role', 'slider');
this.setAttribute("role", "slider");
// Makes the element tab-able.
if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', 0); }
if (!this.hasAttribute("tabindex")) { this.setAttribute("tabindex", 0); }
// Keeps track of keyboard vs. mouse interactions for focus rings
this.mouseEvent = false;
// Handles to shadow DOM elements
this.knob = this.root.querySelector('.knob-container');
this.background = this.root.querySelector('.background');
this.trackFill = this.root.querySelector('.track-fill');
this.track = this.root.querySelector('.track');
this.knob = this.root.querySelector(".knob-container");
this.background = this.root.querySelector(".background");
this.trackFill = this.root.querySelector(".track-fill");
this.track = this.root.querySelector(".track");
// Default values for attributes
this.min = this.min ? this.min : 0;
@@ -147,110 +148,109 @@ export class Slider extends T(HTMLElement) {
this.renderTicks();
this.drag = drag()
.container(this.background)
.on('start', () => {
.container(this.track)
.on("start", () => {
this.mouseEvent = true;
this.background.classList.add('mousedown');
this.background.classList.add("mousedown");
this.changeValue = this.value;
this.dragUpdate();
})
.on('drag', () => {
.on("drag", () => {
this.dragUpdate();
})
.on('end', () => {
.on("end", () => {
this.mouseEvent = false;
this.background.classList.remove('mousedown');
this.background.classList.remove("mousedown");
this.dragUpdate();
if (this.changeValue !== this.value) this.dispatchChange();
this.changeValue = this.value;
});
this.drag(select(this.background));
this.addEventListener('focusin', () => {
this.addEventListener("focusin", (e) => {
if(!this.mouseEvent) {
this.background.classList.add('focus');
this.background.classList.add("focus");
}
});
this.addEventListener('focusout', () => {
this.background.classList.remove('focus');
this.addEventListener("focusout", (e) => {
this.background.classList.remove("focus");
});
this.addEventListener('keydown', this.onKeyDown);
this.addEventListener("keydown", this.onKeyDown);
}
static get observedAttributes() {return ['min', 'max', 'value', 'step', 'ticks', 'origin', 'tickValues', 'tickLabels']; }
static get observedAttributes() {return ["min", "max", "value", "step", "ticks", "origin", "tickValues", "tickLabels"]; }
attributeChangedCallback(attr, oldValue, newValue) {
if (isNaN(newValue) || newValue === undefined || newValue === null) return;
if (attr == 'min') {
if (attr == "min") {
this.min = +newValue;
this.setAttribute('aria-valuemin', this.min);
this.setAttribute("aria-valuemin", this.min);
}
if (attr == 'max') {
if (attr == "max") {
this.max = +newValue;
this.setAttribute('aria-valuemax', this.max);
this.setAttribute("aria-valuemax", this.max);
}
if (attr == 'value') {
if (attr == "value") {
this.update(+newValue);
}
if (attr == 'origin') {
if (attr == "origin") {
this.origin = +newValue;
// this.update(this.value);
this.update(this.value);
}
if (attr == 'step') {
if (attr == "step") {
if (newValue > 0) {
this.step = +newValue;
}
}
if (attr == 'ticks') {
this.ticks = (newValue === '' ? true : newValue);
if (attr == "ticks") {
this.ticks = (newValue === "" ? true : newValue);
}
}
onKeyDown(event) {
onKeyDown(e) {
this.changeValue = this.value;
let stopPropagation = false;
switch (event.keyCode) {
case keyCodes.left:
case keyCodes.down:
this.update(this.value - this.step);
stopPropagation = true;
break;
case keyCodes.right:
case keyCodes.up:
this.update(this.value + this.step);
stopPropagation = true;
break;
case keyCodes.pageUp:
this.update(this.value + this.step * 10);
stopPropagation = true;
break;
case keyCodes.left:
case keyCodes.down:
this.update(this.value - this.step)
stopPropagation = true;
break;
case keyCodes.right:
case keyCodes.up:
this.update(this.value + this.step)
stopPropagation = true;
break;
case keyCodes.pageUp:
this.update(this.value + this.step * 10)
stopPropagation = true;
break;
case keyCodes.pageDown:
this.update(this.value + this.step * 10);
stopPropagation = true;
break;
case keyCodes.home:
this.update(this.min);
stopPropagation = true;
break;
case keyCodes.end:
this.update(this.max);
stopPropagation = true;
break;
default:
break;
case keyCodes.pageDown:
this.update(this.value + this.step * 10)
stopPropagation = true;
break;
case keyCodes.home:
this.update(this.min);
stopPropagation = true;
break;
case keyCodes.end:
this.update(this.max);
stopPropagation = true;
break;
default:
break;
}
if (stopPropagation) {
this.background.classList.add('focus');
event.preventDefault();
event.stopPropagation();
this.background.classList.add("focus");
e.preventDefault();
e.stopPropagation();
if (this.changeValue !== this.value) this.dispatchChange();
}
}
validateValueRange(min, max, value) {
return Math.max(Math.min(max, value), min);
return Math.max(Math.min(max, value), min)
}
quantizeValue(value, step) {
@@ -259,60 +259,61 @@ export class Slider extends T(HTMLElement) {
dragUpdate() {
const bbox = this.background.getBoundingClientRect();
const x = currentEvent.x;
const left = bbox.left;
const x = event.x - left;
const width = bbox.width;
this.update(this.scale.invert(x / width));
}
update(value) {
let v = value;
if (this.step !== 'any') {
if (this.step !== "any") {
v = this.quantizeValue(value, this.step);
}
v = this.validateValueRange(this.min, this.max, v);
if (this.connected) {
this.knob.style.left = this.scale(v) * 100 + '%';
this.trackFill.style.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + '%';
this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + '%';
this.knob.style.left = this.scale(v) * 100 + "%";
this.trackFill.style.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + "%";
this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + "%";
}
if (this.value !== v) {
this.value = v;
this.setAttribute('aria-valuenow', this.value);
this.setAttribute("aria-valuenow", this.value);
this.dispatchInput();
}
}
// Dispatches only on a committed change (basically only on mouseup).
dispatchChange() {
const e = new Event('change');
const e = new Event("change");
this.dispatchEvent(e, {});
}
// Dispatches on each value change.
dispatchInput() {
const e = new Event('input');
const e = new Event("input");
this.dispatchEvent(e, {});
}
renderTicks() {
const ticksContainer = this.root.querySelector('.ticks');
const ticksContainer = this.root.querySelector(".ticks");
if (this.ticks !== false) {
let tickData = [];
if (this.ticks > 0) {
tickData = this.scale.ticks(this.ticks);
} else if (this.step === 'any') {
} else if (this.step === "any") {
tickData = this.scale.ticks();
} else {
tickData = range(this.min, this.max + 1e-6, this.step);
}
tickData.forEach(d => {
const tick = document.createElement('div');
tick.classList.add('tick');
tick.style.left = this.scale(d) * 100 + '%';
ticksContainer.appendChild(tick);
const tick = document.createElement("div");
tick.classList.add("tick");
tick.style.left = this.scale(d) * 100 + "%";
ticksContainer.appendChild(tick)
});
} else {
ticksContainer.style.display = 'none';
ticksContainer.style.display = "none";
}
}
}
}