Compare commits

...

13 Commits

Author SHA1 Message Date
Ludwig Schubert ecce53f1a2 2.2.4 2017-10-24 16:51:24 -07:00
Ludwig Schubert f355ff6894 ONly remove script tag if we find it in polyfills 2017-10-24 16:51:17 -07:00
Ludwig Schubert f388c39553 WIP switch to webcomponents loader async polyfills; multiple small fixes for Firefox and generally more defensive coding 2017-10-24 16:48:48 -07:00
Ludwig Schubert 11b00b4cee Merge branch 'v2' of github.com:distillpub/template into v2 2017-10-24 15:35:46 -07:00
Ludwig Schubert 302370c1cf Switch travis away from yarn, add running test to CI 2017-10-24 15:35:40 -07:00
Shan Carter b8d26a4dac Fixing nasty firefox/polyfill bug 2017-10-24 15:33:37 -07:00
Ludwig Schubert 00076d3123 Merge branch 'v2' of github.com:distillpub/template into v2 2017-10-24 14:05:40 -07:00
Shan Carter 94bba88924 Adding hover box element 2017-10-24 13:59:48 -07:00
Shan Carter 4c9c387760 Fixing hoverbox bug on safari 2017-10-24 11:35:13 -07:00
Shan Carter 33714c9ca4 Tweaking mobile styles 2017-10-24 10:57:05 -07:00
Shan Carter a43db020b1 Article style tweaks 2017-10-24 09:31:37 -07:00
Ludwig Schubert bc68238be9 2.2.3 2017-10-23 15:59:59 -07:00
Ludwig Schubert d01e7e9317 Trigger release 2017-10-23 15:57:06 -07:00
22 changed files with 431 additions and 394 deletions
+2 -2
View File
@@ -2,11 +2,11 @@ language: node_js
node_js: node_js:
- "node" # latest version - "node" # latest version
cache: cache:
yarn: true
directories: directories:
- node_modules - node_modules
script: script:
- yarn build - npm run build
- npm test
deploy: deploy:
provider: releases provider: releases
api_key: $GITHUB_OAUTH_TOKEN api_key: $GITHUB_OAUTH_TOKEN
+3
View File
@@ -2,9 +2,12 @@
<head> <head>
<script src="../dist/template.v2.js"></script> <script src="../dist/template.v2.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" >
<meta charset="utf8">
</head> </head>
<body> <body>
<distill-header></distill-header>
<d-front-matter> <d-front-matter>
<script id='distill-front-matter' type="text/json">{ <script id='distill-front-matter' type="text/json">{
"title": "Why Momentum Really Works", "title": "Why Momentum Really Works",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "distill-template", "name": "distill-template",
"version": "2.2.2", "version": "2.2.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "distill-template", "name": "distill-template",
"version": "2.2.2", "version": "2.2.4",
"description": "Template for creating Distill articles.", "description": "Template for creating Distill articles.",
"main": "dist/template.v2.js", "main": "dist/template.v2.js",
"bin": { "bin": {
+2 -1
View File
@@ -16,6 +16,7 @@ import { Code } from './components/d-code';
import { Footnote } from './components/d-footnote'; import { Footnote } from './components/d-footnote';
import { FootnoteList } from './components/d-footnote-list'; import { FootnoteList } from './components/d-footnote-list';
import { FrontMatter } from './components/d-front-matter'; import { FrontMatter } from './components/d-front-matter';
import { HoverBox } from './components/d-hover-box';
import { Title } from './components/d-title'; import { Title } from './components/d-title';
import { DMath } from './components/d-math'; import { DMath } from './components/d-math';
import { References } from './components/d-references'; import { References } from './components/d-references';
@@ -53,7 +54,7 @@ const distillMain = function() {
/* Article will register controller which takes control from there */ /* Article will register controller which takes control from there */
const components = [ const components = [
Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code, Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code,
Footnote, FootnoteList, FrontMatter, Title, DMath, References, TOC, Figure, Footnote, FootnoteList, FrontMatter, HoverBox, Title, DMath, References, TOC, Figure,
Slider, Interstitial Slider, Interstitial
]; ];
+2 -3
View File
@@ -1,6 +1,5 @@
import { Template } from '../mixins/template'; // import { Template } from '../mixins/template';
import { Controller } from '../controller'; import { Controller } from '../controller';
import style from '../styles/d-article.css';
const isOnlyWhitespace = /^\s*$/; const isOnlyWhitespace = /^\s*$/;
@@ -32,7 +31,7 @@ export class Article extends HTMLElement {
connectedCallback() { connectedCallback() {
document.onreadystatechange = function () { document.onreadystatechange = function () {
console.log("onreadystatechange:"); console.log('onreadystatechange:');
console.log(document.readyState); console.log(document.readyState);
}; };
console.info('Article tag connected, we can now listen to controller events.'); console.info('Article tag connected, we can now listen to controller events.');
+6
View File
@@ -35,6 +35,12 @@ export class Bibliography extends HTMLElement {
observer.observe(this, options); observer.observe(this, options);
} }
connectedCallback() {
requestAnimationFrame(() => {
this.parseIfPossible();
});
}
parseIfPossible() { parseIfPossible() {
const scriptTag = this.querySelector('script'); const scriptTag = this.querySelector('script');
if (!scriptTag) return; if (!scriptTag) return;
+19 -83
View File
@@ -1,6 +1,5 @@
import { Template } from '../mixins/template'; import { Template } from '../mixins/template';
import { hover_cite, bibliography_cite } from '../helpers/citation'; import { hover_cite, bibliography_cite } from '../helpers/citation';
import { HoverBox } from '../helpers/hover-box';
const T = Template('d-cite', ` const T = Template('d-cite', `
<style> <style>
@@ -35,31 +34,13 @@ figcaption .citation-number {
line-height: 1em; line-height: 1em;
} }
.container { d-hover-box {
position: fixed; margin-top: 1.9em;
width: 100%;
left: 0;
z-index: 10000;
margin-top: 2em;
}
.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> </style>
<div class="container"> <d-hover-box id="hover-box"></d-hover-box>
<div id="hover-box" class="dt-hover-box"></div>
</div>
<div id="citation-" class="citation"><slot></slot><span class="citation-number"></span></div> <div id="citation-" class="citation"><slot></slot><span class="citation-number"></span></div>
`); `);
@@ -68,43 +49,23 @@ export class Cite extends T(HTMLElement) {
/* Lifecycle */ /* Lifecycle */
// constructor() {
// super();
// // Cite.currentId += 1;
// // this.citeId = Cite.currentId;
// }
connectedCallback() { connectedCallback() {
// this.notify();
this.hoverDiv = this.root.querySelector('.dt-hover-box');
this.outerSpan = this.root.querySelector('#citation-'); this.outerSpan = this.root.querySelector('#citation-');
this.innerSpan = this.root.querySelector('.citation-number'); this.innerSpan = this.root.querySelector('.citation-number');
// this.outerSpan.id = `citation-${this.citeId}`; this.hoverBox = this.root.querySelector('d-hover-box');
// this.hoverDiv.id = `dt-cite-hover-box-${this.citeId}`; window.customElements.whenDefined('d-hover-box').then(() => {
// console.log(this, this.hoverDiv, this.outerSpan, this.innerSpan); this.hoverBox.listen(this);
this.hoverbox = new HoverBox(this.hoverDiv, this.outerSpan); });
} }
disconnectedCallback() { //TODO This causes an infinite loop on firefox with polyfills.
const options = { detail: [this, this.keys], bubbles: true }; // This is only needed for interactive editing so no priority.
const event = new CustomEvent('onCiteKeyRemoved', options); // disconnectedCallback() {
document.dispatchEvent(event); // 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 */ /* observe 'key' attribute */
static get observedAttributes() { static get observedAttributes() {
@@ -138,40 +99,15 @@ export class Cite extends T(HTMLElement) {
return index == -1 ? '?' : index + 1 + ''; return index == -1 ? '?' : index + 1 + '';
}); });
const textContent = '[' + numberStrings.join(', ') + ']'; const textContent = '[' + numberStrings.join(', ') + ']';
const innerSpan = this.root.querySelector('.citation-number'); if (this.innerSpan) {
innerSpan.textContent = textContent; this.innerSpan.textContent = textContent;
}
} }
set entries(entries) { set entries(entries) {
const div = this.root.querySelector('#hover-box'); if (this.hoverBox) {
div.innerHTML = entries.map(hover_cite).join('<br><br>'); this.hoverBox.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.`)
// }
// }
} }
+14 -16
View File
@@ -1,5 +1,4 @@
import { Template } from '../mixins/template.js'; import { Template } from '../mixins/template.js';
import { HoverBox } from '../helpers/hover-box';
const T = Template('d-footnote', ` const T = Template('d-footnote', `
<style> <style>
@@ -9,7 +8,6 @@ d-math[block] {
} }
:host { :host {
position: relative;
} }
sup { sup {
@@ -26,7 +24,7 @@ span {
} }
.container { .container {
position: fixed; position: absolute;
width: 100%; width: 100%;
left: 0; left: 0;
z-index: 10000; z-index: 10000;
@@ -34,23 +32,22 @@ span {
.dt-hover-box { .dt-hover-box {
margin: 0 auto; margin: 0 auto;
width: 400px; width: 704px;
max-width: 700px; max-width: 100vw;
background-color: #FFF; background-color: #FFF;
opacity: 0.95; opacity: 0.95;
border: 1px solid rgba(0, 0, 0, 0.25); border: 1px solid rgba(0, 0, 0, 0.25);
padding: 8px 16px; padding: 8px 16px;
border-radius: 3px; border-radius: 3px;
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2); box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
} }
</style> </style>
<div class="container"> <d-hover-box>
<div id="hover-box" class="dt-hover-box"> <slot id="slot"></slot>
<slot id="slot"></slot> </d-hover-box>
</div>
</div>
<sup> <sup>
<span id="fn-" data-hover-ref=""></span> <span id="fn-" data-hover-ref=""></span>
@@ -79,23 +76,24 @@ export class Footnote extends T(HTMLElement) {
// const slot = this.shadowRoot.querySelector('#slot'); // const slot = this.shadowRoot.querySelector('#slot');
// console.warn(slot.textContent); // console.warn(slot.textContent);
// slot.addEventListener('slotchange', this.notify); // 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 // create numeric ID
Footnote.currentFootnoteId += 1; Footnote.currentFootnoteId += 1;
const IdString = Footnote.currentFootnoteId.toString(); const IdString = Footnote.currentFootnoteId.toString();
this.root.host.id = 'd-footnote-' + IdString; this.root.host.id = 'd-footnote-' + IdString;
// set up hidden hover box // set up hidden hover box
const div = this.root.querySelector('.dt-hover-box'); const id = 'dt-fn-hover-box-' + IdString;
div.id = 'dt-fn-hover-box-' + IdString; this.hoverBox.id = id
// set up visible footnote marker // set up visible footnote marker
const span = this.root.querySelector('#fn-'); const span = this.root.querySelector('#fn-');
span.setAttribute('id', 'fn-' + IdString); span.setAttribute('id', 'fn-' + IdString);
span.setAttribute('data-hover-ref', div.id); span.setAttribute('data-hover-ref', id);
span.textContent = IdString; span.textContent = IdString;
this.hoverbox = new HoverBox(div, span);
} }
} }
+132
View File
@@ -0,0 +1,132 @@
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;
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;
padding: 10px;
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);
}
}
+2 -49
View File
@@ -1,50 +1,3 @@
import { Template } from '../mixins/template'; export class Title extends HTMLElement {
static get is() { return 'd-title'; }
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) {
} }
+2 -3
View File
@@ -38,7 +38,7 @@ export const Controller = {
citeTag.entries = entries; citeTag.entries = entries;
}, },
onCiteKeyChanged(event) { onCiteKeyChanged() {
// const [citeTag, keys] = event.detail; // const [citeTag, keys] = event.detail;
// update citations // update citations
@@ -71,7 +71,6 @@ export const Controller = {
}, },
onBibliographyChanged(event) { onBibliographyChanged(event) {
console.info('BibliographyChanged');
const citationListTag = document.querySelector('d-citation-list'); const citationListTag = document.querySelector('d-citation-list');
const bibliography = event.detail; const bibliography = event.detail;
@@ -146,7 +145,7 @@ export const Controller = {
return; return;
} else { } else {
Controller.loaded = true; Controller.loaded = true;
console.log('Controller running DOMContentLoaded') console.log('Controller running DOMContentLoaded');
} }
const frontMatterTag = document.querySelector('d-front-matter'); const frontMatterTag = document.querySelector('d-front-matter');
+1 -1
View File
@@ -7,7 +7,7 @@ const T = Template('distill-footer', `
:host { :host {
color: rgba(255, 255, 255, 0.5); color: rgba(255, 255, 255, 0.5);
font-weight: 300; font-weight: 300;
padding: 60px 0; padding: 2rem 0;
border-top: 1px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, 0.1);
background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/ background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
text-align: left; text-align: left;
-109
View File
@@ -1,109 +0,0 @@
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);
}
}
+10 -3
View File
@@ -3,6 +3,7 @@ d-article {
border-top: 1px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, 0.1);
padding-top: 2rem; padding-top: 2rem;
color: rgba(0, 0, 0, 0.8); color: rgba(0, 0, 0, 0.8);
overflow: hidden;
} }
d-article > * { d-article > * {
@@ -17,7 +18,7 @@ d-article > * {
@media(min-width: 1024px) { @media(min-width: 1024px) {
d-article { d-article {
font-size: 1rem; font-size: 1.06rem;
line-height: 1.7em; line-height: 1.7em;
} }
} }
@@ -102,7 +103,6 @@ d-article blockquote {
margin-bottom: 1em; margin-bottom: 1em;
margin-left: 0; margin-left: 0;
margin-right: 0; margin-right: 0;
-webkit-font-smoothing: antialiased;
} }
d-article blockquote { d-article blockquote {
@@ -132,11 +132,15 @@ d-article ol {
} }
d-article li { d-article li {
margin-bottom: 24px; margin-bottom: 1em;
margin-left: 0; margin-left: 0;
padding-left: 0; padding-left: 0;
} }
d-article li:last-child {
margin-bottom: 0;
}
d-article pre { d-article pre {
font-size: 14px; font-size: 14px;
margin-bottom: 20px; margin-bottom: 20px;
@@ -165,11 +169,14 @@ d-article span.equation-mimic {
d-article > d-code, d-article > d-code,
d-article section > d-code { d-article section > d-code {
display: block; display: block;
overflow-x: scroll;
} }
d-article > d-math[block], d-article > d-math[block],
d-article section > d-math[block] { d-article section > d-math[block] {
display: block; display: block;
overflow-x: scroll;
} }
d-article .citation { d-article .citation {
+17 -3
View File
@@ -7,14 +7,28 @@ d-byline {
min-height: 1.8em; min-height: 1.8em;
} }
d-byline .byline { d-byline .byline {
grid-template-columns: 2fr 1fr 1fr; grid-template-columns: 1fr 1fr;
grid-column: text; grid-column: text;
} }
d-byline .authors-affiliations { @media(min-width: 768px) {
grid-template-columns: 1fr 1fr; 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 { d-byline h3 {
+55
View File
@@ -0,0 +1,55 @@
d-title {
padding: 2rem 0 1.5rem;
contain: content;
overflow: 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.05em;
margin: 0 0 1rem;
}
@media(min-width: 768px) {
d-title h1 {
font-size: 60px;
}
}
d-title p {
font-weight: 300;
font-size: 1.2rem;
line-height: 1.7em;
grid-column: text;
}
@media(min-width: 768px) {
d-title p {
font-size: 1.5rem;
}
}
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;
}
+7 -1
View File
@@ -1,5 +1,5 @@
html { html {
font-size: 16px; font-size: 14px;
line-height: 1.6em; line-height: 1.6em;
/* font-family: "Libre Franklin", "Helvetica Neue", sans-serif; */ /* 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; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif;
@@ -9,6 +9,12 @@ html {
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
} }
@media(min-width: 768px) {
html {
font-size: 16px;
}
}
body { body {
margin: 0; margin: 0;
} }
+2 -1
View File
@@ -3,9 +3,10 @@ import layout from './styles-layout.css';
import print from './styles-print.css'; import print from './styles-print.css';
import byline from './d-byline.css'; import byline from './d-byline.css';
import article from './d-article.css'; import article from './d-article.css';
import title from './d-title.css';
import math from './d-math.css'; import math from './d-math.css';
export const styles = base + layout + byline + article + math + print; export const styles = base + layout + title + byline + article + math + print;
export function makeStyleTag(dom) { export function makeStyleTag(dom) {
+5
View File
@@ -37,6 +37,11 @@ export default function(dom, data) {
<meta property="description" itemprop="description" content="${escape(data.description)}" /> <meta property="description" itemprop="description" content="${escape(data.description)}" />
<meta property="article:published" itemprop="datePublished" content="${data.publishedISODateOnly}" /> <meta property="article:published" itemprop="datePublished" content="${data.publishedISODateOnly}" />
<meta property="article:created" itemprop="dateCreated" 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()}" /> <meta property="article:modified" itemprop="dateModified" content="${data.updatedDate.toISOString()}" />
`); `);
} }
+67 -36
View File
@@ -1,47 +1,78 @@
const webcomponentPath = 'https://distill.pub/third-party/polyfills/webcomponents-lite.js'; const webcomponentPath = 'https://distill.pub/third-party/polyfills/webcomponents-lite.js';
const intersectionObserverPath = 'https://distill.pub/third-party/polyfills/intersection-observer.js'; const intersectionObserverPath = 'https://distill.pub/third-party/polyfills/intersection-observer.js';
const template = ` // const template = `
if ('IntersectionObserver' in window && // if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window && // 'IntersectionObserverEntry' in window &&
'intersectionRatio' in IntersectionObserverEntry.prototype) { // 'intersectionRatio' in IntersectionObserverEntry.prototype) {
// Platform supports IntersectionObserver natively! :-) // // Platform supports IntersectionObserver natively! :-)
if (!('isIntersecting' in IntersectionObserverEntry.prototype)) { // if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
Object.defineProperty(IntersectionObserverEntry.prototype, // Object.defineProperty(IntersectionObserverEntry.prototype,
'isIntersecting', { // 'isIntersecting', {
get: function () { // get: function () {
return this.intersectionRatio > 0; // return this.intersectionRatio > 0;
} // }
}); // });
} // }
} else { // } else {
// Platform does not support webcomponents--loading polyfills synchronously. // // Platform does not support webcomponents--loading polyfills synchronously.
const scriptTag = document.createElement('script'); // const scriptTag = document.createElement('script');
scriptTag.src = '${intersectionObserverPath}'; // scriptTag.src = '${intersectionObserverPath}';
scriptTag.async = false; // scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling); // 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);
// }
//
//
// `;
if ('registerElement' in document &&
'import' in document.createElement('link') && const addBackIn = `
'content' in document.createElement('template')) { window.addEventListener('WebComponentsReady', function() {
// Platform supports webcomponents natively! :-) console.warn('WebComponentsReady');
} else { const loaderTag = document.createElement('script');
// Platform does not support webcomponents--loading polyfills synchronously. loaderTag.src = 'http://localhost:8888/dist/template.v2.js';
const scriptTag = document.createElement('script'); document.head.insertBefore(loaderTag, document.head.firstChild);
scriptTag.src = '${webcomponentPath}'; });
scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
}
`; `;
export default function render(dom) { 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 // create polyfill script tag
const polyfillScriptTag = dom.createElement('script'); // const polyfillScriptTag = dom.createElement('script');
polyfillScriptTag.innerHTML = template; // polyfillScriptTag.innerHTML = template;
polyfillScriptTag.id = 'polyfills'; // polyfillScriptTag.id = 'polyfills';
// insert at appropriate position--before any other script tag // insert at appropriate position--before any other script tag
const firstScriptTag = dom.head.querySelector('script'); // const firstScriptTag = dom.head.querySelector('script');
dom.head.insertBefore(polyfillScriptTag, firstScriptTag); // dom.head.insertBefore(polyfillScriptTag, firstScriptTag);
} }
+81 -81
View File
@@ -90,14 +90,14 @@ const T = Template('d-slider', `
</style> </style>
<div class="background"> <div class='background'>
<div class="track"></div> <div class='track'></div>
<div class="track-fill"></div> <div class='track-fill'></div>
<div class="knob-container"> <div class='knob-container'>
<div class="knob-highlight"></div> <div class='knob-highlight'></div>
<div class="knob"></div> <div class='knob'></div>
</div> </div>
<div class="ticks"></div> <div class='ticks'></div>
</div> </div>
`); `);
@@ -121,18 +121,18 @@ export class Slider extends T(HTMLElement) {
connectedCallback() { connectedCallback() {
this.connected = true; this.connected = true;
this.setAttribute("role", "slider"); this.setAttribute('role', 'slider');
// Makes the element tab-able. // 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 // Keeps track of keyboard vs. mouse interactions for focus rings
this.mouseEvent = false; this.mouseEvent = false;
// Handles to shadow DOM elements // Handles to shadow DOM elements
this.knob = this.root.querySelector(".knob-container"); this.knob = this.root.querySelector('.knob-container');
this.background = this.root.querySelector(".background"); this.background = this.root.querySelector('.background');
this.trackFill = this.root.querySelector(".track-fill"); this.trackFill = this.root.querySelector('.track-fill');
this.track = this.root.querySelector(".track"); this.track = this.root.querySelector('.track');
// Default values for attributes // Default values for attributes
this.min = this.min ? this.min : 0; this.min = this.min ? this.min : 0;
@@ -148,108 +148,108 @@ export class Slider extends T(HTMLElement) {
this.drag = drag() this.drag = drag()
.container(this.background) .container(this.background)
.on("start", () => { .on('start', () => {
this.mouseEvent = true; this.mouseEvent = true;
this.background.classList.add("mousedown"); this.background.classList.add('mousedown');
this.changeValue = this.value; this.changeValue = this.value;
this.dragUpdate(); this.dragUpdate();
}) })
.on("drag", () => { .on('drag', () => {
this.dragUpdate(); this.dragUpdate();
}) })
.on("end", () => { .on('end', () => {
this.mouseEvent = false; this.mouseEvent = false;
this.background.classList.remove("mousedown"); this.background.classList.remove('mousedown');
this.dragUpdate(); this.dragUpdate();
if (this.changeValue !== this.value) this.dispatchChange(); if (this.changeValue !== this.value) this.dispatchChange();
this.changeValue = this.value; this.changeValue = this.value;
}); });
this.drag(select(this.background)); this.drag(select(this.background));
this.addEventListener("focusin", (e) => { this.addEventListener('focusin', () => {
if(!this.mouseEvent) { if(!this.mouseEvent) {
this.background.classList.add("focus"); this.background.classList.add('focus');
} }
}); });
this.addEventListener("focusout", (e) => { this.addEventListener('focusout', () => {
this.background.classList.remove("focus"); 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) { attributeChangedCallback(attr, oldValue, newValue) {
if (attr == "min") { if (attr == 'min') {
this.min = +newValue; 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.max = +newValue;
this.setAttribute("aria-valuemax", this.max); this.setAttribute('aria-valuemax', this.max);
} }
if (attr == "value") { if (attr == 'value') {
this.update(+newValue); this.update(+newValue);
} }
if (attr == "origin") { if (attr == 'origin') {
this.origin = +newValue; this.origin = +newValue;
this.update(this.value); this.update(this.value);
} }
if (attr == "step") { if (attr == 'step') {
if (newValue > 0) { if (newValue > 0) {
this.step = +newValue; this.step = +newValue;
} }
} }
if (attr == "ticks") { if (attr == 'ticks') {
this.ticks = (newValue === "" ? true : newValue); this.ticks = (newValue === '' ? true : newValue);
} }
} }
onKeyDown(e) { onKeyDown(event) {
this.changeValue = this.value; this.changeValue = this.value;
let stopPropagation = false; let stopPropagation = false;
switch (event.keyCode) { switch (event.keyCode) {
case keyCodes.left: case keyCodes.left:
case keyCodes.down: case keyCodes.down:
this.update(this.value - this.step) this.update(this.value - this.step);
stopPropagation = true; stopPropagation = true;
break; break;
case keyCodes.right: case keyCodes.right:
case keyCodes.up: case keyCodes.up:
this.update(this.value + this.step) this.update(this.value + this.step);
stopPropagation = true; stopPropagation = true;
break; break;
case keyCodes.pageUp: case keyCodes.pageUp:
this.update(this.value + this.step * 10) this.update(this.value + this.step * 10);
stopPropagation = true; stopPropagation = true;
break; break;
case keyCodes.pageDown: case keyCodes.pageDown:
this.update(this.value + this.step * 10) this.update(this.value + this.step * 10);
stopPropagation = true; stopPropagation = true;
break; break;
case keyCodes.home: case keyCodes.home:
this.update(this.min); this.update(this.min);
stopPropagation = true; stopPropagation = true;
break; break;
case keyCodes.end: case keyCodes.end:
this.update(this.max); this.update(this.max);
stopPropagation = true; stopPropagation = true;
break; break;
default: default:
break; break;
} }
if (stopPropagation) { if (stopPropagation) {
this.background.classList.add("focus"); this.background.classList.add('focus');
e.preventDefault(); event.preventDefault();
e.stopPropagation(); event.stopPropagation();
if (this.changeValue !== this.value) this.dispatchChange(); if (this.changeValue !== this.value) this.dispatchChange();
} }
} }
validateValueRange(min, max, value) { validateValueRange(min, max, value) {
return Math.max(Math.min(max, value), min) return Math.max(Math.min(max, value), min);
} }
quantizeValue(value, step) { quantizeValue(value, step) {
@@ -265,53 +265,53 @@ export class Slider extends T(HTMLElement) {
update(value) { update(value) {
let v = value; let v = value;
if (this.step !== "any") { if (this.step !== 'any') {
v = this.quantizeValue(value, this.step); v = this.quantizeValue(value, this.step);
} }
v = this.validateValueRange(this.min, this.max, v); v = this.validateValueRange(this.min, this.max, v);
if (this.connected) { if (this.connected) {
this.knob.style.left = this.scale(v) * 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.width = this.scale(this.min + Math.abs(v - this.origin)) * 100 + '%';
this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + "%"; this.trackFill.style.left = this.scale(Math.min(v, this.origin)) * 100 + '%';
} }
if (this.value !== v) { if (this.value !== v) {
this.value = v; this.value = v;
this.setAttribute("aria-valuenow", this.value); this.setAttribute('aria-valuenow', this.value);
this.dispatchInput(); this.dispatchInput();
} }
} }
// Dispatches only on a committed change (basically only on mouseup). // Dispatches only on a committed change (basically only on mouseup).
dispatchChange() { dispatchChange() {
const e = new Event("change"); const e = new Event('change');
this.dispatchEvent(e, {}); this.dispatchEvent(e, {});
} }
// Dispatches on each value change. // Dispatches on each value change.
dispatchInput() { dispatchInput() {
const e = new Event("input"); const e = new Event('input');
this.dispatchEvent(e, {}); this.dispatchEvent(e, {});
} }
renderTicks() { renderTicks() {
const ticksContainer = this.root.querySelector(".ticks"); const ticksContainer = this.root.querySelector('.ticks');
if (this.ticks !== false) { if (this.ticks !== false) {
let tickData = []; let tickData = [];
if (this.ticks > 0) { if (this.ticks > 0) {
tickData = this.scale.ticks(this.ticks); tickData = this.scale.ticks(this.ticks);
} else if (this.step === "any") { } else if (this.step === 'any') {
tickData = this.scale.ticks(); tickData = this.scale.ticks();
} else { } else {
tickData = range(this.min, this.max + 1e-6, this.step); tickData = range(this.min, this.max + 1e-6, this.step);
} }
tickData.forEach(d => { tickData.forEach(d => {
const tick = document.createElement("div"); const tick = document.createElement('div');
tick.classList.add("tick"); tick.classList.add('tick');
tick.style.left = this.scale(d) * 100 + "%"; tick.style.left = this.scale(d) * 100 + '%';
ticksContainer.appendChild(tick) ticksContainer.appendChild(tick);
}); });
} else { } else {
ticksContainer.style.display = "none"; ticksContainer.style.display = 'none';
} }
} }
} }