Compare commits

..

1 Commits

Author SHA1 Message Date
Shan Carter ab8ab149e6 Moving headers in appendix to text column 2018-12-27 11:44:47 -08:00
28 changed files with 2044 additions and 2612 deletions
+44 -1
View File
@@ -1 +1,44 @@
.DS_Store # Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
bower_components
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# Copied fonts
examples/fonts
dist
article-rendered.html
# dependency graph
rollup-grapher.html
+1 -1
View File
@@ -11,7 +11,7 @@ To contribute a change, [check out the contributing guide](CONTRIBUTING.md).
### Local Development ### Local Development
First, run `npm install` to install all node modules required. Then, run `npm run dev` to start a watching build rollup server. To view the sample pages in the repo, you can run `npm run serve` as a separate process which starts a static server. `npm run build` will run a one-time build. Run `npm run start` to start a watching build rollup server. To view the sample pages in the repo, you can run `npm run serve` as a separate process which starts a static server. `npm run build` will run a one-time build.
## Disclaimer & License ## Disclaimer & License
-1
View File
@@ -37,7 +37,6 @@ const options = { runScripts: 'outside-only', QuerySelector: true, virtualConsol
JSDOM.fromFile(program.inputPath, options).then(dom => { JSDOM.fromFile(program.inputPath, options).then(dom => {
const window = dom.window; const window = dom.window;
const document = window.document; const document = window.document;
const HTMLElement = window.HTMLElement;
const data = new transforms.FrontMatter; const data = new transforms.FrontMatter;
data.inputHTMLPath = program.inputPath; // may be needed to resolve relative links! data.inputHTMLPath = program.inputPath; // may be needed to resolve relative links!
+85 -118
View File
@@ -17,14 +17,14 @@
<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 name="viewport" content="width=device-width, initial-scale=1" >
<meta charset="utf8"> <meta charset="utf8">
</head> </head>
<body> <body>
<distill-header></distill-header> <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",
"description": "Although \" extremely useful for visualizing high-dimensional data, t-SNE plots can sometimes be mysterious or misleading.", "description": "Although \" extremely useful for visualizing high-dimensional data, t-SNE plots can sometimes be mysterious or misleading.",
"published": "Jan 10, 2017", "published": "Jan 10, 2017",
@@ -54,129 +54,96 @@
] ]
} }
}</script> }</script>
</d-front-matter> </d-front-matter>
<d-title> <d-title>
<figure style="grid-column: page; margin: 1rem 0;"><img src="momentum.png" <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>
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<d-cite key="mercier2011humans"></d-cite> as a means of dampening oscillations and </d-title>
speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a <d-byline></d-byline>
larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p> <d-article>
</d-title> <a class="marker" href="#section-1" id="section-1"><span>1</span></a>
<d-byline></d-byline> <h2>A Brief Survey of Techniques</h2>
<d-article> <p>Before diving in: if you havent encountered t-SNE before, heres what you need to know about the math behind it. The goal is to take a set of points in a high-dimensional space and find a faithful representation of those points in a lower-dimensional space, typically the 2D plane. The algorithm is non-linear and adapts to the underlying data, performing different transformations on different regions. Those differences can be a major source of confusion.</p>
<a class="marker" href="#section-1" id="section-1"><span>1</span></a> <p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p>
<h2>A Brief Survey of Techniques</h2> <p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for diving.</p>
<p>Before diving in: if you havent encountered t-SNE before, heres what you need to know about the math behind it. <aside>Some text in an aside, margin notes, etc...</aside>
The goal is to take a set of points in a high-dimensional space and find a faithful representation of those points <p>Here's a test of an inline equation <d-math>c = a^2 + b^2</d-math>. Also with configurable katex standards just using inline '$' signs: $$x^2$$ And then there's a block equation:</p>
in a lower-dimensional space, typically the 2D plane. The algorithm is non-linear and adapts to the underlying <d-math block>
data, performing different transformations on different regions. Those differences can be a major source of c = \pm \sqrt{ \sum_{i=0}^{n}{a^{222} + b^2}}
confusion.</p> </d-math>
<p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p> <p>Math can also be quite involved:</p>
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for <d-math block>
diving.</p> \frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} = 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} {1+\frac{e^{-6\pi}} {1+\frac{e^{-8\pi}} {1+\cdots} } } }
<aside>Some text in an aside, margin notes, etc...</aside> </d-math>
<p>Here's a test of an inline equation <d-math>c = a^2 + b^2</d-math>. Also with configurable katex standards just <a class="marker" href="#section-1.1" id="section-1.1"><span>1.1</span></a>
using inline '$' signs: $$x^2$$ And then there's a block equation:</p> <h3>Citations</h3>
<d-math block> <p><d-slider style="width: 200px;"></d-slider></p>
c = \pm \sqrt{ \sum_{i=0}^{n}{a^{222} + b^2}} <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>
</d-math> <a class="marker" href="#section-2" id="section-2"><span>2</span></a>
<p>Math can also be quite involved:</p> <h2>Displaying code snippets</h2>
<d-math block> <p>Some inline javascript:<d-code language="javascript">var x = 25;</d-code>. And here's a javascript code block.</p>
\frac{1}{\Bigl(\sqrt{\phi \sqrt{5}}-\phi\Bigr) e^{\frac25 \pi}} = 1+\frac{e^{-2\pi}} {1+\frac{e^{-4\pi}} <d-code block language="javascript">
{1+\frac{e^{-6\pi}} {1+\frac{e^{-8\pi}} {1+\cdots} } } }
</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 bibtex-key="mercier2011humans"></d-cite> also cite <d-cite
key="gregor2015draw,mercier2011humans,openai2018charter"></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>
<p>Some inline javascript:<d-code language="javascript">var x = 25;</d-code>. And here's a javascript code block.
</p>
<d-code block language="javascript">
var x = 25; var x = 25;
function(x){ function(x){
return x * x; return x * x;
} }
</d-code> </d-code>
<p>We also support python.</p> <p>We also support python.</p>
<d-code block language="python"> <d-code block language="python">
# Python 3: Fibonacci series up to n # Python 3: Fibonacci series up to n
def fib(n): def fib(n):
a, b = 0, 1 a, b = 0, 1
while a < n: print(a, end=' ' ) a, b=b, a+b </d-code> <p>And a table</p> while a < n:
<table> print(a, end=' ')
<thead> a, b = b, a+b
<tr> </d-code>
<th>First</th> <p>And a table</p>
<th>Second</th> <table>
<th>Third</th> <thead>
</tr> <tr><th>First</th><th>Second</th><th>Third</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr><td>23</td><td>654</td><td>23</td></tr>
<td>23</td> <tr><td>14</td><td>54</td><td>34</td></tr>
<td>654</td> <tr><td>234</td><td>54</td><td>23</td></tr>
<td>23</td> </tbody>
</tr> </table>
<tr> <d-figure id="last-figure"></d-figure>
<td>14</td> <script>
<td>54</td> const figure = document.querySelector("d-figure#last-figure");
<td>34</td> const initTag = document.createElement("span");
</tr> initTag.textContent = "initialized!"
<tr> figure.appendChild(initTag);
<td>234</td> figure.addEventListener("ready", function() {
<td>54</td> const initTag = figure.querySelector("span");
<td>23</td> initTag.textContent = "ready"
</tr> console.log('ready')
</tbody> });
</table> figure.addEventListener("onscreen", function() {
<d-figure id="last-figure"></d-figure> const initTag = figure.querySelector("span");
<script> initTag.textContent = "onscreen"
const figure = document.querySelector("d-figure#last-figure"); console.log('onscreen')
const initTag = document.createElement("span"); });
initTag.textContent = "initialized!" figure.addEventListener("offscreen", function() {
figure.appendChild(initTag); const initTag = figure.querySelector("span");
figure.addEventListener("ready", function () { initTag.textContent = "offscreen!"
const initTag = figure.querySelector("span"); console.log('offscreen')
initTag.textContent = "ready" });
console.log('ready') </script>
}); <p>That's it for the example article!</p>
figure.addEventListener("onscreen", function () {
const initTag = figure.querySelector("span");
initTag.textContent = "onscreen"
console.log('onscreen')
});
figure.addEventListener("offscreen", function () {
const initTag = figure.querySelector("span");
initTag.textContent = "offscreen!"
console.log('offscreen')
});
</script>
<p>That's it for the example article!</p>
</d-article> </d-article>
<d-appendix> <d-appendix>
<h3>Contributions</h3> <h3>Contributions</h3>
<p>Some text describing who did what.</p> <p>Some text describing who did what.</p>
<h3>Reviewers</h3> <h3>Reviewers</h3>
<p>Some text with links describing who reviewed the article.</p> <p>Some text with links describing who reviewed the article.</p>
<d-bibliography src="bibliography.bib"></d-bibliography> <d-bibliography src="bibliography.bib"></d-bibliography>
</d-appendix> </d-appendix>
<distill-footer></distill-footer> <distill-footer></distill-footer>
</body> </body>
-9
View File
@@ -97,12 +97,3 @@
year={2016}, year={2016},
url={https://arxiv.org/pdf/1609.07009.pdf} url={https://arxiv.org/pdf/1609.07009.pdf}
} }
@misc{openai2018charter,
author={OpenAI},
title={OpenAI Charter},
type={Blog},
number={April 9},
year={2018},
url={https://blog.openai.com/charter},
}
+1444 -1881
View File
File diff suppressed because it is too large Load Diff
+4 -6
View File
@@ -1,6 +1,6 @@
{ {
"name": "distill-template", "name": "distill-template",
"version": "2.5.1", "version": "2.2.26",
"description": "Template for creating Distill articles.", "description": "Template for creating Distill articles.",
"main": "dist/template.v2.js", "main": "dist/template.v2.js",
"bin": { "bin": {
@@ -13,7 +13,7 @@
}, },
"scripts": { "scripts": {
"dev": "rollup -c rollup.config.dev.js -w", "dev": "rollup -c rollup.config.dev.js -w",
"serve": "http-server", "serve": "python3 -m http.server --bind 127.0.0.1 8888",
"test": "mocha", "test": "mocha",
"lint": "eslint", "lint": "eslint",
"build": "rollup -c rollup.config.js", "build": "rollup -c rollup.config.js",
@@ -28,12 +28,11 @@
"chai": "^3.5.0", "chai": "^3.5.0",
"eslint": "^4.3.0", "eslint": "^4.3.0",
"eslint-config-google": "^0.9.1", "eslint-config-google": "^0.9.1",
"http-server": "^0.11.1",
"js-yaml": "^3.7.0", "js-yaml": "^3.7.0",
"jsdom": "11.3.0", "jsdom": "11.3.0",
"jsdom-global": "3.0.2", "jsdom-global": "3.0.2",
"marked": "^0.6.0", "marked": "^0.3.6",
"mocha": "^5.2.0", "mocha": "^3.5.3",
"prismjs": "^1.6.0", "prismjs": "^1.6.0",
"rollup": "^0.50.0", "rollup": "^0.50.0",
"rollup-plugin-babili": "^3.1.0", "rollup-plugin-babili": "^3.1.0",
@@ -48,7 +47,6 @@
"rollup-plugin-uglify": "^1.0.1", "rollup-plugin-uglify": "^1.0.1",
"rollup-watch": "^2.5.0", "rollup-watch": "^2.5.0",
"should": "^13.1.2", "should": "^13.1.2",
"source-map-support": "^0.5.16",
"webpack": "^2.2.1" "webpack": "^2.2.1"
}, },
"dependencies": { "dependencies": {
+13 -16
View File
@@ -13,7 +13,6 @@
// limitations under the License. // limitations under the License.
import { Controller } from './controller'; import { Controller } from './controller';
import { domContentLoaded } from './helpers/domContentLoaded.js';
/* Transforms */ /* Transforms */
import { makeStyleTag } from './styles/styles'; import { makeStyleTag } from './styles/styles';
@@ -56,13 +55,13 @@ const distillMain = function() {
throw new Error('Runlevel 1: Distill Template is getting loaded more than once, aborting!'); throw new Error('Runlevel 1: Distill Template is getting loaded more than once, aborting!');
} else { } else {
window.distillTemplateIsLoading = true; window.distillTemplateIsLoading = true;
console.debug('Runlevel 1: Distill Template has started loading.'); console.info('Runlevel 1: Distill Template has started loading.');
} }
/* 2. Add styles if they weren't added during prerendering */ /* 2. Add styles if they weren't added during prerendering */
makeStyleTag(document); makeStyleTag(document);
console.debug('Runlevel 1: Static Distill styles have been added.'); console.info('Runlevel 1: Static Distill styles have been added.');
console.debug('Runlevel 1->2.'); console.info('Runlevel 1->2.');
window.distillRunlevel += 1; window.distillRunlevel += 1;
/* 3. Register Controller listener functions */ /* 3. Register Controller listener functions */
@@ -74,8 +73,8 @@ const distillMain = function() {
console.error('Runlevel 2: Controller listeners need to be functions!'); console.error('Runlevel 2: Controller listeners need to be functions!');
} }
} }
console.debug('Runlevel 2: We can now listen to controller events.'); console.info('Runlevel 2: We can now listen to controller events.');
console.debug('Runlevel 2->3.'); console.info('Runlevel 2->3.');
window.distillRunlevel += 1; window.distillRunlevel += 1;
/* 4. Register components */ /* 4. Register components */
@@ -94,31 +93,29 @@ const distillMain = function() {
} }
const allComponents = components.concat(distillComponents); const allComponents = components.concat(distillComponents);
for (const component of allComponents) { for (const component of allComponents) {
console.debug('Runlevel 2: Registering custom element: ' + component.is); console.info('Runlevel 2: Registering custom element: ' + component.is);
customElements.define(component.is, component); customElements.define(component.is, component);
} }
console.debug('Runlevel 3: Distill Template finished registering custom elements.'); console.info('Runlevel 3: Distill Template finished registering custom elements.');
console.debug('Runlevel 3->4.'); console.info('Runlevel 3->4.');
window.distillRunlevel += 1; window.distillRunlevel += 1;
// If template was added after DOMContentLoaded we may have missed that event. // If template was added after DOMContentLoaded we may have missed that event.
// Controller will check for that case, so trigger the event explicitly: // Controller will check for that case, so trigger the event explicitly:
if (domContentLoaded()) { Controller.listeners.DOMContentLoaded();
Controller.listeners.DOMContentLoaded();
}
console.debug('Runlevel 4: Distill Template initialisation complete.'); console.info('Runlevel 4: Distill Template initialisation complete.');
}; };
window.distillRunlevel = 0; window.distillRunlevel = 0;
/* 0. Check browser feature support; synchronously polyfill if needed */ /* 0. Check browser feature support; synchronously polyfill if needed */
if (Polyfills.browserSupportsAllFeatures()) { if (Polyfills.browserSupportsAllFeatures()) {
console.debug('Runlevel 0: No need for polyfills.'); console.info('Runlevel 0: No need for polyfills.');
console.debug('Runlevel 0->1.'); console.info('Runlevel 0->1.');
window.distillRunlevel += 1; window.distillRunlevel += 1;
distillMain(); distillMain();
} else { } else {
console.debug('Runlevel 0: Distill Template is loading polyfills.'); console.info('Runlevel 0: Distill Template is loading polyfills.');
Polyfills.load(distillMain); Polyfills.load(distillMain);
} }
+1 -1
View File
@@ -30,7 +30,7 @@ d-appendix {
} }
d-appendix h3 { d-appendix h3 {
grid-column: page-start / text-start; grid-column: text;
font-size: 15px; font-size: 15px;
font-weight: 500; font-weight: 500;
margin-top: 1em; margin-top: 1em;
+1 -1
View File
@@ -16,7 +16,7 @@ import { bibliography_cite } from '../helpers/citation';
const styles = ` const styles = `
d-citation-list { d-citation-list {
contain: style; contain: layout style;
} }
d-citation-list .references { d-citation-list .references {
+32 -64
View File
@@ -12,19 +12,18 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
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';
const T = Template( const T = Template('d-cite', `
"d-cite",
`
<style> <style>
:host { :host {
display: inline-block;
} }
.citation { .citation {
display: inline-block;
color: hsla(206, 90%, 20%, 0.7); color: hsla(206, 90%, 20%, 0.7);
} }
@@ -69,107 +68,76 @@ ul li:last-of-type {
<d-hover-box id="hover-box"></d-hover-box> <d-hover-box id="hover-box"></d-hover-box>
<div id="citation-" class="citation"> <div id="citation-" class="citation">
<slot></slot>
<span class="citation-number"></span> <span class="citation-number"></span>
</div> </div>
` `);
);
export class Cite extends T(HTMLElement) { export class Cite extends T(HTMLElement) {
/* Lifecycle */ /* Lifecycle */
constructor() {
super();
this._numbers = [];
this._entries = [];
}
connectedCallback() { connectedCallback() {
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.hoverBox = this.root.querySelector("d-hover-box"); this.hoverBox = this.root.querySelector('d-hover-box');
window.customElements.whenDefined("d-hover-box").then(() => { window.customElements.whenDefined('d-hover-box').then(() => {
this.hoverBox.listen(this); this.hoverBox.listen(this);
}); });
// in case this component got connected after values were set
if (this.numbers) {
this.displayNumbers(this.numbers);
}
if (this.entries) {
this.displayEntries(this.entries);
}
} }
//TODO This causes an infinite loop on firefox with polyfills. //TODO This causes an infinite loop on firefox with polyfills.
// This is only needed for interactive editing so no priority. // This is only needed for interactive editing so no priority.
// disconnectedCallback() { // disconnectedCallback() {
// const options = { detail: [this, this.keys], bubbles: true }; // const options = { detail: [this, this.keys], bubbles: true };
// const event = new CustomEvent('onCiteKeyRemoved', options); // const event = new CustomEvent('onCiteKeyRemoved', options);
// document.dispatchEvent(event); // document.dispatchEvent(event);
// } // }
/* observe 'key' attribute */ /* observe 'key' attribute */
static get observedAttributes() { static get observedAttributes() {
return ["key", "bibtex-key"]; return ['key'];
} }
attributeChangedCallback(name, oldValue, newValue) { attributeChangedCallback(name, oldValue, newValue) {
const eventName = oldValue ? "onCiteKeyChanged" : "onCiteKeyCreated"; const eventName = oldValue ? 'onCiteKeyChanged' : 'onCiteKeyCreated';
const keys = newValue.split(",").map(k => k.trim()); const keys = newValue.split(',');
const options = { detail: [this, keys], bubbles: true }; const options = { detail: [this, keys], bubbles: true };
const event = new CustomEvent(eventName, options); const event = new CustomEvent(eventName, options);
document.dispatchEvent(event); document.dispatchEvent(event);
} }
set key(value) { set key(value) {
this.setAttribute("key", value); this.setAttribute('key', value);
} }
get key() { get key() {
return this.getAttribute("key") || this.getAttribute("bibtex-key"); return this.getAttribute('key');
} }
get keys() { get keys() {
const result = this.key.split(","); return this.getAttribute('key').split(',');
console.log(result);
return result;
} }
/* Setters & Rendering */ /* Setters & Rendering */
set numbers(numbers) { set numbers(numbers) {
this._numbers = numbers; const numberStrings = numbers.map( index => {
this.displayNumbers(numbers); return index == -1 ? '?' : index + 1 + '';
}
get numbers() {
return this._numbers;
}
displayNumbers(numbers) {
if (!this.innerSpan) return;
const numberStrings = numbers.map(index => {
return index == -1 ? "?" : index + 1 + "";
}); });
const textContent = "[" + numberStrings.join(", ") + "]"; const textContent = '[' + numberStrings.join(', ') + ']';
this.innerSpan.textContent = textContent; if (this.innerSpan) {
this.innerSpan.textContent = textContent;
}
} }
set entries(entries) { set entries(entries) {
this._entries = entries; if (this.hoverBox) {
this.displayEntries(entries); this.hoverBox.innerHTML = `<ul>
${entries.map(hover_cite).map(html => `<li>${html}</li>`).join('\n')}
</ul>`;
}
} }
get entries() {
return this._entries;
}
displayEntries(entries) {
if (!this.hoverBox) return;
this.hoverBox.innerHTML = `<ul>
${entries
.map(hover_cite)
.map(html => `<li>${html}</li>`)
.join("\n")}
</ul>`;
}
} }
+2 -1
View File
@@ -30,11 +30,12 @@ export function _moveLegacyAffiliationFormatIntoArray(frontMatter) {
author.affiliations = [newAffiliation]; author.affiliations = [newAffiliation];
} }
} }
console.log(frontMatter)
return frontMatter return frontMatter
} }
export function parseFrontmatter(element) { export function parseFrontmatter(element) {
const scriptTag = element.firstElementChild; const scriptTag = element.querySelector('script');
if (scriptTag) { if (scriptTag) {
const type = scriptTag.getAttribute('type'); const type = scriptTag.getAttribute('type');
if (type.split('/')[1] == 'json') { if (type.split('/')[1] == 'json') {
+3 -2
View File
@@ -30,7 +30,7 @@ ${katexCSSTag}
:host { :host {
display: inline-block; display: inline-block;
contain: style; contain: content;
} }
:host([block]) { :host([block]) {
@@ -73,7 +73,8 @@ export class DMath extends Mutating(T(HTMLElement)) {
} }
// transform inline delimited math to d-math tags // transform inline delimited math to d-math tags
if (DMath.katexOptions.delimiters) { if (DMath.katexOptions.delimiters) {
renderMathInElement(document.body, DMath.katexOptions); const article = document.querySelector('d-article');
renderMathInElement(article, DMath.katexOptions);
} }
} }
+52 -62
View File
@@ -12,46 +12,47 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { FrontMatter, mergeFromYMLFrontmatter } from "./front-matter"; import { FrontMatter, mergeFromYMLFrontmatter } from './front-matter';
import { DMath } from "./components/d-math"; import { DMath } from './components/d-math';
import { collect_citations } from "./helpers/citation.js"; import { collect_citations } from './helpers/citation.js';
import { domContentLoaded } from "./helpers/domContentLoaded.js"; import { parseFrontmatter } from './components/d-front-matter';
import { parseFrontmatter } from "./components/d-front-matter"; import optionalComponents from './transforms/optional-components';
import optionalComponents from "./transforms/optional-components";
const frontMatter = new FrontMatter(); const frontMatter = new FrontMatter();
function domContentLoaded() {
return ['interactive', 'complete'].indexOf(document.readyState) !== -1;
}
export const Controller = { export const Controller = {
frontMatter: frontMatter, frontMatter: frontMatter,
waitingOn: { waitingOn: {
bibliography: [], bibliography: [],
citations: [] citations: [],
}, },
listeners: { listeners: {
onCiteKeyCreated(event) { onCiteKeyCreated(event) {
const [citeTag, keys] = event.detail; const [citeTag, keys] = event.detail;
// ensure we have citations // ensure we have citations
if (!frontMatter.citationsCollected) { if (!frontMatter.citationsCollected) {
// console.debug('onCiteKeyCreated, but unresolved dependency ("citations"). Enqueing.'); // console.debug('onCiteKeyCreated, but unresolved dependency ("citations"). Enqueing.');
Controller.waitingOn.citations.push(() => Controller.waitingOn.citations.push(() => Controller.listeners.onCiteKeyCreated(event));
Controller.listeners.onCiteKeyCreated(event)
);
return; return;
} }
// ensure we have a loaded bibliography // ensure we have a loaded bibliography
if (!frontMatter.bibliographyParsed) { if (!frontMatter.bibliographyParsed) {
// console.debug('onCiteKeyCreated, but unresolved dependency ("bibliography"). Enqueing.'); // console.debug('onCiteKeyCreated, but unresolved dependency ("bibliography"). Enqueing.');
Controller.waitingOn.bibliography.push(() => Controller.waitingOn.bibliography.push(() => Controller.listeners.onCiteKeyCreated(event));
Controller.listeners.onCiteKeyCreated(event)
);
return; return;
} }
const numbers = keys.map(key => frontMatter.citations.indexOf(key)); const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
citeTag.numbers = numbers; citeTag.numbers = numbers;
const entries = keys.map(key => frontMatter.bibliography.get(key)); const entries = keys.map( key => frontMatter.bibliography.get(key) );
citeTag.entries = entries; citeTag.entries = entries;
}, },
@@ -66,23 +67,21 @@ export const Controller = {
} }
// update bibliography // update bibliography
const citationListTag = document.querySelector("d-citation-list"); const citationListTag = document.querySelector('d-citation-list');
const bibliographyEntries = new Map( const bibliographyEntries = new Map(frontMatter.citations.map( citationKey => {
frontMatter.citations.map(citationKey => { return [citationKey, frontMatter.bibliography.get(citationKey)];
return [citationKey, frontMatter.bibliography.get(citationKey)]; }));
})
);
citationListTag.citations = bibliographyEntries; citationListTag.citations = bibliographyEntries;
const citeTags = document.querySelectorAll("d-cite"); const citeTags = document.querySelectorAll('d-cite');
for (const citeTag of citeTags) { for (const citeTag of citeTags) {
console.log(citeTag);
const keys = citeTag.keys; const keys = citeTag.keys;
const numbers = keys.map(key => frontMatter.citations.indexOf(key)); const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
citeTag.numbers = numbers; citeTag.numbers = numbers;
const entries = keys.map(key => frontMatter.bibliography.get(key)); const entries = keys.map( key => frontMatter.bibliography.get(key) );
citeTag.entries = entries; citeTag.entries = entries;
} }
}, },
onCiteKeyRemoved(event) { onCiteKeyRemoved(event) {
@@ -90,7 +89,7 @@ export const Controller = {
}, },
onBibliographyChanged(event) { onBibliographyChanged(event) {
const citationListTag = document.querySelector("d-citation-list"); const citationListTag = document.querySelector('d-citation-list');
const bibliography = event.detail; const bibliography = event.detail;
@@ -102,23 +101,19 @@ export const Controller = {
// ensure we have citations // ensure we have citations
if (!frontMatter.citationsCollected) { if (!frontMatter.citationsCollected) {
Controller.waitingOn.citations.push(function() { Controller.waitingOn.citations.push( function() {
Controller.listeners.onBibliographyChanged({ Controller.listeners.onBibliographyChanged({target: event.target, detail: event.detail});
target: event.target,
detail: event.detail
});
}); });
return; return;
} }
if (citationListTag.hasAttribute("distill-prerendered")) {
console.debug("Citation list was prerendered; not updating it."); if (citationListTag.hasAttribute('distill-prerendered')) {
console.info('Citation list was prerendered; not updating it.');
} else { } else {
const entries = new Map( const entries = new Map(frontMatter.citations.map( citationKey => {
frontMatter.citations.map(citationKey => { return [citationKey, frontMatter.bibliography.get(citationKey)];
return [citationKey, frontMatter.bibliography.get(citationKey)]; }));
})
);
citationListTag.citations = entries; citationListTag.citations = entries;
} }
}, },
@@ -126,9 +121,9 @@ export const Controller = {
onFootnoteChanged() { onFootnoteChanged() {
// const footnote = event.detail; // const footnote = event.detail;
//TODO: optimize to only update current footnote //TODO: optimize to only update current footnote
const footnotesList = document.querySelector("d-footnote-list"); const footnotesList = document.querySelector('d-footnote-list');
if (footnotesList) { if (footnotesList) {
const footnotes = document.querySelectorAll("d-footnote"); const footnotes = document.querySelectorAll('d-footnote');
footnotesList.footnotes = footnotes; footnotesList.footnotes = footnotes;
} }
}, },
@@ -137,25 +132,25 @@ export const Controller = {
const data = event.detail; const data = event.detail;
mergeFromYMLFrontmatter(frontMatter, data); mergeFromYMLFrontmatter(frontMatter, data);
const interstitial = document.querySelector("d-interstitial"); const interstitial = document.querySelector('d-interstitial');
if (interstitial) { if (interstitial) {
if (typeof frontMatter.password !== "undefined") { if (typeof frontMatter.password !== 'undefined') {
interstitial.password = frontMatter.password; interstitial.password = frontMatter.password;
} else { } else {
interstitial.parentElement.removeChild(interstitial); interstitial.parentElement.removeChild(interstitial);
} }
} }
const prerendered = document.body.hasAttribute("distill-prerendered"); const prerendered = document.body.hasAttribute('distill-prerendered');
if (!prerendered && domContentLoaded()) { if (!prerendered && domContentLoaded()) {
optionalComponents(document, frontMatter); optionalComponents(document, frontMatter);
const appendix = document.querySelector("distill-appendix"); const appendix = document.querySelector('distill-appendix');
if (appendix) { if (appendix) {
appendix.frontMatter = frontMatter; appendix.frontMatter = frontMatter;
} }
const byline = document.querySelector("d-byline"); const byline = document.querySelector('d-byline');
if (byline) { if (byline) {
byline.frontMatter = frontMatter; byline.frontMatter = frontMatter;
} }
@@ -164,31 +159,24 @@ export const Controller = {
DMath.katexOptions = data.katex; DMath.katexOptions = data.katex;
} }
} }
}, },
DOMContentLoaded() { DOMContentLoaded() {
if (Controller.loaded) { if (Controller.loaded) {
console.warn( console.warn('Controller received DOMContentLoaded but was already loaded!');
"Controller received DOMContentLoaded but was already loaded!"
);
return; return;
} else if (!domContentLoaded()) { } else if (!domContentLoaded()) {
console.warn( console.warn('Controller received DOMContentLoaded before appropriate document.readyState!');
"Controller received DOMContentLoaded at document.readyState: " +
document.readyState +
"!"
);
return; return;
} else { } else {
Controller.loaded = true; Controller.loaded = true;
console.debug("Runlevel 4: Controller running DOMContentLoaded"); console.log('Runlevel 4: Controller running DOMContentLoaded');
} }
const frontMatterTag = document.querySelector("d-front-matter"); const frontMatterTag = document.querySelector('d-front-matter');
if (frontMatterTag) { const data = parseFrontmatter(frontMatterTag);
const data = parseFrontmatter(frontMatterTag); Controller.listeners.onFrontMatterChanged({detail: data});
Controller.listeners.onFrontMatterChanged({ detail: data });
}
// Resolving "citations" dependency due to initial DOM load // Resolving "citations" dependency due to initial DOM load
frontMatter.citations = collect_citations(); frontMatter.citations = collect_citations();
@@ -203,11 +191,13 @@ export const Controller = {
} }
} }
const footnotesList = document.querySelector("d-footnote-list"); const footnotesList = document.querySelector('d-footnote-list');
if (footnotesList) { if (footnotesList) {
const footnotes = document.querySelectorAll("d-footnote"); const footnotes = document.querySelectorAll('d-footnote');
footnotesList.footnotes = footnotes; footnotesList.footnotes = footnotes;
} }
} }
} // listeners
}, // listeners
}; // Controller }; // Controller
@@ -1,74 +0,0 @@
import logo from '../assets/distill-logo.svg';
export const footerTemplate = `
<style>
:host {
color: rgba(255, 255, 255, 0.5);
font-weight: 300;
padding: 2rem 0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
text-align: left;
contain: content;
}
.footer-container .logo svg {
width: 24px;
position: relative;
top: 4px;
margin-right: 2px;
}
.footer-container .logo svg path {
fill: none;
stroke: rgba(255, 255, 255, 0.8);
stroke-width: 3px;
}
.footer-container .logo {
font-size: 17px;
font-weight: 200;
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
margin-right: 6px;
}
.footer-container {
grid-column: text;
}
.footer-container .nav {
font-size: 0.9em;
margin-top: 1.5em;
}
.footer-container .nav a {
color: rgba(255, 255, 255, 0.8);
margin-right: 6px;
text-decoration: none;
}
</style>
<div class='footer-container'>
<a href="/" class="logo">
${logo}
Distill
</a> is dedicated to clear explanations of machine learning
<div class="nav">
<a href="https://distill.pub/about/">About</a>
<a href="https://distill.pub/journal/">Submit</a>
<a href="https://distill.pub/prize/">Prize</a>
<a href="https://distill.pub/archive/">Archive</a>
<a href="https://distill.pub/rss.xml">RSS</a>
<a href="https://github.com/distillpub">GitHub</a>
<a href="https://twitter.com/distillpub">Twitter</a>
&nbsp;&nbsp;&nbsp;&nbsp; ISSN 2476-0757
</div>
</div>
`;
+72 -2
View File
@@ -13,10 +13,80 @@
// limitations under the License. // limitations under the License.
import { Template } from '../mixins/template'; import { Template } from '../mixins/template';
import logo from '../assets/distill-logo.svg';
import {footerTemplate} from './distill-footer-template'; const T = Template('distill-footer', `
<style>
const T = Template('distill-footer', footerTemplate); :host {
color: rgba(255, 255, 255, 0.5);
font-weight: 300;
padding: 2rem 0;
border-top: 1px solid rgba(0, 0, 0, 0.1);
background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
text-align: left;
contain: content;
}
.logo svg {
width: 24px;
position: relative;
top: 4px;
margin-right: 2px;
}
.logo svg path {
fill: none;
stroke: rgba(255, 255, 255, 0.8);
stroke-width: 3px;
}
.logo {
font-size: 17px;
font-weight: 200;
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
margin-right: 6px;
}
.container {
grid-column: text;
}
.nav {
font-size: 0.9em;
margin-top: 1.5em;
}
.nav a {
color: rgba(255, 255, 255, 0.8);
margin-right: 6px;
text-decoration: none;
}
</style>
<div class='container'>
<a href="/" class="logo">
${logo}
Distill
</a> is dedicated to clear explanations of machine learning
<div class="nav">
<a href="https://distill.pub/about/">About</a>
<a href="https://distill.pub/journal/">Submit</a>
<a href="https://distill.pub/prize/">Prize</a>
<a href="https://distill.pub/archive/">Archive</a>
<a href="https://distill.pub/rss.xml">RSS</a>
<a href="https://github.com/distillpub">GitHub</a>
<a href="https://twitter.com/distillpub">Twitter</a>
&nbsp;&nbsp;&nbsp;&nbsp; ISSN 2476-0757
</div>
</div>
`);
export class DistillFooter extends T(HTMLElement) { export class DistillFooter extends T(HTMLElement) {
@@ -1,79 +0,0 @@
import logo from '../assets/distill-logo.svg';
export const headerTemplate = `
<style>
distill-header {
position: relative;
height: 60px;
background-color: hsl(200, 60%, 15%);
width: 100%;
box-sizing: border-box;
z-index: 2;
color: rgba(0, 0, 0, 0.8);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
}
distill-header .content {
height: 70px;
grid-column: page;
}
distill-header a {
font-size: 16px;
height: 60px;
line-height: 60px;
text-decoration: none;
color: rgba(255, 255, 255, 0.8);
padding: 22px 0;
}
distill-header a:hover {
color: rgba(255, 255, 255, 1);
}
distill-header svg {
width: 24px;
position: relative;
top: 4px;
margin-right: 2px;
}
@media(min-width: 1080px) {
distill-header {
height: 70px;
}
distill-header a {
height: 70px;
line-height: 70px;
padding: 28px 0;
}
distill-header .logo {
}
}
distill-header svg path {
fill: none;
stroke: rgba(255, 255, 255, 0.8);
stroke-width: 3px;
}
distill-header .logo {
font-size: 17px;
font-weight: 200;
}
distill-header .nav {
float: right;
font-weight: 300;
}
distill-header .nav a {
font-size: 12px;
margin-left: 24px;
text-transform: uppercase;
}
</style>
<div class="content">
<a href="/" class="logo">
${logo}
Distill
</a>
<nav class="nav">
<a href="/about/">About</a>
<a href="/prize/">Prize</a>
<a href="/journal/">Submit</a>
</nav>
</div>
`;
+79 -2
View File
@@ -14,9 +14,86 @@
import { Template } from '../mixins/template'; import { Template } from '../mixins/template';
import {headerTemplate} from './distill-header-template'; import logo from '../assets/distill-logo.svg';
const T = Template('distill-header', `
<style>
distill-header {
position: relative;
height: 60px;
background-color: hsl(200, 60%, 15%);
width: 100%;
box-sizing: border-box;
z-index: 2;
color: rgba(0, 0, 0, 0.8);
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
}
distill-header .content {
height: 70px;
grid-column: page;
}
distill-header a {
font-size: 16px;
height: 60px;
line-height: 60px;
text-decoration: none;
color: rgba(255, 255, 255, 0.8);
padding: 22px 0;
}
distill-header a:hover {
color: rgba(255, 255, 255, 1);
}
distill-header svg {
width: 24px;
position: relative;
top: 4px;
margin-right: 2px;
}
@media(min-width: 1080px) {
distill-header {
height: 70px;
}
distill-header a {
height: 70px;
line-height: 70px;
padding: 28px 0;
}
distill-header .logo {
}
}
distill-header svg path {
fill: none;
stroke: rgba(255, 255, 255, 0.8);
stroke-width: 3px;
}
distill-header .logo {
font-size: 17px;
font-weight: 200;
}
distill-header .nav {
float: right;
font-weight: 300;
}
distill-header .nav a {
font-size: 12px;
margin-left: 24px;
text-transform: uppercase;
}
</style>
<div class="content">
<a href="/" class="logo">
${logo}
Distill
</a>
<nav class="nav">
<a href="/about/">About</a>
<a href="/prize/">Prize</a>
<a href="/journal/">Submit</a>
</nav>
</div>
`, false);
const T = Template('distill-header', headerTemplate, false);
export class DistillHeader extends T(HTMLElement) { export class DistillHeader extends T(HTMLElement) {
-3
View File
@@ -12,13 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { footerTemplate } from '../distill-components/distill-footer-template';
export default function(dom) { export default function(dom) {
const footerTag = dom.querySelector('distill-footer'); const footerTag = dom.querySelector('distill-footer');
if(!footerTag) { if(!footerTag) {
const footer = dom.createElement('distill-footer'); const footer = dom.createElement('distill-footer');
footer.innerHTML = footerTemplate;
const body = dom.querySelector('body'); const body = dom.querySelector('body');
body.appendChild(footer); body.appendChild(footer);
} }
+1 -6
View File
@@ -12,15 +12,10 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
export default function(dom) {
import { headerTemplate } from '../distill-components/distill-header-template';
export default function(dom, data) {
const headerTag = dom.querySelector('distill-header'); const headerTag = dom.querySelector('distill-header');
if (!headerTag) { if (!headerTag) {
const header = dom.createElement('distill-header'); const header = dom.createElement('distill-header');
header.innerHTML = headerTemplate;
header.setAttribute('distill-prerendered', "");
const body = dom.querySelector('body'); const body = dom.querySelector('body');
body.insertBefore(header, body.firstChild); body.insertBefore(header, body.firstChild);
} }
-5
View File
@@ -96,9 +96,6 @@ export function mergeFromYMLFrontmatter(target, source) {
target.authors = source.authors.map( (authorObject) => new Author(authorObject)); target.authors = source.authors.map( (authorObject) => new Author(authorObject));
target.katex = source.katex; target.katex = source.katex;
target.password = source.password; target.password = source.password;
if (source.doi) {
target.doi = source.doi;
}
} }
export class FrontMatter { export class FrontMatter {
@@ -163,7 +160,6 @@ export class FrontMatter {
// githubCompareUpdatesUrl: 'https://github.com/distillpub/post--augmented-rnns/compare/1596e094d8943d2dc0ea445d92071129c6419c59...3bd9209e0c24d020f87cf6152dcecc6017cbc193', // githubCompareUpdatesUrl: 'https://github.com/distillpub/post--augmented-rnns/compare/1596e094d8943d2dc0ea445d92071129c6419c59...3bd9209e0c24d020f87cf6152dcecc6017cbc193',
// updatedDate: 2017-03-21T07:13:16.000Z, // updatedDate: 2017-03-21T07:13:16.000Z,
// doi: '10.23915/distill.00001', // doi: '10.23915/distill.00001',
this.doi = undefined;
this.publishedDate = undefined; this.publishedDate = undefined;
} }
@@ -322,7 +318,6 @@ export class FrontMatter {
Object.assign(target, this); Object.assign(target, this);
target.bibliography = objectFromMap(this.bibliographyEntries); target.bibliography = objectFromMap(this.bibliographyEntries);
target.url = this.url; target.url = this.url;
target.doi = this.doi;
target.githubUrl = this.githubUrl; target.githubUrl = this.githubUrl;
target.previewURL = this.previewURL; target.previewURL = this.previewURL;
if (this.publishedDate) { if (this.publishedDate) {
+88 -106
View File
@@ -12,12 +12,11 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
export function collect_citations(dom = document) { export function collect_citations(dom=document) {
const citations = new Set(); const citations = new Set();
const citeTags = dom.querySelectorAll("d-cite"); const citeTags = dom.querySelectorAll('d-cite');
for (const tag of citeTags) { for (const tag of citeTags) {
const keyString = tag.getAttribute("key") || tag.getAttribute("bibtex-key"); const keys = tag.getAttribute('key').split(',');
const keys = keyString.split(",").map(k => k.trim());
for (const key of keys) { for (const key of keys) {
citations.add(key); citations.add(key);
} }
@@ -25,74 +24,59 @@ export function collect_citations(dom = document) {
return [...citations]; return [...citations];
} }
export function inline_cite_short(keys) { export function inline_cite_short(keys){
function cite_string(key) { function cite_string(key){
if (key in data.bibliography) { if (key in data.bibliography){
var n = data.citations.indexOf(key) + 1; var n = data.citations.indexOf(key)+1;
return "" + n; return ''+n;
} else { } else {
return "?"; return '?';
} }
} }
return "[" + keys.map(cite_string).join(", ") + "]"; return '['+keys.map(cite_string).join(', ')+']';
} }
export function inline_cite_long(keys) { export function inline_cite_long(keys){
function cite_string(key) { function cite_string(key){
if (key in data.bibliography) { if (key in data.bibliography){
var ent = data.bibliography[key]; var ent = data.bibliography[key];
var names = ent.author.split(" and "); var names = ent.author.split(' and ');
names = names.map(name => name.split(",")[0].trim()); names = names.map(name => name.split(',')[0].trim());
var year = ent.year; var year = ent.year;
if (names.length == 1) return names[0] + ", " + year; if (names.length == 1) return names[0] + ', ' + year;
if (names.length == 2) return names[0] + " & " + names[1] + ", " + year; if (names.length == 2) return names[0] + ' & ' + names[1] + ', ' + year;
if (names.length > 2) return names[0] + ", et al., " + year; if (names.length > 2) return names[0] + ', et al., ' + year;
} else { } else {
return "?"; return '?';
} }
} }
return keys.map(cite_string).join(", "); return keys.map(cite_string).join(', ');
} }
function author_string(ent, template, sep, finalSep) { function author_string(ent, template, sep, finalSep){
if (ent.author == null) { if (ent.author == null) { return ''; }
return ""; var names = ent.author.split(' and ');
}
var names = ent.author.split(" and ");
let name_strings = names.map(name => { let name_strings = names.map(name => {
name = name.trim(); name = name.trim();
if (name.indexOf(",") != -1) { if (name.indexOf(',') != -1){
var last = name.split(",")[0].trim(); var last = name.split(',')[0].trim();
var firsts = name.split(",")[1]; var firsts = name.split(',')[1];
} else if (name.indexOf(" ") != -1) {
var last = name
.split(" ")
.slice(-1)[0]
.trim();
var firsts = name
.split(" ")
.slice(0, -1)
.join(" ");
} else { } else {
var last = name.trim(); var last = name.split(' ').slice(-1)[0].trim();
var firsts = name.split(' ').slice(0,-1).join(' ');
} }
var initials = ""; var initials = '';
if (firsts != undefined) { if (firsts != undefined) {
initials = firsts initials = firsts.trim().split(' ').map(s => s.trim()[0]);
.trim() initials = initials.join('.')+'.';
.split(" ")
.map(s => s.trim()[0]);
initials = initials.join(".") + ".";
} }
return template return template.replace('${F}', firsts)
.replace("${F}", firsts) .replace('${L}', last)
.replace("${L}", last) .replace('${I}', initials);
.replace("${I}", initials)
.trim(); // in case one of first or last was empty
}); });
if (names.length > 1) { if (names.length > 1) {
var str = name_strings.slice(0, names.length - 1).join(sep); var str = name_strings.slice(0, names.length-1).join(sep);
str += (finalSep || sep) + name_strings[names.length - 1]; str += (finalSep || sep) + name_strings[names.length-1];
return str; return str;
} else { } else {
return name_strings[0]; return name_strings[0];
@@ -100,71 +84,69 @@ function author_string(ent, template, sep, finalSep) {
} }
function venue_string(ent) { function venue_string(ent) {
var cite = ent.journal || ent.booktitle || ""; var cite = (ent.journal || ent.booktitle || '');
if ("volume" in ent) { if ('volume' in ent){
var issue = ent.issue || ent.number; var issue = ent.issue || ent.number;
issue = issue != undefined ? "(" + issue + ")" : ""; issue = (issue != undefined)? '('+issue+')' : '';
cite += ", Vol " + ent.volume + issue; cite += ', Vol ' + ent.volume + issue;
} }
if ("pages" in ent) { if ('pages' in ent){
cite += ", pp. " + ent.pages; cite += ', pp. ' + ent.pages;
} }
if (cite != "") cite += ". "; if (cite != '') cite += '. ';
if ("publisher" in ent) { if ('publisher' in ent){
cite += ent.publisher; cite += ent.publisher;
if (cite[cite.length - 1] != ".") cite += "."; if (cite[cite.length-1] != '.') cite += '.';
} }
return cite; return cite;
} }
function link_string(ent) { function link_string(ent){
if ("url" in ent) { if ('url' in ent){
var url = ent.url; var url = ent.url;
var arxiv_match = /arxiv\.org\/abs\/([0-9\.]*)/.exec(url); var arxiv_match = (/arxiv\.org\/abs\/([0-9\.]*)/).exec(url);
if (arxiv_match != null) { if (arxiv_match != null){
url = `http://arxiv.org/pdf/${arxiv_match[1]}.pdf`; url = `http://arxiv.org/pdf/${arxiv_match[1]}.pdf`;
} }
if (url.slice(-4) == ".pdf") { if (url.slice(-4) == '.pdf'){
var label = "PDF"; var label = 'PDF';
} else if (url.slice(-5) == ".html") { } else if (url.slice(-5) == '.html') {
var label = "HTML"; var label = 'HTML';
} }
return ` &ensp;<a href="${url}">[${label || "link"}]</a>`; return ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
} /* else if ("doi" in ent){ }/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`; return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else { }*/ else {
return ""; return '';
} }
} }
function doi_string(ent, new_line) { function doi_string(ent, new_line){
if ("doi" in ent) { if ('doi' in ent) {
return `${new_line ? "<br>" : ""} <a href="https://doi.org/${ return `${new_line?'<br>':''} <a href="https://doi.org/${ent.doi}" style="text-decoration:inherit;">DOI: ${ent.doi}</a>`;
ent.doi
}" style="text-decoration:inherit;">DOI: ${ent.doi}</a>`;
} else { } else {
return ""; return '';
} }
} }
function title_string(ent) { function title_string(ent) {
return '<span class="title">' + ent.title + "</span> "; return '<span class="title">' + ent.title + '</span> ';
} }
export function bibliography_cite(ent, fancy) { export function bibliography_cite(ent, fancy){
if (ent) { if (ent){
var cite = title_string(ent); var cite = title_string(ent);
cite += link_string(ent) + "<br>"; cite += link_string(ent) + '<br>';
if (ent.author) { if (ent.author) {
cite += author_string(ent, "${L}, ${I}", ", ", " and "); cite += author_string(ent, '${L}, ${I}', ', ', ' and ');
if (ent.year || ent.date) { if (ent.year || ent.date) {
cite += ", "; cite += ', ';
} }
} }
if (ent.year || ent.date) { if (ent.year || ent.date) {
cite += (ent.year || ent.date) + ". "; cite += (ent.year || ent.date) + '. ';
} else { } else {
cite += ". "; cite += '. ';
} }
cite += venue_string(ent); cite += venue_string(ent);
cite += doi_string(ent); cite += doi_string(ent);
@@ -181,39 +163,39 @@ export function bibliography_cite(ent, fancy) {
cite += link_string(ent); cite += link_string(ent);
return cite*/ return cite*/
} else { } else {
return "?"; return '?';
} }
} }
export function hover_cite(ent) { export function hover_cite(ent){
if (ent) { if (ent){
var cite = ""; var cite = '';
cite += "<strong>" + ent.title + "</strong>"; cite += '<strong>' + ent.title + '</strong>';
cite += link_string(ent); cite += link_string(ent);
cite += "<br>"; cite += '<br>';
var a_str = author_string(ent, "${I} ${L}", ", ") + "."; var a_str = author_string(ent, '${I} ${L}', ', ') + '.';
var v_str = var v_str = venue_string(ent).trim() + ' ' + ent.year + '. ' + doi_string(ent, true);
venue_string(ent).trim() + " " + ent.year + ". " + doi_string(ent, true);
if ((a_str + v_str).length < Math.min(40, ent.title.length)) { if ((a_str+v_str).length < Math.min(40, ent.title.length)) {
cite += a_str + " " + v_str; cite += a_str + ' ' + v_str;
} else { } else {
cite += a_str + "<br>" + v_str; cite += a_str + '<br>' + v_str;
} }
return cite; return cite;
} else { } else {
return "?"; return '?';
} }
} }
//https://scholar.google.com/scholar?q=allintitle%3ADocument+author%3Aolah //https://scholar.google.com/scholar?q=allintitle%3ADocument+author%3Aolah
function get_GS_URL(ent) { function get_GS_URL(ent){
if (ent) { if (ent){
var names = ent.author.split(" and "); var names = ent.author.split(' and ');
names = names.map(name => name.split(",")[0].trim()); names = names.map(name => name.split(',')[0].trim());
var title = ent.title.split(" "); //.replace(/[,:]/, "") var title = ent.title.split(' ');//.replace(/[,:]/, "")
var url = "http://search.labs.crossref.org/dois?"; //""https://scholar.google.com/scholar?" var url = 'http://search.labs.crossref.org/dois?';//""https://scholar.google.com/scholar?"
url += uris({ q: names.join(" ") + " " + title.join(" ") }); url += uris({q: names.join(' ') + ' ' + title.join(' ')});
} }
} }
-3
View File
@@ -1,3 +0,0 @@
export function domContentLoaded() {
return ['interactive', 'complete'].indexOf(document.readyState) !== -1;
}
+5 -5
View File
@@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
export function addPolyfill(polyfill, polyfillLoadedCallback) { export function addPolyfill(polyfill, polyfillLoadedCallback) {
console.debug('Runlevel 0: Polyfill required: ' + polyfill.name); console.info('Runlevel 0: Polyfill required: ' + polyfill.name);
const script = document.createElement('script'); const script = document.createElement('script');
script.src = polyfill.url; script.src = polyfill.url;
script.async = false; script.async = false;
@@ -58,11 +58,11 @@ export class Polyfills {
// Define an intermediate callback that checks if all is loaded. // Define an intermediate callback that checks if all is loaded.
const polyfillLoaded = function(polyfill) { const polyfillLoaded = function(polyfill) {
polyfill.loaded = true; polyfill.loaded = true;
console.debug('Runlevel 0: Polyfill has finished loading: ' + polyfill.name); console.info('Runlevel 0: Polyfill has finished loading: ' + polyfill.name);
// console.debug(window[polyfill.name]); // console.info(window[polyfill.name]);
if (Polyfills.neededPolyfills.every((poly) => poly.loaded)) { if (Polyfills.neededPolyfills.every((poly) => poly.loaded)) {
console.debug('Runlevel 0: All required polyfills have finished loading.'); console.info('Runlevel 0: All required polyfills have finished loading.');
console.debug('Runlevel 0->1.'); console.info('Runlevel 0->1.');
window.distillRunlevel = 1; window.distillRunlevel = 1;
callback(); callback();
} }
-3
View File
@@ -40,9 +40,6 @@ export const Template = (name, templateString, useShadow = true) => {
} }
connectedCallback() { connectedCallback() {
if (this.hasAttribute('distill-prerendered')) {
return;
}
if (useShadow) { if (useShadow) {
if ('ShadyCSS' in window) { if ('ShadyCSS' in window) {
ShadyCSS.styleElement(this); ShadyCSS.styleElement(this);
+1 -1
View File
@@ -15,7 +15,7 @@
*/ */
d-byline { d-byline {
contain: style; contain: content;
overflow: hidden; overflow: hidden;
border-top: 1px solid rgba(0, 0, 0, 0.1); border-top: 1px solid rgba(0, 0, 0, 0.1);
font-size: 0.8rem; font-size: 0.8rem;
+1 -1
View File
@@ -67,7 +67,7 @@ export default function render(dom) {
if (templateTag) { if (templateTag) {
templateTag.parentNode.removeChild(templateTag); templateTag.parentNode.removeChild(templateTag);
} else { } else {
console.debug('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.') 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 // add loader
+114 -157
View File
@@ -14,88 +14,75 @@
/* global it, describe, before, beforeEach, after, afterEach */ /* global it, describe, before, beforeEach, after, afterEach */
const jsdom = require("jsdom"); const jsdom = require('jsdom');
const { JSDOM } = jsdom; const { JSDOM } = jsdom;
const expect = require("chai").expect; const expect = require('chai').expect;
const distill = require("../dist/transforms.v2.js"); const distill = require('../dist/transforms.v2.js');
// omitJSDOMErrors as JSDOM routinely can't parse modern CSS // omitJSDOMErrors as JSDOM routinely can't parse modern CSS
const virtualConsole = new jsdom.VirtualConsole(); const virtualConsole = new jsdom.VirtualConsole();
virtualConsole.sendTo(console, { omitJSDOMErrors: true }); virtualConsole.sendTo(console, { omitJSDOMErrors: true });
const options = { const options = { runScripts: 'outside-only', QuerySelector: true, virtualConsole: virtualConsole };
runScripts: "outside-only",
QuerySelector: true,
virtualConsole: virtualConsole
};
describe("Distill V2 (transforms)", function() { describe('Distill V2 (transforms)', function() {
it("should export its expected interface", function() {
expect(distill.testing).to.be.an("object"); it('should export its expected interface', function() {
expect(distill.usesTemplateV2).to.be.a("function"); expect(distill.testing).to.be.an('object');
expect(distill.render).to.be.a("function"); expect(distill.usesTemplateV2).to.be.a('function');
expect(distill.distillify).to.be.a("function"); expect(distill.render).to.be.a('function');
expect(distill.distillify).to.be.a('function');
}); });
describe("#usesTemplateV2()", function() { describe('#usesTemplateV2()', function() {
it("should detect v1", function() {
const frag = JSDOM.fragment( it('should detect v1', function() {
'<script src="https://distill.pub/template.v1.js"></script>' const frag = JSDOM.fragment('<script src="https://distill.pub/template.v1.js"></script>');
);
expect(distill.usesTemplateV2(frag)).to.be.false; expect(distill.usesTemplateV2(frag)).to.be.false;
}); });
it("should detect v2", function() { it('should detect v2', function() {
const frag = JSDOM.fragment( const frag = JSDOM.fragment('<script src="https://distill.pub/template.v2.js"></script>');
'<script src="https://distill.pub/template.v2.js"></script>'
);
expect(distill.usesTemplateV2(frag)).to.be.true; expect(distill.usesTemplateV2(frag)).to.be.true;
}); });
it("should detect local scripts as well", function() { it('should detect local scripts as well', function() {
const frag = JSDOM.fragment('<script src="/template.v2.js"></script>'); const frag = JSDOM.fragment('<script src="/template.v2.js"></script>');
expect(distill.usesTemplateV2(frag)).to.be.true; expect(distill.usesTemplateV2(frag)).to.be.true;
}); });
it("should error on unknown distill script", function() { it('should error on unknown distill script', function() {
const frag = JSDOM.fragment( const frag = JSDOM.fragment('<script src="https://distill.pub/template.v42.js"></script>');
'<script src="https://distill.pub/template.v42.js"></script>' expect(()=> distill.usesTemplateV2(frag)).to.throw('unknown');
);
expect(() => distill.usesTemplateV2(frag)).to.throw("unknown");
}); });
it("should error on no distill script", function() { it('should error on no distill script', function() {
const frag = JSDOM.fragment( const frag = JSDOM.fragment('<script src="https://code.jquery.com/jquery-3.2.1.js"></script>');
'<script src="https://code.jquery.com/jquery-3.2.1.js"></script>' expect(()=> distill.usesTemplateV2(frag)).to.throw('at all');
);
expect(() => distill.usesTemplateV2(frag)).to.throw("at all");
}); });
}); });
describe("#render()", function() { describe('#render()', function() {
describe("should extract metadata", function() {
it("should extract citations", function() { describe('should extract metadata', function() {
const dom = new JSDOM(
'<d-cite key="test-citation-key">sth</d-cite>', it('should extract citations', function() {
options const dom = new JSDOM('<d-cite key="test-citation-key">sth</d-cite>', options);
);
const data = {}; const data = {};
const extractCitations = distill.testing.extractors.get( const extractCitations = distill.testing.extractors.get('ExtractCitations');
"ExtractCitations" expect(extractCitations).to.be.a('function');
);
expect(extractCitations).to.be.a("function");
extractCitations(dom.window.document, data); extractCitations(dom.window.document, data);
expect(data).to.have.property("citations"); expect(data).to.have.property('citations');
const citations = data.citations; const citations = data.citations;
expect(citations).to.be.an.instanceof(Array); expect(citations).to.be.an.instanceof(Array);
expect(citations).to.have.lengthOf(1); expect(citations).to.have.lengthOf(1);
const citation = citations[0]; const citation = citations[0];
expect(citation).to.equal("test-citation-key"); expect(citation).to.equal('test-citation-key');
}); });
it("should extract bibliography", function() { it('should extract bibliography', function() {
const dom = new JSDOM( const dom = new JSDOM(`
`
<d-cite key="mercier2011humans">sth</d-cite> <d-cite key="mercier2011humans">sth</d-cite>
<d-bibliography> <d-bibliography>
<script type="text/bibtex"> <script type="text/bibtex">
@@ -112,58 +99,44 @@ describe("Distill V2 (transforms)", function() {
} }
</script> </script>
</d-bibliography> </d-bibliography>
`, `, options);
options
);
const data = {}; const data = {};
const extractBibliography = distill.testing.extractors.get( const extractBibliography = distill.testing.extractors.get('ExtractBibliography');
"ExtractBibliography"
);
extractBibliography(dom.window.document, data); extractBibliography(dom.window.document, data);
expect(data.bibliography).to.be.an.instanceof(Map); expect(data.bibliography).to.be.an.instanceof(Map);
const entry = data.bibliography.get("mercier2011humans"); const entry = data.bibliography.get('mercier2011humans');
expect(entry).to.be.an("object"); expect(entry).to.be.an('object');
expect(entry).to.have.property("year", "2011"); expect(entry).to.have.property('year', '2011');
}); });
it("should extract front-matter"); it('should extract front-matter');
}); // metadata }); // metadata
describe("should transform the DOM", function() { describe('should transform the DOM', function() {
it("should add Google scholar citation information", function() {
const dom = new JSDOM("", options); it('should add Google scholar citation information', function() {
const dom = new JSDOM('', options);
const data = { const data = {
authors: [ authors: [
{ {firstName: 'Frank', lastName: 'Underwood', affiliation: 'Google Brain', affiliationURL: 'https://g.co/brain'},
firstName: "Frank", {firstName: 'Shan', lastName: 'Carter', affiliation: 'Google Brain', affiliationURL: 'https://g.co/brain'},
lastName: "Underwood",
affiliation: "Google Brain",
affiliationURL: "https://g.co/brain"
},
{
firstName: "Shan",
lastName: "Carter",
affiliation: "Google Brain",
affiliationURL: "https://g.co/brain"
}
], ],
doiSuffix: "test-doi-suffix" doiSuffix: 'test-doi-suffix'
}; };
const firstAuthorName = const firstAuthorName = data.authors[0].firstName + ' ' + data.authors[0].lastName;
data.authors[0].firstName + " " + data.authors[0].lastName; const GSfirstAuthorName = data.authors[0].lastName + ', ' + data.authors[0].firstName;
const GSfirstAuthorName =
data.authors[0].lastName + ", " + data.authors[0].firstName;
const meta = distill.testing.transforms.get("Meta"); const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a("function"); expect(meta).to.be.a('function');
meta(dom.window.document, data); meta(dom.window.document, data);
const metaTags = dom.window.document.querySelectorAll("meta"); const metaTags = dom.window.document.querySelectorAll('meta');
expect(metaTags).to.not.be.empty; expect(metaTags).to.not.be.empty;
// Google Scholar // Google Scholar
const GSAuthorTags = Array.prototype.filter.call(metaTags, tag => { const GSAuthorTags = Array.prototype.filter.call(metaTags, (tag) => {
return tag.name === "citation_author"; return tag.name === 'citation_author';
}); });
expect(GSAuthorTags).to.have.lengthOf(2); expect(GSAuthorTags).to.have.lengthOf(2);
const GSFirstAuthorTag = GSAuthorTags[0]; const GSFirstAuthorTag = GSAuthorTags[0];
@@ -171,89 +144,74 @@ describe("Distill V2 (transforms)", function() {
expect(GSFirstAuthorTag.content).to.equal(GSfirstAuthorName); expect(GSFirstAuthorTag.content).to.equal(GSfirstAuthorName);
// Schema.org Author tags // Schema.org Author tags
const SOAuthorTags = Array.prototype.filter.call(metaTags, tag => { const SOAuthorTags = Array.prototype.filter.call(metaTags, (tag) => {
return tag.getAttribute("property") === "article:author"; return tag.getAttribute('property') === 'article:author';
}); });
expect(SOAuthorTags).to.have.lengthOf(2); expect(SOAuthorTags).to.have.lengthOf(2);
const SOFirstAuthorTag = SOAuthorTags[0]; const SOFirstAuthorTag = SOAuthorTags[0];
expect(SOFirstAuthorTag.content).to.equal(firstAuthorName); expect(SOFirstAuthorTag.content).to.equal(firstAuthorName);
}); });
it("given already correct data, it should add Google scholar references information", function() { it('given already correct data, it should add Google scholar references information', function() {
const dom = new JSDOM("", options); const dom = new JSDOM('', options);
const data = { const data = {
doiSuffix: "test-doi-suffix", doiSuffix: 'test-doi-suffix',
citations: ["test-citation-key"], citations: ['test-citation-key'],
bibliography: new Map([ bibliography: new Map([[
[ 'test-citation-key', {
"test-citation-key", title: 'Why do humans reason? Arguments for an argumentative theory',
{ author: 'Mercier, Hugo and Sperber, Dan',
title: journal: 'Behavioral and brain sciences',
"Why do humans reason? Arguments for an argumentative theory", volume: 34,
author: "Mercier, Hugo and Sperber, Dan", number: 2
journal: "Behavioral and brain sciences", }
volume: 34, ]])
number: 2
}
]
])
}; };
const meta = distill.testing.transforms.get("Meta"); const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a("function"); expect(meta).to.be.a('function');
meta(dom.window.document, data); meta(dom.window.document, data);
const metaTags = [].slice.call( const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty; expect(metaTags).to.not.be.empty;
}); });
it("given an arxiv article, it should add a special Google scholar arxiv citation", function() { it('given an arxiv article, it should add a special Google scholar arxiv citation', function() {
const dom = new JSDOM("", options); const dom = new JSDOM('', options);
const data = { const data = {
doiSuffix: "test-doi-suffix", doiSuffix: 'test-doi-suffix',
citations: ["dumoulin2016guide"], citations: ['dumoulin2016guide'],
bibliography: new Map([ bibliography: new Map([[
[ 'dumoulin2016guide', {
"dumoulin2016guide", title: 'A guide to convolution arithmetic for deep learning',
{ author: 'Dumoulin, Vincent and Visin, Francesco',
title: "A guide to convolution arithmetic for deep learning", journal: 'arXiv preprint arXiv:1603.07285',
author: "Dumoulin, Vincent and Visin, Francesco", year: '2016',
journal: "arXiv preprint arXiv:1603.07285", url: 'https://arxiv.org/pdf/1603.07285.pdf'
year: "2016", }
url: "https://arxiv.org/pdf/1603.07285.pdf" ]])
}
]
])
}; };
const meta = distill.testing.transforms.get("Meta"); const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a("function"); expect(meta).to.be.a('function');
meta(dom.window.document, data); meta(dom.window.document, data);
const metaTags = [].slice.call( const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty; expect(metaTags).to.not.be.empty;
const metaTag = metaTags[0]; const metaTag = metaTags[0];
expect(metaTag).to.have.property("content"); expect(metaTag).to.have.property('content');
const content = metaTag.content; const content = metaTag.content;
expect(content).to.include("citation_title"); expect(content).to.include('citation_title');
expect(content).to.include("citation_author"); expect(content).to.include('citation_author');
expect(content.match(/citation_author=/g).length).to.equal(2); expect(content.match(/citation_author=/g).length).to.equal(2);
expect(content).to.include("citation_publication_date"); expect(content).to.include('citation_publication_date');
expect(content).to.include("citation_arxiv_id"); expect(content).to.include('citation_arxiv_id');
expect(content).to.not.include("journal"); expect(content).to.not.include('journal');
}); });
it("given only a DOM (and publish data), it should add Google scholar references information", function() { it('given only a DOM (and publish data), it should add Google scholar references information', function() {
const dom = new JSDOM( const dom = new JSDOM(`
`
<d-cite key="mercier2011humans">sth</d-cite> <d-cite key="mercier2011humans">sth</d-cite>
<d-bibliography> <d-bibliography>
<script type="text/bibtex"> <script type="text/bibtex">
@@ -270,28 +228,27 @@ describe("Distill V2 (transforms)", function() {
} }
</script> </script>
</d-bibliography> </d-bibliography>
`, `, options);
options
);
const data = { publishedDate: new Date(), updatedDate: new Date() }; const data = { publishedDate: new Date(), updatedDate: new Date() };
distill.render(dom.window.document, data, false); distill.render(dom.window.document, data, false);
const metaTags = [].slice.call( const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty; expect(metaTags).to.not.be.empty;
}); });
}); });
}); // render }); // render
it("should export #distillify()", function() { it('should export #distillify()', function() {
expect(distill.distillify).to.be.a("function"); expect(distill.distillify).to.be.a('function');
}); });
describe("#distillify()", function() { describe('#distillify()', function() {
it("should ensure existence of header");
it("should ensure existence of footer"); it('should ensure existence of header');
it("should ensure existence of distill appendix"); it('should ensure existence of footer');
it('should ensure existence of distill appendix');
}); });
}); // describe 'Transform' }); // describe 'Transform'