Compare commits

..

13 Commits

Author SHA1 Message Date
Ludwig Schubert 9be3faee20 2.6.0 2020-02-11 13:54:17 -08:00
Ludwig Schubert f95deb292e Update dependencies and minor rollup config change 2020-02-11 13:53:55 -08:00
Ludwig Schubert dccd48154b Fix bug discovered by Fred where katex in dev mode would interfere with svelte figures updating 2020-02-11 13:34:12 -08:00
Ludwig Schubert 0d6de08c82 2.5.1 2019-12-16 11:58:07 -08:00
Ludwig Schubert 9d253fdd33 Update citation helper to also support both "key" and "bibtex-key" attribute names 2019-12-16 11:57:53 -08:00
Ludwig Schubert 7fcd24a07b 2.5.0 2019-12-16 10:21:47 -08:00
Ludwig Schubert f569b07151 Add bibtex-key to d-cite for framework compatability 2019-12-16 10:21:38 -08:00
Ludwig Schubert 042da68b9a 2.4.3 2019-02-18 11:43:56 -08:00
Ludwig Schubert 4adbf9dcd2 Scope footer styles to avoid leaking them in pre-rendered mode 2019-02-18 11:43:45 -08:00
Ludwig Schubert f933920421 2.4.2 2019-02-15 17:35:55 -08:00
Ludwig Schubert cdfa045a36 Header prerendering now adds markup directly and adds distill-prerendered tag which TEMPLATE webcomponents now respect 2019-02-15 17:35:48 -08:00
Ludwig Schubert 5d83dbfd61 Add updated package-lock with hopefully some of the securoty warnings fixed 2019-02-06 21:09:46 -08:00
Ludwig Schubert 94510ee10b Switch debugging http server from python's http server to a http-server. 2019-02-06 21:07:06 -08:00
22 changed files with 4453 additions and 3837 deletions
+1 -43
View File
@@ -1,44 +1,2 @@
# 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
.DS_Store
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
View File
@@ -37,6 +37,7 @@ const options = { runScripts: 'outside-only', QuerySelector: true, virtualConsol
JSDOM.fromFile(program.inputPath, options).then(dom => {
const window = dom.window;
const document = window.document;
const HTMLElement = window.HTMLElement;
const data = new transforms.FrontMatter;
data.inputHTMLPath = program.inputPath; // may be needed to resolve relative links!
-149
View File
@@ -1,149 +0,0 @@
<!--
Copyright 2018 The Distill Template Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!doctype html>
<head>
<script src="../dist/template.v2.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" >
<meta charset="utf8">
</head>
<body>
<distill-header></distill-header>
<d-front-matter>
<script id='distill-front-matter' type="text/json">{
"title": "Why Momentum Really Works",
"description": "Although \" extremely useful for visualizing high-dimensional data, t-SNE plots can sometimes be mysterious or misleading.",
"published": "Jan 10, 2017",
"authors": [
{
"author":"Chris Olah",
"authorURL":"https://colah.github.io/",
"affiliations": [{"name": "Google Brain"}]
},
{
"author":"Ludwig Schubert",
"authorURL":"https://shancarter.com/",
"affiliations": [{"name": "Google Brain", "url": "https://g.co/brain"}]
},
{
"author":"Shan Carter",
"authorURL":"https://shancarter.com/",
"affiliations": [
{"name": "Google Brain", "url": "https://g.co/brain"},
{"name": "NYT", "url": "https://nytimes.com"}
]
}
],
"katex": {
"delimiters": [
{"left": "$$", "right": "$$", "display": false}
]
}
}</script>
</d-front-matter>
<d-title>
<figure style="grid-column: page; margin: 1rem 0;"><img src="momentum.png" style="width:100%; border: 1px solid rgba(0, 0, 0, 0.2);"/></figure>
<p>We often think of Momentum<d-cite key="mercier2011humans"></d-cite> as a means of dampening oscillations and speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p>
</d-title>
<d-byline></d-byline>
<d-article>
<a class="marker" href="#section-1" id="section-1"><span>1</span></a>
<h2>A Brief Survey of Techniques</h2>
<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>
<p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p>
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for diving.</p>
<aside>Some text in an aside, margin notes, etc...</aside>
<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>
<d-math block>
c = \pm \sqrt{ \sum_{i=0}^{n}{a^{222} + b^2}}
</d-math>
<p>Math can also be quite involved:</p>
<d-math block>
\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} } } }
</d-math>
<a class="marker" href="#section-1.1" id="section-1.1"><span>1.1</span></a>
<h3>Citations</h3>
<p><d-slider style="width: 200px;"></d-slider></p>
<p>We can<d-cite key="mercier2011humans"></d-cite> also cite <d-cite key="gregor2015draw,mercier2011humans,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;
function(x){
return x * x;
}
</d-code>
<p>We also support python.</p>
<d-code block language="python">
# Python 3: Fibonacci series up to n
def fib(n):
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
</d-code>
<p>And a table</p>
<table>
<thead>
<tr><th>First</th><th>Second</th><th>Third</th></tr>
</thead>
<tbody>
<tr><td>23</td><td>654</td><td>23</td></tr>
<tr><td>14</td><td>54</td><td>34</td></tr>
<tr><td>234</td><td>54</td><td>23</td></tr>
</tbody>
</table>
<d-figure id="last-figure"></d-figure>
<script>
const figure = document.querySelector("d-figure#last-figure");
const initTag = document.createElement("span");
initTag.textContent = "initialized!"
figure.appendChild(initTag);
figure.addEventListener("ready", function() {
const initTag = figure.querySelector("span");
initTag.textContent = "ready"
console.log('ready')
});
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-appendix>
<h3>Contributions</h3>
<p>Some text describing who did what.</p>
<h3>Reviewers</h3>
<p>Some text with links describing who reviewed the article.</p>
<d-bibliography src="bibliography.bib"></d-bibliography>
</d-appendix>
<distill-footer></distill-footer>
</body>
+183
View File
@@ -0,0 +1,183 @@
<!--
Copyright 2018 The Distill Template Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!doctype html>
<head>
<script src="template.v2.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf8">
</head>
<body>
<distill-header></distill-header>
<d-front-matter>
<script id='distill-front-matter' type="text/json">{
"title": "Why Momentum Really Works",
"description": "Although \" extremely useful for visualizing high-dimensional data, t-SNE plots can sometimes be mysterious or misleading.",
"published": "Jan 10, 2017",
"authors": [
{
"author":"Chris Olah",
"authorURL":"https://colah.github.io/",
"affiliations": [{"name": "Google Brain"}]
},
{
"author":"Ludwig Schubert",
"authorURL":"https://shancarter.com/",
"affiliations": [{"name": "Google Brain", "url": "https://g.co/brain"}]
},
{
"author":"Shan Carter",
"authorURL":"https://shancarter.com/",
"affiliations": [
{"name": "Google Brain", "url": "https://g.co/brain"},
{"name": "NYT", "url": "https://nytimes.com"}
]
}
],
"katex": {
"delimiters": [
{"left": "$$", "right": "$$", "display": false}
]
}
}</script>
</d-front-matter>
<d-title>
<figure style="grid-column: page; margin: 1rem 0;"><img src="momentum.png"
style="width:100%; border: 1px solid rgba(0, 0, 0, 0.2);" /></figure>
<p>We often think of Momentum<d-cite key="mercier2011humans"></d-cite> as a means of dampening oscillations and
speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a
larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p>
</d-title>
<d-byline></d-byline>
<d-article>
<a class="marker" href="#section-1" id="section-1"><span>1</span></a>
<h2>A Brief Survey of Techniques</h2>
<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>
<p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p>
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for
diving.</p>
<aside>Some text in an aside, margin notes, etc...</aside>
<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>
<d-math block>
c = \pm \sqrt{ \sum_{i=0}^{n}{a^{222} + b^2}}
</d-math>
<p>Math can also be quite involved:</p>
<d-math block>
\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} } } }
</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;
function(x){
return x * x;
}
</d-code>
<p>We also support python.</p>
<d-code block language="python">
# Python 3: Fibonacci series up to n
def fib(n):
a, b = 0, 1
while a < n: print(a, end=' ' ) a, b=b, a+b </d-code>
<p>And a table</p>
<table>
<thead>
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
</tr>
</thead>
<tbody>
<tr>
<td>23</td>
<td>654</td>
<td>23</td>
</tr>
<tr>
<td>14</td>
<td>54</td>
<td>34</td>
</tr>
<tr>
<td>234</td>
<td>54</td>
<td>23</td>
</tr>
</tbody>
</table>
<d-figure id="last-figure"></d-figure>
<script>
const figure = document.querySelector("d-figure#last-figure");
const initTag = document.createElement("span");
initTag.textContent = "initialized!"
figure.appendChild(initTag);
figure.addEventListener("ready", function () {
const initTag = figure.querySelector("span");
initTag.textContent = "ready"
console.log('ready')
});
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-appendix>
<h3>Contributions</h3>
<p>Some text describing who did what.</p>
<h3>Reviewers</h3>
<p>Some text with links describing who reviewed the article.</p>
<d-bibliography src="bibliography.bib"></d-bibliography>
</d-appendix>
<distill-footer></distill-footer>
</body>
-270
View File
@@ -1,270 +0,0 @@
<!--
Copyright 2018 The Distill Template Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!doctype html>
<meta charset="utf-8">
<script src="../dist/template.js"></script>
<style>
.fake-img {
background: #bbb;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 0px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 12px;
}
.fake-img p {
font-family: monospace;
color: white;
text-align: left;
margin: 12px 0;
text-align: center;
font-size: 16px;
}
</style>
<dt-article>
<h1>How to Create a Distill Article</h1>
<h2>A collection of examples and best practices for creating interactive explanatory articles using the Distill web framework</h2>
<hr>
<h2>Getting Started</h2>
<p>Distill ships with a CSS framework and a collection of custom web components that make building interactive academic articles easier than with raw HTML, CSS and JavaScript. At its simplest, each distill post is just a single HTML file with one special script tag.</p>
<dt-code block language="html">
&lt;!doctype html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="http://distill.pub/template.js"&gt;&lt;/script&gt;
&lt;dt-article&gt;
&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/dt-article&gt;
</dt-code>
<p>This script tag will modify your post in your browser, adding the distill styling and functionality. When we publish your article, we will bake in these transformations, but during development its handy to be able to preview it locally (It even works without a web server).</p>
<p>A typical distill post will be quite a bit longer than the one above. Below is a more complete example. Dont worry if some of the tags dont make sense, theyre all documented further in this post.</p>
<dt-code block language="html">
&lt;!doctype html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="http://distill.pub/template.js"&gt;&lt;/script&gt;
&lt;script type="text/front-matter"&gt;
title: Article Title
description: Description of the post
published: Jan 10, 2017
authors:
- Chris Olah: http://colah.github.io
- Shan Carter: http://shancarter.com
affiliations:
- Google Brain: http://g.co/brain
- Google Brain: http://g.co/brain
&lt;/script&gt;
&lt;dt-article&gt;
&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;h2&gt;A description of the article&lt;/h2&gt;
&lt;dt-byline&gt;&lt;/dt-byline&gt;
&lt;p&gt;This is the first paragraph of the article.&lt;/p&gt;
&lt;p&gt;We can also cite &lt;dt-cite key="gregor2015draw"&gt;&lt;/dt-cite&gt; external publications.&lt;/p&gt;
&lt;/dt-article&gt;
&lt;dt-appendix&gt;
&lt;/dt-appendix&gt;
&lt;script type="text/bibliography"&gt;
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf}
}
&lt;/script&gt;
</dt-code>
<!-- <hr>
<h2>Markdown</h2>
<p>Markdown is supported as an alternative to html for the <dt-code language="html">&lt;dt-article&gt;</dt-code> element. </p>
<dt-code block language="html">
&lt;!doctype html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="../dist/template.min.js"&gt;&lt;/script&gt;
&lt;dt-article markdown&gt;
# Hello World
## A description of the post
First paragraph of the article.
&lt;/dt-article&gt;
&lt;script type="text/bibliography"&gt;&lt;/script&gt;
</dt-code>
<p>We use <a href="https://github.com/chjj/marked">marked</a> as the rendering engine, with <a href="https://help.github.com/articles/basic-writing-and-formatting-syntax/">github flavored markdown</a> and <a href="https://daringfireball.net/projects/smartypants/">smartypants</a> enabled. In development mode the markdown is translated in the client after the dom content has loaded, but when published, the translation is precompiled.</p> -->
<hr>
<h2>Project Structure</h2>
<p>Because all the templating is delivered via a script tag, you are generally free to develop however you are most comfortable. The only requirements are that each article must be its own Github repository. The simplest setup would be a repository that contained a single HTML file, along with any additional assets, like images or javascript files. Note, in this default setup, all files in the root of the repository will be published. Note, also, in this configuration you generally will not even need to run a static local webserver. You can just open the <dt-code>index.html</dt-code> file in your browser to preview.</p>
<dt-code block language="html">
image.jpg
index.html
script.js
</dt-code>
<p>If you have a more complicated build process, or have files you dont want published, put your output in a <dt-code>public</dt-code> folder and we will only publish its contents.</p>
<dt-code block language="html">
build/
_index.html
package.json
public/
index.html
image.jpg
</dt-code>
<hr>
<h2>Front Matter</h2>
<p>Youll need to describe some data about you post — title, description, authors, etc. For this use the <dt-code language="html">&lt;script type="text/front-matter"&gt;</dt-code> tag.</p>
<dt-code block language="html">
&lt;script type="text/front-matter"&gt;
title: Article Title
description: Description of the post
authors:
- Chris Olah: http://colah.github.io
- Shan Carter: http://shancarter.com
affiliations:
- Google Brain: http://g.co/brain
- Google Brain: http://g.co/brain
&lt;/script&gt;
</dt-code>
<!-- <p>You can also use an external JSON file if you like. We will automatically make a request for a <dt-code>distill.json</dt-code> file if there is no <dt-code language="html">&lt;script type="text/front-matter"&gt;</dt-code> element on the page, or you can point to another file with the <dt-code>src</dt-code> attribute. In production, these files will be inlined into the document.</p>
<dt-code block language="html">
&lt;script type="text/front-matter" src="./distill.json"&gt;&lt;/script&gt;
</dt-code> -->
<hr>
<h2>Citations</h2>
<p>Bibtex is the supported way of making academic citations. You first need have a global definition of all your possible citations. For this well use the <dt-code language="html">&lt;script type="text/bibliography"&gt;</dt-code> element.</p>
<dt-code block language="html">
&lt;script type="text/bibliography"&gt;
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf},
}
&lt;/script&gt;
</dt-code>
<p>(We strongly encourage you to populate the <dt-code>url</dt-code> bibtex field where possible so that we can provide links for citations.)</p>
<!-- <p>Like with the <dt-code language="html">&lt;script type="text/front-matter"&gt;</dt-code> element, you can alternatively reference an external file with the <dt-code>src</dt-code> attribute. If no <dt-code language="html">&lt;script type="text/bibliography"&gt;</dt-code> element is found on the page, a request will automatically be made for <dt-code>bibliography.bib</dt-code>. In production, these files will be inlined into the document.</p>
<dt-code block language="html">
&lt;script type="text/bibliography" src="bibliography.bib"&gt;&lt;/script&gt;
</dt-code> -->
<p>Citations are then used in the article body with the <dt-code language="html">&lt;dt-cite&gt;</dt-code> tag. The <dt-code>key</dt-code> attribute is a reference to the id provided in the bibiography. The <dt-code>key</dt-code> attribute can take multiple ids, separated by commas.</p>
<dt-code block language="html">
&lt;dt-cite key="gregor2015draw"&gt;&lt;/dt-cite&gt;
</dt-code>
<script type="text/bibliography">
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf},
}
</script>
<p>The citation is presented inline like this: <dt-cite key="gregor2015draw"></dt-cite> (a number that displays more information on hover). If you have an appendix, a bibliography is automatically created and populated in it.</p>
<p>Distill chose a numerical inline citation style to improve readability of citation dense articles and because many of the benefits of longer citations are obviated by displaying more information on hover. However, we consider it good style to mention author last names if you discuss something at length and it fits into the flow well -- the authors are human and it's nice for them to have the community associate them with their work.</p>
<hr>
<h2>Footnotes</h2>
<p>Just wrap the text you would like to show up in a footnote in a <dt-code language="html">&lt;dt-fn&gt;</dt-code> tag. The number of the footnote will be automatically generated. <dt-fn>This text will be shown on hover.</dt-fn></p>
<dt-code block language="html">
&lt;dt-fn&gt;This will become a hoverable footnote.&lt;/dt-fn&gt;
</dt-code>
<dt-footnote-body ref="blah"></dt-footnote-body>
<hr>
<h2>Code Blocks</h2>
<p>Syntax highlighting is provided within <dt-code language="html">&lt;dt-code&gt;</dt-code> tags. An example of inline code snippets: <dt-code language="html">&lt;dt-code language="html"&gt;let x = 10;&lt;/dt-code&gt;</dt-code>. For larger blocks of code, add a <dt-code>block</dt-code> attribute:</p>
<dt-code block language="html">
&lt;dt-code block language="javascript"&gt;
var x = 25;
function(x){
return x * x;
}
&lt;/dt-code&gt;
</dt-code>
<!--
<hr>
<h2>Math</h2>
-->
<hr>
<h2>Layouts</h2>
<p>The main text column is referred to as the body. It is the assumed layout of any direct descendents of the <code>dt-article</code> element.</p>
<div class="fake-img l-body"><p>.l-body</p></div>
<p>For images you want to display a little larger, try these:</p>
<div class="fake-img l-middle"><p>.l-middle</p></div>
<div class="fake-img l-page"><p>.l-page</p></div>
<p>All of these have an <dt-code>outset</dt-code> variant if you want to poke out from the body text a little bit. For instance:</p>
<div class="fake-img l-body-outset"><p>.l-body-outset</p></div>
<div class="fake-img l-middle-outset"><p>.l-middle-outset</p></div>
<div class="fake-img l-page-outset"><p>.l-page-outset</p></div>
<p>Occasionally youll want to use the full browser width. For this, use <dt-code>.l-screen</dt-code>. You can also inset the element a little from the edge of the browser by using the inset variant.</p>
<div class="fake-img l-screen"><p>.l-screen</p></div>
<div class="fake-img l-screen-inset"><p>.l-screen-inset</p></div>
<p>Often you want to position smaller images so as not to completely interrupt the flow of your text. Or perhaps you want to put some text in the margin as an aside or to signal that its optional content. For these cases well use the float-based layouts.</p>
<div class="fake-img l-body side"><p>.l-body.side</p></div>
<div class="fake-img l-middle side"><p>.l-middle.side</p></div>
<div class="fake-img l-page side"><p>.l-page.side</p></div>
<p>They are all floated to the right and anchored to the right-hand edge of the position you specify. By default, each will take up approximately half of the width of the standard layout position, but you can override the width with a more specific selector. </p>
<div class="fake-img l-gutter"><p>.l-gutter</p></div>
<p>The final layout is for marginalia, asides, and footnotes. It does not interrupt the normal flow of <code>.l-body</code> sized text except on mobile screen sizes.</p>
<p>You can also use an alternate centered layout by adding a <dt-code>centered</dt-code> class to the <dt-code>dt-article</dt-code> element.</p>
<dt-code block language="html">
&lt;dt-article class="centered"&gt;
&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/dt-article&gt;
</dt-code>
<p>You can toggle it on this article by <a onclick="document.querySelector('dt-article').classList.toggle('centered');">clicking here</a></p>
<section class="centered">
</section>
<hr>
<h2>Appendix</h2>
<p>An appendix can be added after your article, using the <dt-code language="html">&lt;dt-appendix&gt;</dt-code> tag.</p>
<dt-code block language="html">
&lt;dt-article&gt;
...
&lt;/dt-article&gt;
&lt;dt-appendix&gt;
&lt;h3&gt;Appendix Section Title&lt;/h3&gt;
&lt;p&gt;section content&lt;p&gt;
&lt;/dt-appendix&gt;
</dt-code>
<p>You may wish to include the following sections in your appendix:</p>
<ul>
<li><b>Acknowledgments</b>: This is a place to recognize people and institutions. It may also be a good place to acknowledge and cite software that makes your work possible (eg. TensorFlow, OpenAI Gym).</li>
<li><b>Author Contributions</b>: We strongly encourage you to include an author contributions statement briefly describing what each author did.</li>
</ul>
<hr>
<h2>And Youre Off</h2>
<p>That should do it. If you have any questions or bugs to file, feel free to <a href="https://github.com/distillpub/template/issues/new">open an issue on GitHub</a>.</p>
<!--
<hr>
<h2>Including External Files</h2> -->
</dt-article>
+3572 -2818
View File
File diff suppressed because it is too large Load Diff
+23 -21
View File
@@ -1,6 +1,6 @@
{
"name": "distill-template",
"version": "2.4.1",
"version": "2.6.0",
"description": "Template for creating Distill articles.",
"main": "dist/template.v2.js",
"bin": {
@@ -13,7 +13,7 @@
},
"scripts": {
"dev": "rollup -c rollup.config.dev.js -w",
"serve": "python3 -m http.server --bind 127.0.0.1 8888",
"serve": "http-server",
"test": "mocha",
"lint": "eslint",
"build": "rollup -c rollup.config.js",
@@ -26,40 +26,42 @@
"devDependencies": {
"bibtex-parse-js": "^0.0.23",
"chai": "^3.5.0",
"eslint": "^4.3.0",
"eslint": "^4.19.1",
"eslint-config-google": "^0.9.1",
"js-yaml": "^3.7.0",
"http-server": "^0.11.1",
"js-yaml": "^3.13.1",
"jsdom": "11.3.0",
"jsdom-global": "3.0.2",
"marked": "^0.3.6",
"mocha": "^3.5.3",
"prismjs": "^1.6.0",
"rollup": "^0.50.0",
"rollup-plugin-babili": "^3.1.0",
"marked": "^0.8.0",
"mocha": "^5.2.0",
"prismjs": "^1.19.0",
"rollup": "^0.50.1",
"rollup-plugin-babili": "^3.1.1",
"rollup-plugin-buble": "^0.15.0",
"rollup-plugin-commonjs": "^7.0.0",
"rollup-plugin-copy": "^0.2.3",
"rollup-plugin-grapher": "^0.2.0",
"rollup-plugin-gzip": "^1.2.0",
"rollup-plugin-gzip": "^1.4.0",
"rollup-plugin-node-resolve": "^2.0.0",
"rollup-plugin-serve": "^0.1.0",
"rollup-plugin-serve": "^0.4.2",
"rollup-plugin-string": "^2.0.2",
"rollup-plugin-uglify": "^1.0.1",
"rollup-watch": "^2.5.0",
"should": "^13.1.2",
"should": "^13.2.3",
"source-map-support": "^0.5.16",
"webpack": "^2.2.1"
},
"dependencies": {
"@webcomponents/webcomponentsjs": "^1.0.7",
"assert": "^1.4.1",
"commander": "^2.9.0",
"d3-array": "^1.2.1",
"d3-drag": "^1.2.1",
"d3-scale": "^1.0.6",
"d3-selection": "^1.1.0",
"d3-time-format": "^2.0.3",
"@webcomponents/webcomponentsjs": "^1.3.3",
"assert": "^1.5.0",
"commander": "^2.20.3",
"d3-array": "^1.2.4",
"d3-drag": "^1.2.5",
"d3-scale": "^1.0.7",
"d3-selection": "^1.4.1",
"d3-time-format": "^2.2.3",
"escape-html": "^1.0.3",
"intersection-observer": "^0.4.0",
"intersection-observer": "^0.4.3",
"jsdom-wc": "^11.0.0-alpha-1",
"katex": "^0.8.3"
}
+32 -19
View File
@@ -12,23 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import resolve from 'rollup-plugin-node-resolve';
import string from 'rollup-plugin-string';
import commonjs from 'rollup-plugin-commonjs';
import buble from 'rollup-plugin-buble';
import resolve from "rollup-plugin-node-resolve";
import string from "rollup-plugin-string";
import commonjs from "rollup-plugin-commonjs";
import buble from "rollup-plugin-buble";
import serve from "rollup-plugin-serve";
// uncomment to show dependencies [1/2]
// import rollupGrapher from 'rollup-plugin-grapher'
const componentsConfig = {
input: 'src/components.js',
output: [{ format: 'umd', name: 'dl', file: 'dist/template.v2.js' }],
input: "src/components.js",
output: [{ format: "umd", name: "dl", file: "dist/template.v2.js" }]
};
const transformsConfig = {
input: 'src/transforms.js',
output: [{ format: 'umd', name: 'dl', file: 'dist/transforms.v2.js', globals: {fs: 'fs'} }],
external: ['fs']
input: "src/transforms.js",
output: [
{
format: "umd",
name: "dl",
file: "dist/transforms.v2.js",
globals: { fs: "fs" }
}
],
external: ["fs"]
};
const defaultConfig = {
@@ -36,13 +44,21 @@ const defaultConfig = {
plugins: [
resolve({
jsnext: true,
browser: true,
}),
string({
include: ['**/*.txt', '**/*.svg', '**/*.html', '**/*.css', '**/*.base64']
browser: true
}),
commonjs(),
string({
include: ["**/*.txt", "**/*.svg", "**/*.html", "**/*.css", "**/*.base64"]
}),
serve({
open: true,
openPage: "/examples/index.html",
contentBase: ["dist", "examples"],
headers: {
"Access-Control-Allow-Origin": "*"
},
port: 8088
})
]
};
@@ -52,7 +68,7 @@ Object.assign(transformsConfig, defaultConfig);
// transpile transforms so the node render script works…
transformsConfig.plugins.push(
buble({
target: { 'node': 6 }
target: { node: 6 }
})
);
@@ -64,7 +80,4 @@ transformsConfig.plugins.push(
// })
// );
export default [
componentsConfig,
transformsConfig,
];
export default [componentsConfig, transformsConfig];
+17 -10
View File
@@ -12,17 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import configs from './rollup.config.dev';
import babili from 'rollup-plugin-babili';
import configs from "./rollup.config.dev";
import babili from "rollup-plugin-babili";
function isNotServePlugin(plugin) {
return plugin.name !== "serve";
}
for (const config of configs) {
config.plugins = config.plugins.filter(isNotServePlugin);
}
const [componentsConfig, transformsConfig] = configs;
componentsConfig.plugins.push(babili({
comments: false, // means: *remove* comments
sourceMap: true,
}));
componentsConfig.plugins.push(
babili({
comments: false, // means: *remove* comments
sourceMap: true
})
);
export default [
componentsConfig,
transformsConfig,
];
export default [componentsConfig, transformsConfig];
+39 -33
View File
@@ -45,38 +45,41 @@ import { DistillHeader } from './distill-components/distill-header';
import { DistillAppendix } from './distill-components/distill-appendix';
import { DistillFooter } from './distill-components/distill-footer';
const distillMain = function() {
if (window.distillRunlevel < 1) {
throw new Error('Insufficient Runlevel for Distill Template!');
let templateIsLoading = false;
let runlevel = 0;
const initialize = function() {
if (window.distill.runlevel < 1) {
throw new Error("Insufficient Runlevel for Distill Template!");
}
/* 1. Flag that we're being loaded */
if ('distillTemplateIsLoading' in window && window.distillTemplateIsLoading) {
throw new Error('Runlevel 1: Distill Template is getting loaded more than once, aborting!');
if ("distill" in window && window.distill.templateIsLoading) {
throw new Error(
"Runlevel 1: Distill Template is getting loaded more than once, aborting!"
);
} else {
window.distillTemplateIsLoading = true;
console.debug('Runlevel 1: Distill Template has started loading.');
window.distill.templateIsLoading = true;
console.debug("Runlevel 1: Distill Template has started loading.");
}
/* 2. Add styles if they weren't added during prerendering */
makeStyleTag(document);
console.debug('Runlevel 1: Static Distill styles have been added.');
console.debug('Runlevel 1->2.');
window.distillRunlevel += 1;
console.debug("Runlevel 1: Static Distill styles have been added.");
console.debug("Runlevel 1->2.");
window.distill.runlevel += 1;
/* 3. Register Controller listener functions */
/* Needs to happen before components to their connected callbacks have a controller to talk to. */
for (const [functionName, callback] of Object.entries(Controller.listeners)) {
if (typeof callback === 'function') {
if (typeof callback === "function") {
document.addEventListener(functionName, callback);
} else {
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.debug('Runlevel 2->3.');
window.distillRunlevel += 1;
console.debug("Runlevel 2: We can now listen to controller events.");
console.debug("Runlevel 2->3.");
window.distill.runlevel += 1;
/* 4. Register components */
const components = [
@@ -85,22 +88,22 @@ const distillMain = function() {
Slider, Interstitial
];
const distillComponents = [
DistillHeader, DistillAppendix, DistillFooter,
];
const distillComponents = [DistillHeader, DistillAppendix, DistillFooter];
if (window.distillRunlevel < 2) {
throw new Error('Insufficient Runlevel for adding custom elements!');
if (window.distill.runlevel < 2) {
throw new Error("Insufficient Runlevel for adding custom elements!");
}
const allComponents = components.concat(distillComponents);
for (const component of allComponents) {
console.debug('Runlevel 2: Registering custom element: ' + component.is);
console.debug("Runlevel 2: Registering custom element: " + component.is);
customElements.define(component.is, component);
}
console.debug('Runlevel 3: Distill Template finished registering custom elements.');
console.debug('Runlevel 3->4.');
window.distillRunlevel += 1;
console.debug(
"Runlevel 3: Distill Template finished registering custom elements."
);
console.debug("Runlevel 3->4.");
window.distill.runlevel += 1;
// If template was added after DOMContentLoaded we may have missed that event.
// Controller will check for that case, so trigger the event explicitly:
@@ -108,17 +111,20 @@ const distillMain = function() {
Controller.listeners.DOMContentLoaded();
}
console.debug('Runlevel 4: Distill Template initialisation complete.');
console.debug("Runlevel 4: Distill Template initialisation complete.");
window.distill.templateIsLoading = false;
window.distill.templateHasLoaded = true;
};
window.distillRunlevel = 0;
window.distill = { runlevel, initialize, templateIsLoading };
/* 0. Check browser feature support; synchronously polyfill if needed */
if (Polyfills.browserSupportsAllFeatures()) {
console.debug('Runlevel 0: No need for polyfills.');
console.debug('Runlevel 0->1.');
window.distillRunlevel += 1;
distillMain();
console.debug("Runlevel 0: No need for polyfills.");
console.debug("Runlevel 0->1.");
window.distill.runlevel += 1;
window.distill.initialize();
} else {
console.debug('Runlevel 0: Distill Template is loading polyfills.');
Polyfills.load(distillMain);
console.debug("Runlevel 0: Distill Template is loading polyfills.");
Polyfills.load(window.distill.initialize);
}
+33 -27
View File
@@ -12,10 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Template } from '../mixins/template';
import { hover_cite, bibliography_cite } from '../helpers/citation';
import { Template } from "../mixins/template";
import { hover_cite, bibliography_cite } from "../helpers/citation";
const T = Template('d-cite', `
const T = Template(
"d-cite",
`
<style>
:host {
@@ -69,10 +71,10 @@ ul li:last-of-type {
<div id="citation-" class="citation">
<span class="citation-number"></span>
</div>
`);
`
);
export class Cite extends T(HTMLElement) {
/* Lifecycle */
constructor() {
super();
@@ -81,53 +83,55 @@ export class Cite extends T(HTMLElement) {
}
connectedCallback() {
this.outerSpan = this.root.querySelector('#citation-');
this.innerSpan = this.root.querySelector('.citation-number');
this.hoverBox = this.root.querySelector('d-hover-box');
window.customElements.whenDefined('d-hover-box').then(() => {
this.outerSpan = this.root.querySelector("#citation-");
this.innerSpan = this.root.querySelector(".citation-number");
this.hoverBox = this.root.querySelector("d-hover-box");
window.customElements.whenDefined("d-hover-box").then(() => {
this.hoverBox.listen(this);
});
// in case this component got connected after values were set
if (this.numbers) {
this.displayNumbers(this.numbers)
this.displayNumbers(this.numbers);
}
if (this.entries) {
this.displayEntries(this.entries)
this.displayEntries(this.entries);
}
}
//TODO This causes an infinite loop on firefox with polyfills.
// This is only needed for interactive editing so no priority.
// disconnectedCallback() {
// const options = { detail: [this, this.keys], bubbles: true };
// const event = new CustomEvent('onCiteKeyRemoved', options);
// document.dispatchEvent(event);
// const options = { detail: [this, this.keys], bubbles: true };
// const event = new CustomEvent('onCiteKeyRemoved', options);
// document.dispatchEvent(event);
// }
/* observe 'key' attribute */
static get observedAttributes() {
return ['key'];
return ["key", "bibtex-key"];
}
attributeChangedCallback(name, oldValue, newValue) {
const eventName = oldValue ? 'onCiteKeyChanged' : 'onCiteKeyCreated';
const keys = newValue.split(',').map(k => k.trim());
const eventName = oldValue ? "onCiteKeyChanged" : "onCiteKeyCreated";
const keys = newValue.split(",").map(k => k.trim());
const options = { detail: [this, keys], bubbles: true };
const event = new CustomEvent(eventName, options);
document.dispatchEvent(event);
}
set key(value) {
this.setAttribute('key', value);
this.setAttribute("key", value);
}
get key() {
return this.getAttribute('key');
return this.getAttribute("key") || this.getAttribute("bibtex-key");
}
get keys() {
return this.getAttribute('key').split(',');
const result = this.key.split(",");
console.log(result);
return result;
}
/* Setters & Rendering */
@@ -143,16 +147,16 @@ export class Cite extends T(HTMLElement) {
displayNumbers(numbers) {
if (!this.innerSpan) return;
const numberStrings = numbers.map( index => {
return index == -1 ? '?' : index + 1 + '';
const numberStrings = numbers.map(index => {
return index == -1 ? "?" : index + 1 + "";
});
const textContent = '[' + numberStrings.join(', ') + ']';
const textContent = "[" + numberStrings.join(", ") + "]";
this.innerSpan.textContent = textContent;
}
set entries(entries) {
this._entries = entries;
this.displayEntries(entries)
this.displayEntries(entries);
}
get entries() {
@@ -160,10 +164,12 @@ export class Cite extends T(HTMLElement) {
}
displayEntries(entries) {
if (!this.hoverBox) return
if (!this.hoverBox) return;
this.hoverBox.innerHTML = `<ul>
${entries.map(hover_cite).map(html => `<li>${html}</li>`).join('\n')}
${entries
.map(hover_cite)
.map(html => `<li>${html}</li>`)
.join("\n")}
</ul>`;
}
}
+62 -50
View File
@@ -12,45 +12,46 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { FrontMatter, mergeFromYMLFrontmatter } from './front-matter';
import { DMath } from './components/d-math';
import { collect_citations } from './helpers/citation.js';
import { domContentLoaded } from './helpers/domContentLoaded.js';
import { parseFrontmatter } from './components/d-front-matter';
import optionalComponents from './transforms/optional-components';
import { FrontMatter, mergeFromYMLFrontmatter } from "./front-matter";
import { DMath } from "./components/d-math";
import { collect_citations } from "./helpers/citation.js";
import { domContentLoaded } from "./helpers/domContentLoaded.js";
import { parseFrontmatter } from "./components/d-front-matter";
import optionalComponents from "./transforms/optional-components";
const frontMatter = new FrontMatter();
export const Controller = {
frontMatter: frontMatter,
waitingOn: {
bibliography: [],
citations: [],
citations: []
},
listeners: {
onCiteKeyCreated(event) {
const [citeTag, keys] = event.detail;
// ensure we have citations
if (!frontMatter.citationsCollected) {
// console.debug('onCiteKeyCreated, but unresolved dependency ("citations"). Enqueing.');
Controller.waitingOn.citations.push(() => Controller.listeners.onCiteKeyCreated(event));
Controller.waitingOn.citations.push(() =>
Controller.listeners.onCiteKeyCreated(event)
);
return;
}
// ensure we have a loaded bibliography
if (!frontMatter.bibliographyParsed) {
// console.debug('onCiteKeyCreated, but unresolved dependency ("bibliography"). Enqueing.');
Controller.waitingOn.bibliography.push(() => Controller.listeners.onCiteKeyCreated(event));
Controller.waitingOn.bibliography.push(() =>
Controller.listeners.onCiteKeyCreated(event)
);
return;
}
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
const numbers = keys.map(key => frontMatter.citations.indexOf(key));
citeTag.numbers = numbers;
const entries = keys.map( key => frontMatter.bibliography.get(key) );
const entries = keys.map(key => frontMatter.bibliography.get(key));
citeTag.entries = entries;
},
@@ -65,21 +66,23 @@ export const Controller = {
}
// update bibliography
const citationListTag = document.querySelector('d-citation-list');
const bibliographyEntries = new Map(frontMatter.citations.map( citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
}));
const citationListTag = document.querySelector("d-citation-list");
const bibliographyEntries = new Map(
frontMatter.citations.map(citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
})
);
citationListTag.citations = bibliographyEntries;
const citeTags = document.querySelectorAll('d-cite');
const citeTags = document.querySelectorAll("d-cite");
for (const citeTag of citeTags) {
console.log(citeTag);
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;
const entries = keys.map( key => frontMatter.bibliography.get(key) );
const entries = keys.map(key => frontMatter.bibliography.get(key));
citeTag.entries = entries;
}
},
onCiteKeyRemoved(event) {
@@ -87,7 +90,7 @@ export const Controller = {
},
onBibliographyChanged(event) {
const citationListTag = document.querySelector('d-citation-list');
const citationListTag = document.querySelector("d-citation-list");
const bibliography = event.detail;
@@ -99,19 +102,23 @@ export const Controller = {
// ensure we have citations
if (!frontMatter.citationsCollected) {
Controller.waitingOn.citations.push( function() {
Controller.listeners.onBibliographyChanged({target: event.target, detail: event.detail});
Controller.waitingOn.citations.push(function() {
Controller.listeners.onBibliographyChanged({
target: event.target,
detail: event.detail
});
});
return;
}
if (citationListTag.hasAttribute('distill-prerendered')) {
console.debug('Citation list was prerendered; not updating it.');
if (citationListTag.hasAttribute("distill-prerendered")) {
console.debug("Citation list was prerendered; not updating it.");
} else {
const entries = new Map(frontMatter.citations.map( citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
}));
const entries = new Map(
frontMatter.citations.map(citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
})
);
citationListTag.citations = entries;
}
},
@@ -119,9 +126,9 @@ export const Controller = {
onFootnoteChanged() {
// const footnote = event.detail;
//TODO: optimize to only update current footnote
const footnotesList = document.querySelector('d-footnote-list');
const footnotesList = document.querySelector("d-footnote-list");
if (footnotesList) {
const footnotes = document.querySelectorAll('d-footnote');
const footnotes = document.querySelectorAll("d-footnote");
footnotesList.footnotes = footnotes;
}
},
@@ -130,25 +137,25 @@ export const Controller = {
const data = event.detail;
mergeFromYMLFrontmatter(frontMatter, data);
const interstitial = document.querySelector('d-interstitial');
const interstitial = document.querySelector("d-interstitial");
if (interstitial) {
if (typeof frontMatter.password !== 'undefined') {
if (typeof frontMatter.password !== "undefined") {
interstitial.password = frontMatter.password;
} else {
interstitial.parentElement.removeChild(interstitial);
}
}
const prerendered = document.body.hasAttribute('distill-prerendered');
const prerendered = document.body.hasAttribute("distill-prerendered");
if (!prerendered && domContentLoaded()) {
optionalComponents(document, frontMatter);
const appendix = document.querySelector('distill-appendix');
const appendix = document.querySelector("distill-appendix");
if (appendix) {
appendix.frontMatter = frontMatter;
}
const byline = document.querySelector('d-byline');
const byline = document.querySelector("d-byline");
if (byline) {
byline.frontMatter = frontMatter;
}
@@ -157,24 +164,31 @@ export const Controller = {
DMath.katexOptions = data.katex;
}
}
},
DOMContentLoaded() {
if (Controller.loaded) {
console.warn('Controller received DOMContentLoaded but was already loaded!');
console.warn(
"Controller received DOMContentLoaded but was already loaded!"
);
return;
} else if (!domContentLoaded()) {
console.warn('Controller received DOMContentLoaded at document.readyState: ' + document.readyState + '!');
console.warn(
"Controller received DOMContentLoaded at document.readyState: " +
document.readyState +
"!"
);
return;
} else {
Controller.loaded = true;
console.debug('Runlevel 4: Controller running DOMContentLoaded');
console.debug("Runlevel 4: Controller running DOMContentLoaded");
}
const frontMatterTag = document.querySelector('d-front-matter');
const data = parseFrontmatter(frontMatterTag);
Controller.listeners.onFrontMatterChanged({detail: data});
const frontMatterTag = document.querySelector("d-front-matter");
if (frontMatterTag) {
const data = parseFrontmatter(frontMatterTag);
Controller.listeners.onFrontMatterChanged({ detail: data });
}
// Resolving "citations" dependency due to initial DOM load
frontMatter.citations = collect_citations();
@@ -189,13 +203,11 @@ export const Controller = {
}
}
const footnotesList = document.querySelector('d-footnote-list');
const footnotesList = document.querySelector("d-footnote-list");
if (footnotesList) {
const footnotes = document.querySelectorAll('d-footnote');
const footnotes = document.querySelectorAll("d-footnote");
footnotesList.footnotes = footnotes;
}
}
}, // listeners
} // listeners
}; // Controller
@@ -0,0 +1,74 @@
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>
`;
+2 -72
View File
@@ -13,80 +13,10 @@
// limitations under the License.
import { Template } from '../mixins/template';
import logo from '../assets/distill-logo.svg';
const T = Template('distill-footer', `
<style>
import {footerTemplate} from './distill-footer-template';
: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>
`);
const T = Template('distill-footer', footerTemplate);
export class DistillFooter extends T(HTMLElement) {
@@ -0,0 +1,79 @@
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>
`;
+2 -79
View File
@@ -14,86 +14,9 @@
import { Template } from '../mixins/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);
import {headerTemplate} from './distill-header-template';
const T = Template('distill-header', headerTemplate, false);
export class DistillHeader extends T(HTMLElement) {
+3
View File
@@ -12,10 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { footerTemplate } from '../distill-components/distill-footer-template';
export default function(dom) {
const footerTag = dom.querySelector('distill-footer');
if(!footerTag) {
const footer = dom.createElement('distill-footer');
footer.innerHTML = footerTemplate;
const body = dom.querySelector('body');
body.appendChild(footer);
}
+6 -1
View File
@@ -12,10 +12,15 @@
// See the License for the specific language governing permissions and
// 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');
if (!headerTag) {
const header = dom.createElement('distill-header');
header.innerHTML = headerTemplate;
header.setAttribute('distill-prerendered', "");
const body = dom.querySelector('body');
body.insertBefore(header, body.firstChild);
}
+104 -89
View File
@@ -12,11 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
export function collect_citations(dom=document) {
export function collect_citations(dom = document) {
const citations = new Set();
const citeTags = dom.querySelectorAll('d-cite');
const citeTags = dom.querySelectorAll("d-cite");
for (const tag of citeTags) {
const keys = tag.getAttribute('key').split(',');
const keyString = tag.getAttribute("key") || tag.getAttribute("bibtex-key");
const keys = keyString.split(",").map(k => k.trim());
for (const key of keys) {
citations.add(key);
}
@@ -24,62 +25,74 @@ export function collect_citations(dom=document) {
return [...citations];
}
export function inline_cite_short(keys){
function cite_string(key){
if (key in data.bibliography){
var n = data.citations.indexOf(key)+1;
return ''+n;
export function inline_cite_short(keys) {
function cite_string(key) {
if (key in data.bibliography) {
var n = data.citations.indexOf(key) + 1;
return "" + n;
} else {
return '?';
return "?";
}
}
return '['+keys.map(cite_string).join(', ')+']';
return "[" + keys.map(cite_string).join(", ") + "]";
}
export function inline_cite_long(keys){
function cite_string(key){
if (key in data.bibliography){
export function inline_cite_long(keys) {
function cite_string(key) {
if (key in data.bibliography) {
var ent = data.bibliography[key];
var names = ent.author.split(' and ');
names = names.map(name => name.split(',')[0].trim());
var names = ent.author.split(" and ");
names = names.map(name => name.split(",")[0].trim());
var year = ent.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] + ', et al., ' + 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] + ", et al., " + year;
} else {
return '?';
return "?";
}
}
return keys.map(cite_string).join(', ');
return keys.map(cite_string).join(", ");
}
function author_string(ent, template, sep, finalSep){
if (ent.author == null) { return ''; }
var names = ent.author.split(' and ');
function author_string(ent, template, sep, finalSep) {
if (ent.author == null) {
return "";
}
var names = ent.author.split(" and ");
let name_strings = names.map(name => {
name = name.trim();
if (name.indexOf(',') != -1){
var last = name.split(',')[0].trim();
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(' ');
if (name.indexOf(",") != -1) {
var last = name.split(",")[0].trim();
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 {
var last = name.trim();
}
var initials = '';
var initials = "";
if (firsts != undefined) {
initials = firsts.trim().split(' ').map(s => s.trim()[0]);
initials = initials.join('.')+'.';
initials = firsts
.trim()
.split(" ")
.map(s => s.trim()[0]);
initials = initials.join(".") + ".";
}
return template.replace('${F}', firsts)
.replace('${L}', last)
.replace('${I}', initials)
return template
.replace("${F}", firsts)
.replace("${L}", last)
.replace("${I}", initials)
.trim(); // in case one of first or last was empty
});
if (names.length > 1) {
var str = name_strings.slice(0, names.length-1).join(sep);
str += (finalSep || sep) + name_strings[names.length-1];
var str = name_strings.slice(0, names.length - 1).join(sep);
str += (finalSep || sep) + name_strings[names.length - 1];
return str;
} else {
return name_strings[0];
@@ -87,69 +100,71 @@ function author_string(ent, template, sep, finalSep){
}
function venue_string(ent) {
var cite = (ent.journal || ent.booktitle || '');
if ('volume' in ent){
var cite = ent.journal || ent.booktitle || "";
if ("volume" in ent) {
var issue = ent.issue || ent.number;
issue = (issue != undefined)? '('+issue+')' : '';
cite += ', Vol ' + ent.volume + issue;
issue = issue != undefined ? "(" + issue + ")" : "";
cite += ", Vol " + ent.volume + issue;
}
if ('pages' in ent){
cite += ', pp. ' + ent.pages;
if ("pages" in ent) {
cite += ", pp. " + ent.pages;
}
if (cite != '') cite += '. ';
if ('publisher' in ent){
if (cite != "") cite += ". ";
if ("publisher" in ent) {
cite += ent.publisher;
if (cite[cite.length-1] != '.') cite += '.';
if (cite[cite.length - 1] != ".") cite += ".";
}
return cite;
}
function link_string(ent){
if ('url' in ent){
function link_string(ent) {
if ("url" in ent) {
var url = ent.url;
var arxiv_match = (/arxiv\.org\/abs\/([0-9\.]*)/).exec(url);
if (arxiv_match != null){
var arxiv_match = /arxiv\.org\/abs\/([0-9\.]*)/.exec(url);
if (arxiv_match != null) {
url = `http://arxiv.org/pdf/${arxiv_match[1]}.pdf`;
}
if (url.slice(-4) == '.pdf'){
var label = 'PDF';
} else if (url.slice(-5) == '.html') {
var label = 'HTML';
if (url.slice(-4) == ".pdf") {
var label = "PDF";
} else if (url.slice(-5) == ".html") {
var label = "HTML";
}
return ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="${url}">[${label || "link"}]</a>`;
} /* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
return "";
}
}
function doi_string(ent, new_line){
if ('doi' in ent) {
return `${new_line?'<br>':''} <a href="https://doi.org/${ent.doi}" style="text-decoration:inherit;">DOI: ${ent.doi}</a>`;
function doi_string(ent, new_line) {
if ("doi" in ent) {
return `${new_line ? "<br>" : ""} <a href="https://doi.org/${
ent.doi
}" style="text-decoration:inherit;">DOI: ${ent.doi}</a>`;
} else {
return '';
return "";
}
}
function title_string(ent) {
return '<span class="title">' + ent.title + '</span> ';
return '<span class="title">' + ent.title + "</span> ";
}
export function bibliography_cite(ent, fancy){
if (ent){
export function bibliography_cite(ent, fancy) {
if (ent) {
var cite = title_string(ent);
cite += link_string(ent) + '<br>';
cite += link_string(ent) + "<br>";
if (ent.author) {
cite += author_string(ent, '${L}, ${I}', ', ', ' and ');
cite += author_string(ent, "${L}, ${I}", ", ", " and ");
if (ent.year || ent.date) {
cite += ', ';
cite += ", ";
}
}
if (ent.year || ent.date) {
cite += (ent.year || ent.date) + '. ';
cite += (ent.year || ent.date) + ". ";
} else {
cite += '. ';
cite += ". ";
}
cite += venue_string(ent);
cite += doi_string(ent);
@@ -166,39 +181,39 @@ export function bibliography_cite(ent, fancy){
cite += link_string(ent);
return cite*/
} else {
return '?';
return "?";
}
}
export function hover_cite(ent){
if (ent){
var cite = '';
cite += '<strong>' + ent.title + '</strong>';
export function hover_cite(ent) {
if (ent) {
var cite = "";
cite += "<strong>" + ent.title + "</strong>";
cite += link_string(ent);
cite += '<br>';
cite += "<br>";
var a_str = author_string(ent, '${I} ${L}', ', ') + '.';
var v_str = venue_string(ent).trim() + ' ' + ent.year + '. ' + doi_string(ent, true);
var a_str = author_string(ent, "${I} ${L}", ", ") + ".";
var v_str =
venue_string(ent).trim() + " " + ent.year + ". " + doi_string(ent, true);
if ((a_str+v_str).length < Math.min(40, ent.title.length)) {
cite += a_str + ' ' + v_str;
if ((a_str + v_str).length < Math.min(40, ent.title.length)) {
cite += a_str + " " + v_str;
} else {
cite += a_str + '<br>' + v_str;
cite += a_str + "<br>" + v_str;
}
return cite;
} else {
return '?';
return "?";
}
}
//https://scholar.google.com/scholar?q=allintitle%3ADocument+author%3Aolah
function get_GS_URL(ent){
if (ent){
var names = ent.author.split(' and ');
names = names.map(name => name.split(',')[0].trim());
var title = ent.title.split(' ');//.replace(/[,:]/, "")
var url = 'http://search.labs.crossref.org/dois?';//""https://scholar.google.com/scholar?"
url += uris({q: names.join(' ') + ' ' + title.join(' ')});
function get_GS_URL(ent) {
if (ent) {
var names = ent.author.split(" and ");
names = names.map(name => name.split(",")[0].trim());
var title = ent.title.split(" "); //.replace(/[,:]/, "")
var url = "http://search.labs.crossref.org/dois?"; //""https://scholar.google.com/scholar?"
url += uris({ q: names.join(" ") + " " + title.join(" ") });
}
}
+60 -42
View File
@@ -28,14 +28,16 @@ const findEndOfMath = function(delimiter, text, startIndex) {
while (index < text.length) {
const character = text[index];
if (braceLevel <= 0 &&
text.slice(index, index + delimLength) === delimiter) {
if (
braceLevel <= 0 &&
text.slice(index, index + delimLength) === delimiter
) {
return index;
} else if (character === '\\') {
} else if (character === "\\") {
index++;
} else if (character === '{') {
} else if (character === "{") {
braceLevel++;
} else if (character === '}') {
} else if (character === "}") {
braceLevel--;
}
@@ -49,7 +51,7 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
const finalData = [];
for (let i = 0; i < startData.length; i++) {
if (startData[i].type === 'text') {
if (startData[i].type === "text") {
const text = startData[i].data;
let lookingForLeft = true;
@@ -60,13 +62,14 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
if (nextIndex !== -1) {
currIndex = nextIndex;
finalData.push({
type: 'text',
data: text.slice(0, currIndex),
type: "text",
data: text.slice(0, currIndex)
});
lookingForLeft = false;
}
while (true) { // eslint-disable-line no-constant-condition
while (true) {
// eslint-disable-line no-constant-condition
if (lookingForLeft) {
nextIndex = text.indexOf(leftDelim, currIndex);
if (nextIndex === -1) {
@@ -74,8 +77,8 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
}
finalData.push({
type: 'text',
data: text.slice(currIndex, nextIndex),
type: "text",
data: text.slice(currIndex, nextIndex)
});
currIndex = nextIndex;
@@ -83,20 +86,17 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
nextIndex = findEndOfMath(
rightDelim,
text,
currIndex + leftDelim.length);
currIndex + leftDelim.length
);
if (nextIndex === -1) {
break;
}
finalData.push({
type: 'math',
data: text.slice(
currIndex + leftDelim.length,
nextIndex),
rawData: text.slice(
currIndex,
nextIndex + rightDelim.length),
display: display,
type: "math",
data: text.slice(currIndex + leftDelim.length, nextIndex),
rawData: text.slice(currIndex, nextIndex + rightDelim.length),
display: display
});
currIndex = nextIndex + rightDelim.length;
@@ -106,8 +106,8 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
}
finalData.push({
type: 'text',
data: text.slice(currIndex),
type: "text",
data: text.slice(currIndex)
});
} else {
finalData.push(startData[i]);
@@ -117,14 +117,16 @@ const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
return finalData;
};
const splitWithDelimiters = function(text, delimiters) {
let data = [{type: 'text', data: text}];
let data = [{ type: "text", data: text }];
for (let i = 0; i < delimiters.length; i++) {
const delimiter = delimiters[i];
data = splitAtDelimiters(
data, delimiter.left, delimiter.right,
delimiter.display || false);
data,
delimiter.left,
delimiter.right,
delimiter.display || false
);
}
return data;
};
@@ -137,10 +139,10 @@ const renderMathInText = function(text, optionsCopy) {
const fragment = document.createDocumentFragment();
for (let i = 0; i < data.length; i++) {
if (data[i].type === 'text') {
if (data[i].type === "text") {
fragment.appendChild(document.createTextNode(data[i].data));
} else {
const tag = document.createElement('d-math');
const tag = document.createElement("d-math");
const math = data[i].data;
// Override any display mode defined in the settings with that
// defined by the text itself
@@ -148,15 +150,14 @@ const renderMathInText = function(text, optionsCopy) {
try {
tag.textContent = math;
if (optionsCopy.displayMode) {
tag.setAttribute('block', '');
tag.setAttribute("block", "");
}
} catch (e) {
if (!(e instanceof katex.ParseError)) {
throw e;
}
optionsCopy.errorCallback(
'KaTeX auto-render: Failed to parse `' + data[i].data +
'` with ',
"KaTeX auto-render: Failed to parse `" + data[i].data + "` with ",
e
);
fragment.appendChild(document.createTextNode(data[i].rawData));
@@ -174,13 +175,17 @@ const renderElem = function(elem, optionsCopy) {
const childNode = elem.childNodes[i];
if (childNode.nodeType === 3) {
// Text node
const frag = renderMathInText(childNode.textContent, optionsCopy);
i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode);
const text = childNode.textContent;
if (optionsCopy.mightHaveMath(text)) {
const frag = renderMathInText(text, optionsCopy);
i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode);
}
} else if (childNode.nodeType === 1) {
// Element node
const shouldRender = optionsCopy.ignoredTags.indexOf(
childNode.nodeName.toLowerCase()) === -1;
const shouldRender =
optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) ===
-1;
if (shouldRender) {
renderElem(childNode, optionsCopy);
@@ -192,27 +197,40 @@ const renderElem = function(elem, optionsCopy) {
const defaultAutoRenderOptions = {
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '\\[', right: '\\]', display: true},
{left: '\\(', right: '\\)', display: false},
{ left: "$$", right: "$$", display: true },
{ left: "\\[", right: "\\]", display: true },
{ left: "\\(", right: "\\)", display: false }
// LaTeX uses this, but it ruins the display of normal `$` in text:
// {left: '$', right: '$', display: false},
],
ignoredTags: [
'script', 'noscript', 'style', 'textarea', 'pre', 'code', 'svg',
"script",
"noscript",
"style",
"textarea",
"pre",
"code",
"svg"
],
errorCallback: function(msg, err) {
console.error(msg, err);
},
}
};
export const renderMathInElement = function(elem, options) {
if (!elem) {
throw new Error('No element provided to render');
throw new Error("No element provided to render");
}
const optionsCopy = Object.assign({}, defaultAutoRenderOptions, options);
const delimiterStrings = optionsCopy.delimiters.flatMap(d => [
d.left,
d.right
]);
const mightHaveMath = text =>
delimiterStrings.some(d => text.indexOf(d) !== -1);
optionsCopy.mightHaveMath = mightHaveMath;
renderElem(elem, optionsCopy);
};
+3
View File
@@ -40,6 +40,9 @@ export const Template = (name, templateString, useShadow = true) => {
}
connectedCallback() {
if (this.hasAttribute('distill-prerendered')) {
return;
}
if (useShadow) {
if ('ShadyCSS' in window) {
ShadyCSS.styleElement(this);
+157 -114
View File
@@ -14,75 +14,88 @@
/* global it, describe, before, beforeEach, after, afterEach */
const jsdom = require('jsdom');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const expect = require('chai').expect;
const distill = require('../dist/transforms.v2.js');
const expect = require("chai").expect;
const distill = require("../dist/transforms.v2.js");
// omitJSDOMErrors as JSDOM routinely can't parse modern CSS
const virtualConsole = new jsdom.VirtualConsole();
virtualConsole.sendTo(console, { omitJSDOMErrors: true });
const options = { runScripts: 'outside-only', QuerySelector: true, virtualConsole: virtualConsole };
const options = {
runScripts: "outside-only",
QuerySelector: true,
virtualConsole: virtualConsole
};
describe('Distill V2 (transforms)', function() {
it('should export its expected interface', function() {
expect(distill.testing).to.be.an('object');
expect(distill.usesTemplateV2).to.be.a('function');
expect(distill.render).to.be.a('function');
expect(distill.distillify).to.be.a('function');
describe("Distill V2 (transforms)", function() {
it("should export its expected interface", function() {
expect(distill.testing).to.be.an("object");
expect(distill.usesTemplateV2).to.be.a("function");
expect(distill.render).to.be.a("function");
expect(distill.distillify).to.be.a("function");
});
describe('#usesTemplateV2()', function() {
it('should detect v1', function() {
const frag = JSDOM.fragment('<script src="https://distill.pub/template.v1.js"></script>');
describe("#usesTemplateV2()", function() {
it("should detect v1", function() {
const frag = JSDOM.fragment(
'<script src="https://distill.pub/template.v1.js"></script>'
);
expect(distill.usesTemplateV2(frag)).to.be.false;
});
it('should detect v2', function() {
const frag = JSDOM.fragment('<script src="https://distill.pub/template.v2.js"></script>');
it("should detect v2", function() {
const frag = JSDOM.fragment(
'<script src="https://distill.pub/template.v2.js"></script>'
);
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>');
expect(distill.usesTemplateV2(frag)).to.be.true;
});
it('should error on unknown distill script', function() {
const frag = JSDOM.fragment('<script src="https://distill.pub/template.v42.js"></script>');
expect(()=> distill.usesTemplateV2(frag)).to.throw('unknown');
it("should error on unknown distill script", function() {
const frag = JSDOM.fragment(
'<script src="https://distill.pub/template.v42.js"></script>'
);
expect(() => distill.usesTemplateV2(frag)).to.throw("unknown");
});
it('should error on no distill script', function() {
const frag = JSDOM.fragment('<script src="https://code.jquery.com/jquery-3.2.1.js"></script>');
expect(()=> distill.usesTemplateV2(frag)).to.throw('at all');
it("should error on no distill script", function() {
const frag = JSDOM.fragment(
'<script src="https://code.jquery.com/jquery-3.2.1.js"></script>'
);
expect(() => distill.usesTemplateV2(frag)).to.throw("at all");
});
});
describe('#render()', function() {
describe('should extract metadata', function() {
it('should extract citations', function() {
const dom = new JSDOM('<d-cite key="test-citation-key">sth</d-cite>', options);
describe("#render()", function() {
describe("should extract metadata", function() {
it("should extract citations", function() {
const dom = new JSDOM(
'<d-cite key="test-citation-key">sth</d-cite>',
options
);
const data = {};
const extractCitations = distill.testing.extractors.get('ExtractCitations');
expect(extractCitations).to.be.a('function');
const extractCitations = distill.testing.extractors.get(
"ExtractCitations"
);
expect(extractCitations).to.be.a("function");
extractCitations(dom.window.document, data);
expect(data).to.have.property('citations');
expect(data).to.have.property("citations");
const citations = data.citations;
expect(citations).to.be.an.instanceof(Array);
expect(citations).to.have.lengthOf(1);
const citation = citations[0];
expect(citation).to.equal('test-citation-key');
expect(citation).to.equal("test-citation-key");
});
it('should extract bibliography', function() {
const dom = new JSDOM(`
it("should extract bibliography", function() {
const dom = new JSDOM(
`
<d-cite key="mercier2011humans">sth</d-cite>
<d-bibliography>
<script type="text/bibtex">
@@ -99,44 +112,58 @@ describe('Distill V2 (transforms)', function() {
}
</script>
</d-bibliography>
`, options);
`,
options
);
const data = {};
const extractBibliography = distill.testing.extractors.get('ExtractBibliography');
const extractBibliography = distill.testing.extractors.get(
"ExtractBibliography"
);
extractBibliography(dom.window.document, data);
expect(data.bibliography).to.be.an.instanceof(Map);
const entry = data.bibliography.get('mercier2011humans');
expect(entry).to.be.an('object');
expect(entry).to.have.property('year', '2011');
const entry = data.bibliography.get("mercier2011humans");
expect(entry).to.be.an("object");
expect(entry).to.have.property("year", "2011");
});
it('should extract front-matter');
it("should extract front-matter");
}); // metadata
describe('should transform the DOM', function() {
it('should add Google scholar citation information', function() {
const dom = new JSDOM('', options);
describe("should transform the DOM", function() {
it("should add Google scholar citation information", function() {
const dom = new JSDOM("", options);
const data = {
authors: [
{firstName: 'Frank', lastName: 'Underwood', affiliation: 'Google Brain', affiliationURL: 'https://g.co/brain'},
{firstName: 'Shan', lastName: 'Carter', affiliation: 'Google Brain', affiliationURL: 'https://g.co/brain'},
{
firstName: "Frank",
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 = data.authors[0].firstName + ' ' + data.authors[0].lastName;
const GSfirstAuthorName = data.authors[0].lastName + ', ' + data.authors[0].firstName;
const firstAuthorName =
data.authors[0].firstName + " " + data.authors[0].lastName;
const GSfirstAuthorName =
data.authors[0].lastName + ", " + data.authors[0].firstName;
const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a('function');
const meta = distill.testing.transforms.get("Meta");
expect(meta).to.be.a("function");
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;
// Google Scholar
const GSAuthorTags = Array.prototype.filter.call(metaTags, (tag) => {
return tag.name === 'citation_author';
const GSAuthorTags = Array.prototype.filter.call(metaTags, tag => {
return tag.name === "citation_author";
});
expect(GSAuthorTags).to.have.lengthOf(2);
const GSFirstAuthorTag = GSAuthorTags[0];
@@ -144,74 +171,89 @@ describe('Distill V2 (transforms)', function() {
expect(GSFirstAuthorTag.content).to.equal(GSfirstAuthorName);
// Schema.org Author tags
const SOAuthorTags = Array.prototype.filter.call(metaTags, (tag) => {
return tag.getAttribute('property') === 'article:author';
const SOAuthorTags = Array.prototype.filter.call(metaTags, tag => {
return tag.getAttribute("property") === "article:author";
});
expect(SOAuthorTags).to.have.lengthOf(2);
const SOFirstAuthorTag = SOAuthorTags[0];
expect(SOFirstAuthorTag.content).to.equal(firstAuthorName);
});
it('given already correct data, it should add Google scholar references information', function() {
const dom = new JSDOM('', options);
it("given already correct data, it should add Google scholar references information", function() {
const dom = new JSDOM("", options);
const data = {
doiSuffix: 'test-doi-suffix',
citations: ['test-citation-key'],
bibliography: new Map([[
'test-citation-key', {
title: 'Why do humans reason? Arguments for an argumentative theory',
author: 'Mercier, Hugo and Sperber, Dan',
journal: 'Behavioral and brain sciences',
volume: 34,
number: 2
}
]])
doiSuffix: "test-doi-suffix",
citations: ["test-citation-key"],
bibliography: new Map([
[
"test-citation-key",
{
title:
"Why do humans reason? Arguments for an argumentative theory",
author: "Mercier, Hugo and Sperber, Dan",
journal: "Behavioral and brain sciences",
volume: 34,
number: 2
}
]
])
};
const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a('function');
const meta = distill.testing.transforms.get("Meta");
expect(meta).to.be.a("function");
meta(dom.window.document, data);
const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
const metaTags = [].slice.call(
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty;
});
it('given an arxiv article, it should add a special Google scholar arxiv citation', function() {
const dom = new JSDOM('', options);
it("given an arxiv article, it should add a special Google scholar arxiv citation", function() {
const dom = new JSDOM("", options);
const data = {
doiSuffix: 'test-doi-suffix',
citations: ['dumoulin2016guide'],
bibliography: new Map([[
'dumoulin2016guide', {
title: 'A guide to convolution arithmetic for deep learning',
author: 'Dumoulin, Vincent and Visin, Francesco',
journal: 'arXiv preprint arXiv:1603.07285',
year: '2016',
url: 'https://arxiv.org/pdf/1603.07285.pdf'
}
]])
doiSuffix: "test-doi-suffix",
citations: ["dumoulin2016guide"],
bibliography: new Map([
[
"dumoulin2016guide",
{
title: "A guide to convolution arithmetic for deep learning",
author: "Dumoulin, Vincent and Visin, Francesco",
journal: "arXiv preprint arXiv:1603.07285",
year: "2016",
url: "https://arxiv.org/pdf/1603.07285.pdf"
}
]
])
};
const meta = distill.testing.transforms.get('Meta');
expect(meta).to.be.a('function');
const meta = distill.testing.transforms.get("Meta");
expect(meta).to.be.a("function");
meta(dom.window.document, data);
const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
const metaTags = [].slice.call(
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty;
const metaTag = metaTags[0];
expect(metaTag).to.have.property('content');
expect(metaTag).to.have.property("content");
const content = metaTag.content;
expect(content).to.include('citation_title');
expect(content).to.include('citation_author');
expect(content).to.include("citation_title");
expect(content).to.include("citation_author");
expect(content.match(/citation_author=/g).length).to.equal(2);
expect(content).to.include('citation_publication_date');
expect(content).to.include('citation_arxiv_id');
expect(content).to.not.include('journal');
expect(content).to.include("citation_publication_date");
expect(content).to.include("citation_arxiv_id");
expect(content).to.not.include("journal");
});
it('given only a DOM (and publish data), it should add Google scholar references information', function() {
const dom = new JSDOM(`
it("given only a DOM (and publish data), it should add Google scholar references information", function() {
const dom = new JSDOM(
`
<d-cite key="mercier2011humans">sth</d-cite>
<d-bibliography>
<script type="text/bibtex">
@@ -228,27 +270,28 @@ describe('Distill V2 (transforms)', function() {
}
</script>
</d-bibliography>
`, options);
`,
options
);
const data = { publishedDate: new Date(), updatedDate: new Date() };
distill.render(dom.window.document, data, false);
const metaTags = [].slice.call(dom.window.document.querySelectorAll('meta[name="citation_reference"]'));
const metaTags = [].slice.call(
dom.window.document.querySelectorAll(
'meta[name="citation_reference"]'
)
);
expect(metaTags).to.not.be.empty;
});
});
}); // render
it('should export #distillify()', function() {
expect(distill.distillify).to.be.a('function');
it("should export #distillify()", function() {
expect(distill.distillify).to.be.a("function");
});
describe('#distillify()', function() {
it('should ensure existence of header');
it('should ensure existence of footer');
it('should ensure existence of distill appendix');
describe("#distillify()", function() {
it("should ensure existence of header");
it("should ensure existence of footer");
it("should ensure existence of distill appendix");
});
}); // describe 'Transform'