Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6422c27090 | |||
| adba0f6e9b | |||
| 84503f98ae | |||
| 940b70ce5b | |||
| c884d2f018 | |||
| 5ed8b40f23 | |||
| 6f4a44227f | |||
| 2c9850920b | |||
| 0abf0247e2 | |||
| 5c4b1108b6 | |||
| 11b5186394 | |||
| 04fa4ebb8c | |||
| 5292390ba8 | |||
| 0f9e12b1f1 | |||
| e606c84700 | |||
| f96ba800d8 | |||
| 84c90fbef4 | |||
| 0344bc2704 | |||
| afc798f7a0 | |||
| cecaa95989 | |||
| 87d1276564 | |||
| 397bc72df0 | |||
| b19b918466 | |||
| aef31660cc | |||
| 22b1f06a12 | |||
| 6394270d58 | |||
| 788546b8ca | |||
| b3efa2526d | |||
| c24a1d0485 | |||
| 7a5a9bbe74 | |||
| a8c29e227a | |||
| be4e9453c2 | |||
| 22fd0e2b21 | |||
| f362584a74 | |||
| a85517e61b | |||
| 1b7964f626 | |||
| befa67b4dd | |||
| f3578fbf15 | |||
| 56e8de28c4 | |||
| a770e93ec9 | |||
| dceed2ac71 | |||
| ac37a19124 | |||
| e622bd0caa | |||
| cdb4263487 | |||
| 9e14a84149 | |||
| abea1dad49 | |||
| c4c94867bf | |||
| 4bd4c4dcf9 | |||
| bf0cefac67 | |||
| f2cbc9ead4 | |||
| f6cb5bed7d | |||
| 2fd62c518d | |||
| 6c2a450662 | |||
| af02c0a845 | |||
| eb8bc670c9 | |||
| 6721d1f2db | |||
| b439644064 | |||
| 7698d45885 | |||
| b5d5e2a2f1 | |||
| 47ed46b52f |
@@ -1,15 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = spaces
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{json,yml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": ["warn", { "vars": "all", "args": "after-used" }],
|
||||
"no-console": ["off", { "allow": ["warn", "error"] } ],
|
||||
"no-empty": ["error", { "allowEmptyCatch": true }],
|
||||
"indent": [ "warn", 2 ],
|
||||
"linebreak-style": [ "error", "unix" ],
|
||||
"quotes": [ "warn", "single" ],
|
||||
"semi": [ "warn", "always" ],
|
||||
"no-extra-semi": [ "warn" ],
|
||||
"no-debugger": [ "warn" ]
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,18 @@ pids
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
@@ -17,7 +29,6 @@ build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
bower_components
|
||||
jspm_packages
|
||||
|
||||
# Optional npm cache directory
|
||||
@@ -34,11 +45,3 @@ jspm_packages
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# Copied fonts
|
||||
examples/fonts
|
||||
dist
|
||||
article-rendered.html
|
||||
|
||||
# dependency graph
|
||||
rollup-grapher.html
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
src
|
||||
build
|
||||
.editorconfig
|
||||
.eslintrc.json
|
||||
.gitignore
|
||||
.travis.yml
|
||||
rollup.config.dev.js
|
||||
rollup.config.js
|
||||
yarn-error.log
|
||||
@@ -15,4 +15,4 @@ deploy:
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
on:
|
||||
tags: true
|
||||
tags: true
|
||||
@@ -1,11 +1,11 @@
|
||||
# Distill Template [](https://travis-ci.org/distillpub/template)
|
||||
# Distill Templates
|
||||
|
||||
This is the repository for the distill web framework. If you're interesting in just using the framework to write an article for the [Distill journal](http://distill.pub), visit http://distill.pub/guide/.
|
||||
|
||||
The general process for using this framework is to hotlink the compiled code in your dev environment.
|
||||
|
||||
```html
|
||||
<script src="https://distill.pub/template.v2.js"></script>
|
||||
<script src="http://distill.pub/template.v1.js"></script>
|
||||
```
|
||||
|
||||
You can also install it as a local dependency through npm or with [yarn](https://yarnpkg.com).
|
||||
@@ -18,8 +18,8 @@ If you're interested in submitting pull requests or developing on the framework
|
||||
|
||||
## Development
|
||||
|
||||
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.
|
||||
Run `yarn start` to start a watching build rollup server. To view the sample pages in the repo, you can run `yarn serve` as a separate process which starts a static server. `yarn build` will run a one-time build.
|
||||
|
||||
## Testing
|
||||
|
||||
Run `npm test`. That's it.
|
||||
Run `yarn test`. That's it.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require("fs"),
|
||||
jsdom = require("jsdom").jsdom,
|
||||
serializeDocument = require("jsdom").serializeDocument,
|
||||
distill = require("../dist/template.js"),
|
||||
program = require('commander');
|
||||
|
||||
program
|
||||
.version('0.0.1')
|
||||
.option('-i, --input <path>', 'path to input file.')
|
||||
.parse(process.argv);
|
||||
|
||||
let htmlString = fs.readFileSync(program.input, "utf8");
|
||||
var dom = jsdom(htmlString, {features: {ProcessExternalResources: false, FetchExternalResources: false}});
|
||||
distill.render(dom, {});
|
||||
let transformedHtml = serializeDocument(dom);
|
||||
process.stdout.write(transformedHtml);
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const program = require('commander');
|
||||
const jsdom = require('jsdom');
|
||||
const { JSDOM } = jsdom;
|
||||
const transforms = require('../dist/transforms.v2.js');
|
||||
|
||||
program
|
||||
.version('1.0.0')
|
||||
.description('Pre-renders distill articles for publication.')
|
||||
.usage('-i <input_path> -o <output_path>')
|
||||
.option('-i, --input-path <path>', 'path to input HTML file.')
|
||||
.option('-o, --output-path <path>', 'path to write rendered HTML file to.')
|
||||
.parse(process.argv);
|
||||
|
||||
const virtualConsole = new jsdom.VirtualConsole();
|
||||
// omitJSDOMErrors as JSDOM routinely can't parse modern CSS
|
||||
virtualConsole.sendTo(console, { omitJSDOMErrors: true });
|
||||
|
||||
const options = { runScripts: 'outside-only', QuerySelector: true, virtualConsole: virtualConsole };
|
||||
JSDOM.fromFile(program.inputPath, options).then(dom => {
|
||||
const window = dom.window;
|
||||
const document = window.document;
|
||||
|
||||
const data = new transforms.FrontMatter;
|
||||
data.inputHTMLPath = program.inputPath; // may be needed to resolve relative links!
|
||||
data.inputDirectory = path.dirname(program.inputPath);
|
||||
transforms.render(document, data);
|
||||
transforms.distillify(document, data);
|
||||
|
||||
const transformedHtml = dom.serialize();
|
||||
fs.writeFileSync(program.outputPath, transformedHtml);
|
||||
}).catch(console.error);
|
||||
@@ -0,0 +1,28 @@
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector('dt-appendix > div');
|
||||
if (el) {
|
||||
let newHTML = "";
|
||||
|
||||
newHTML += `<h3>Updates and Corrections</h3>
|
||||
<p><a href="${data.githubCompareUpdatesUrl}">View all changes</a> to this article since it was first published. If you see a mistake or want to suggest a change, please <a class="github-issue" href="${data.githubUrl}/issues/new">create an issue on GitHub</a>.</p>`;
|
||||
|
||||
newHTML += `<h3 id="citation">Citations and Reuse</h3>
|
||||
<p>Diagrams and text are licensed under Creative Commons Attribution <a href="https://creativecommons.org/licenses/by/2.0/">CC-BY 2.0</a>, unless noted otherwise, with the <a class="github" href="${data.githubUrl}">source available on GitHub</a>. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: “Figure from …”.</p>
|
||||
|
||||
<p>For attribution in academic contexts, please cite this work as</p>
|
||||
<pre class="citation short">${data.concatenatedAuthors}, "${data.title}", ${data.journal.title}, ${data.publishedYear}. http://doi.org/${data.doi}</pre>
|
||||
|
||||
<p>BibTeX citation</p>
|
||||
<pre class="citation long">@article{${data.slug},
|
||||
author = {${data.bibtexAuthors}},
|
||||
title = {${data.title}},
|
||||
journal = {${data.journal.title}},
|
||||
year = {${data.publishedYear}},
|
||||
url = {${data.url}},
|
||||
doi = {${data.doi}}
|
||||
}</pre>`;
|
||||
|
||||
let existingHTML = el.innerHTML;
|
||||
el.innerHTML = existingHTML + newHTML;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
const templateHTML = `
|
||||
<style>
|
||||
dt-appendix {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 0;
|
||||
border-top: 1px solid rgba(0,0,0,0.1);
|
||||
color: rgba(0,0,0,0.5);
|
||||
background: rgb(250, 250, 250);
|
||||
padding-top: 36px;
|
||||
padding-bottom: 60px;
|
||||
}
|
||||
dt-appendix h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
margin-top: 18px;
|
||||
margin-bottom: 18px;
|
||||
color: rgba(0,0,0,0.65);
|
||||
}
|
||||
dt-appendix .citation {
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-left: 18px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
padding: 10px 18px;
|
||||
border-radius: 3px;
|
||||
color: rgba(150, 150, 150, 1);
|
||||
overflow: hidden;
|
||||
margin-top: -12px;
|
||||
}
|
||||
dt-appendix .references {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
}
|
||||
dt-appendix a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
dt-appendix ol,
|
||||
dt-appendix ul {
|
||||
padding-left: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="l-body">
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector('dt-appendix')
|
||||
if (el) {
|
||||
let userHTML = el.innerHTML;
|
||||
el.innerHTML = templateHTML;
|
||||
let newHTML = "";
|
||||
|
||||
// If we have some footnotes on the page, render a container for the footnote list.
|
||||
if (dom.querySelector("dt-fn")) {
|
||||
newHTML = newHTML + `<h3>Footnotes</h3><dt-fn-list></dt-fn-list>`;
|
||||
}
|
||||
|
||||
// If we have any citations on the page, render a container for the bibliography.
|
||||
if (dom.querySelector("dt-cite")) {
|
||||
newHTML = newHTML + `<h3>References</h3><dt-bibliography></dt-bibliography>`;
|
||||
}
|
||||
|
||||
let div = el.querySelector("div.l-body")
|
||||
div.innerHTML = userHTML + newHTML;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,11 +13,11 @@ const html = `
|
||||
`;
|
||||
|
||||
export default function(dom, data) {
|
||||
let banner = dom.createElement('dt-banner');
|
||||
let banner = dom.createElement("dt-banner");
|
||||
banner.innerHTML = html;
|
||||
let b = dom.querySelector('body');
|
||||
let b = dom.querySelector("body");
|
||||
b.insertBefore(banner, b.firstChild);
|
||||
banner.addEventListener('click', function() {
|
||||
banner.style.display = 'none';
|
||||
banner.addEventListener("click", function() {
|
||||
banner.style.display = "none";
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import bibtexParse from "bibtex-parse-js";
|
||||
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector('script[type="text/bibliography"]');
|
||||
let bibliography = {};
|
||||
//TODO If we don't have a local element, make a request for the document.
|
||||
if (el) {
|
||||
let rawBib = el.textContent;
|
||||
let parsed = bibtexParse.toJSON(rawBib);
|
||||
if(parsed) {
|
||||
parsed.forEach(e => {
|
||||
for (var k in e.entryTags){
|
||||
var val = e.entryTags[k];
|
||||
val = val.replace(/[\t\n ]+/g, " ");
|
||||
val = val.replace(/{\\["^`\.'acu~Hvs]( )?([a-zA-Z])}/g,
|
||||
(full, x, char) => char);
|
||||
val = val.replace(/{\\([a-zA-Z])}/g,
|
||||
(full, char) => char);
|
||||
e.entryTags[k.toLowerCase()] = val;
|
||||
}
|
||||
bibliography[e.citationKey] = e.entryTags;
|
||||
bibliography[e.citationKey].type = e.entryType;
|
||||
});
|
||||
}
|
||||
}
|
||||
data.bibliography = bibliography;
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import mustache from "mustache";
|
||||
|
||||
const html = `
|
||||
<style>
|
||||
dt-byline {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
display: block;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
dt-article.centered dt-byline {
|
||||
text-align: center;
|
||||
|
||||
}
|
||||
dt-byline a,
|
||||
dt-article dt-byline a {
|
||||
text-decoration: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
dt-article dt-byline a:hover {
|
||||
text-decoration: underline;
|
||||
border-bottom: none;
|
||||
}
|
||||
dt-byline .authors {
|
||||
text-align: left;
|
||||
}
|
||||
dt-byline .name {
|
||||
display: inline;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
dt-byline .affiliation {
|
||||
display: inline;
|
||||
}
|
||||
dt-byline .date {
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
dt-byline .year, dt-byline .month {
|
||||
display: inline;
|
||||
}
|
||||
dt-byline .citation {
|
||||
display: block;
|
||||
text-align: left;
|
||||
}
|
||||
dt-byline .citation div {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
dt-byline {
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
dt-byline {
|
||||
border-bottom: none;
|
||||
margin-bottom: 70px;
|
||||
}
|
||||
|
||||
dt-byline a:hover {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
}
|
||||
|
||||
dt-byline .authors {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
dt-byline .author {
|
||||
display: inline-block;
|
||||
margin-right: 12px;
|
||||
/*padding-left: 20px;*/
|
||||
/*border-left: 1px solid #ddd;*/
|
||||
}
|
||||
|
||||
dt-byline .affiliation {
|
||||
display: block;
|
||||
}
|
||||
|
||||
dt-byline .author:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
dt-byline .name {
|
||||
display: block;
|
||||
}
|
||||
|
||||
dt-byline .date {
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-left: 15px;
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
dt-byline .year, dt-byline .month {
|
||||
display: block;
|
||||
}
|
||||
|
||||
dt-byline .citation {
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.15);
|
||||
padding-left: 15px;
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
dt-byline .citation div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
`;
|
||||
|
||||
const template = `
|
||||
<div class="byline">
|
||||
<div class="authors">
|
||||
{{#authors}}
|
||||
<div class="author">
|
||||
{{#personalURL}}
|
||||
<a class="name" href="{{personalURL}}">{{name}}</a>
|
||||
{{/personalURL}}
|
||||
{{^personalURL}}
|
||||
<div class="name">{{name}}</div>
|
||||
{{/personalURL}}
|
||||
{{#affiliation}}
|
||||
{{#affiliationURL}}
|
||||
<a class="affiliation" href="{{affiliationURL}}">{{affiliation}}</a>
|
||||
{{/affiliationURL}}
|
||||
{{^affiliationURL}}
|
||||
<div class="affiliation">{{affiliation}}</div>
|
||||
{{/affiliationURL}}
|
||||
{{/affiliation}}
|
||||
</div>
|
||||
{{/authors}}
|
||||
</div>
|
||||
{{#publishedYear}}
|
||||
<div class="date">
|
||||
<div class="month">{{publishedMonth}}. {{publishedDay}}</div>
|
||||
<div class="year">{{publishedYear}}</div>
|
||||
</div>
|
||||
{{/publishedYear}}
|
||||
{{#publishedYear}}
|
||||
<a class="citation" href="#citation">
|
||||
<div>Citation:</div>
|
||||
<div>{{concatenatedAuthors}}, {{publishedYear}}</div>
|
||||
</a>
|
||||
{{/publishedYear}}
|
||||
</div>
|
||||
`
|
||||
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector('dt-byline');
|
||||
if (el) {
|
||||
el.innerHTML = html + mustache.render(template, data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
export default function(dom, data) {
|
||||
let css = `
|
||||
dt-cite {
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
}
|
||||
dt-cite .citation-number {
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Roboto", Helvetica, sans-serif;
|
||||
font-size: 75%;
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
display: inline-block;
|
||||
line-height: 1.1em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
figcaption dt-cite .citation-number {
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
top: -2px;
|
||||
line-height: 1em;
|
||||
}
|
||||
`;
|
||||
|
||||
let style = dom.createElement("style");
|
||||
style.textContent = css;
|
||||
dom.querySelector("body").appendChild(style);
|
||||
|
||||
let citations = data.citations;
|
||||
/*if (data.citations) {
|
||||
citations = Object.keys(data.citations).map(c => data.citations[c]);
|
||||
citations.sort((a, b) => {
|
||||
return a.author.localeCompare(b.author);
|
||||
});
|
||||
}*/
|
||||
|
||||
var appendCiteHoverDiv = (function() {
|
||||
function nodeFromString(str) {
|
||||
var div = dom.createElement("div");
|
||||
div.innerHTML = str;
|
||||
return div.firstChild;
|
||||
}
|
||||
var hover_boxes_container = nodeFromString(`<div id="cite-hover-boxes-container"></div>`)
|
||||
dom.querySelector("body").appendChild(hover_boxes_container);
|
||||
var hover_n = 0;
|
||||
return function appendHoverDiv(content) {
|
||||
var id = `dt-cite-hover-box-${hover_n}`;
|
||||
hover_n += 1;
|
||||
var str = `<div style="display:none;" class="dt-hover-box" id="${id}" >${content}</div>`;
|
||||
var div = nodeFromString(str);
|
||||
hover_boxes_container.appendChild(div);
|
||||
return id;
|
||||
}
|
||||
})();
|
||||
|
||||
var citeTags = [].slice.apply(dom.querySelectorAll("dt-cite"));
|
||||
citeTags.forEach((el,n) => {
|
||||
var key = el.getAttribute("key");
|
||||
if (key) {
|
||||
var keys = key.split(",");
|
||||
var cite_string = inline_cite_short(keys);
|
||||
var cite_hover_str = "";
|
||||
keys.map((key,n) => {
|
||||
if (n>0) cite_hover_str += "<br><br>";
|
||||
cite_hover_str += hover_cite(data.bibliography[key]);
|
||||
});
|
||||
var ref_id = appendCiteHoverDiv(cite_hover_str);
|
||||
//cite_hover_str = cite_hover_str.replace(/"/g, "'")
|
||||
var orig_string = el.innerHTML;
|
||||
if (orig_string != "") orig_string += " ";
|
||||
el.innerHTML = `<span id="citation-${n}" data-hover-ref="${ref_id}">${orig_string}<span class="citation-number">${cite_string}</span></span>`;
|
||||
}
|
||||
});
|
||||
|
||||
let bibEl = dom.querySelector("dt-bibliography");
|
||||
if (bibEl) {
|
||||
let ol = dom.createElement("ol");
|
||||
citations.forEach(key => {
|
||||
let el = dom.createElement("li");
|
||||
el.innerHTML = bibliography_cite(data.bibliography[key]);
|
||||
ol.appendChild(el);
|
||||
})
|
||||
bibEl.appendChild(ol);
|
||||
}
|
||||
|
||||
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 "["+keys.map(cite_string).join(", ")+"]";
|
||||
}
|
||||
|
||||
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 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;
|
||||
} else {
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
return keys.map(cite_string).join(", ");
|
||||
}
|
||||
|
||||
function author_string(ent, template, sep, finalSep){
|
||||
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 {
|
||||
var last = name.split(" ").slice(-1)[0].trim();
|
||||
var firsts = name.split(" ").slice(0,-1).join(" ");
|
||||
}
|
||||
var initials = "";
|
||||
if (firsts != undefined) {
|
||||
initials = firsts.trim().split(" ").map(s => s.trim()[0]);
|
||||
initials = initials.join(".")+".";
|
||||
}
|
||||
return template.replace("${F}", firsts)
|
||||
.replace("${L}", last)
|
||||
.replace("${I}", initials);
|
||||
});
|
||||
if (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];
|
||||
}
|
||||
}
|
||||
|
||||
function venue_string(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;
|
||||
}
|
||||
if ("pages" in ent){
|
||||
cite += ", pp. " + ent.pages
|
||||
}
|
||||
if (cite != "") cite += ". "
|
||||
if ("publisher" in ent){
|
||||
cite += ent.publisher;
|
||||
if (cite[cite.length-1] != ".") cite += ".";
|
||||
}
|
||||
return cite;
|
||||
}
|
||||
|
||||
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){
|
||||
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";
|
||||
}
|
||||
return `  <a href="${url}">[${label||"link"}]</a>`;
|
||||
}/* else if ("doi" in ent){
|
||||
return `  <a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
|
||||
}*/ else {
|
||||
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>`;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function bibliography_cite(ent, fancy){
|
||||
if (ent){
|
||||
var cite = "<b>" + ent.title + "</b> "
|
||||
cite += link_string(ent) + "<br>";
|
||||
cite += author_string(ent, "${L}, ${I}", ", ", " and ");
|
||||
if (ent.year || ent.date){
|
||||
cite += ", " + (ent.year || ent.date) + ". "
|
||||
} else {
|
||||
cite += ". "
|
||||
}
|
||||
cite += venue_string(ent);
|
||||
cite += doi_string(ent);
|
||||
return cite
|
||||
/*var cite = author_string(ent, "${L}, ${I}", ", ", " and ");
|
||||
if (ent.year || ent.date){
|
||||
cite += ", " + (ent.year || ent.date) + ". "
|
||||
} else {
|
||||
cite += ". "
|
||||
}
|
||||
cite += "<b>" + ent.title + "</b>. ";
|
||||
cite += venue_string(ent);
|
||||
cite += doi_string(ent);
|
||||
cite += link_string(ent);
|
||||
return cite*/
|
||||
} else {
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
function hover_cite(ent){
|
||||
if (ent){
|
||||
var cite = "";
|
||||
cite += "<b>" + ent.title + "</b>";
|
||||
cite += link_string(ent);
|
||||
cite += "<br>"
|
||||
|
||||
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;
|
||||
} else {
|
||||
cite += a_str + "<br>" + v_str;
|
||||
}
|
||||
return cite;
|
||||
} else {
|
||||
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(" ")})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import Prism from "prismjs";
|
||||
import "prismjs/components/prism-python";
|
||||
import "prismjs/components/prism-clike";
|
||||
import "prismjs/components/prism-lua";
|
||||
import "prismjs/components/prism-bash";
|
||||
import "prismjs/components/prism-go";
|
||||
import "prismjs/components/prism-markdown";
|
||||
import "prismjs/components/prism-julia";
|
||||
|
||||
|
||||
export default function(dom, data) {
|
||||
let codeElements = [].slice.call(dom.querySelectorAll("dt-code"));
|
||||
codeElements.forEach(el => {
|
||||
let content = el.textContent;
|
||||
el.innerHTML = "";
|
||||
let language = el.getAttribute("language");
|
||||
let c = dom.createElement("code");
|
||||
if (el.getAttribute("block") === "") {
|
||||
// Let's normalize the tab indents
|
||||
content = content.replace(/\n/, "");
|
||||
let tabs = content.match(/\s*/);
|
||||
content = content.replace(new RegExp("\n" + tabs, "g"), "\n");
|
||||
content = content.trim();
|
||||
let p = dom.createElement("pre");
|
||||
p.appendChild(c);
|
||||
el.appendChild(p);
|
||||
} else {
|
||||
el.appendChild(c);
|
||||
}
|
||||
let highlighted = content;
|
||||
if (Prism.languages[language]) {
|
||||
c.setAttribute("class", "language-" + language);
|
||||
highlighted = Prism.highlight(content, Prism.languages[language]);
|
||||
}
|
||||
c.innerHTML = highlighted;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import {timeFormat} from "d3-time-format";
|
||||
|
||||
export default function(dom, data) {
|
||||
|
||||
//
|
||||
// Properties from source
|
||||
//
|
||||
|
||||
// title: 'Attention and Augmented Recurrent Neural Networks',
|
||||
// description: 'A visual overview of neural attention, and the powerful extensions of neural networks being built on top of it.',
|
||||
// url: 'http://distill.pub/2016/augmented-rnns',
|
||||
// tags: [ 'rnn' ],
|
||||
// doiSuffix: 1,
|
||||
// doi: '10.23915/distill.00001',
|
||||
// volume: 1,
|
||||
// issue: 9,
|
||||
// distillPath: '2016/augmented-rnns',
|
||||
// githubPath: 'distillpub/post--augmented-rnns',
|
||||
// githubCompareUpdatesUrl: 'https://github.com/distillpub/post--augmented-rnns/compare/1596e094d8943d2dc0ea445d92071129c6419c59...3bd9209e0c24d020f87cf6152dcecc6017cbc193',
|
||||
// updatedDate: 2017-03-21T07:13:16.000Z,
|
||||
// publishedDate: 2016-09-08T07:00:00.000Z,
|
||||
// journal: {
|
||||
// "title": "Distill",
|
||||
// "full_title": "Distill",
|
||||
// "abbrev_title": "Distill",
|
||||
// "url": "http://distill.pub",
|
||||
// "doi": "10.23915/distill",
|
||||
// "publisherName": "Distill Working Group",
|
||||
// "publisherEmail": "admin@distill.pub",
|
||||
// "issn": "2476-0757",
|
||||
// "editors": [...],
|
||||
// "committee": [...]
|
||||
// }
|
||||
|
||||
//
|
||||
// Computed Properties
|
||||
//
|
||||
|
||||
// githubUrl: 'https://github.com/distillpub/post--augmented-rnns',
|
||||
// previewURL: 'http://distill.pub/2016/augmented-rnns/thumbnail.jpg',
|
||||
// publishedDateRFC: 'Thu, 08 Sep 2016 00:00:00 -0700',
|
||||
// publishedYear: 2016,
|
||||
// publishedMonth: 'Sept',
|
||||
// publishedDay: 8,
|
||||
// publishedMonthPadded: '09',
|
||||
// publishedDayPadded: '08',
|
||||
// updatedDateRFC: 'Tue, 21 Mar 2017 00:13:16 -0700',
|
||||
// concatenatedAuthors: 'Olah & Carter',
|
||||
// bibtexAuthors: 'Olah, Chris and Carter, Shan',
|
||||
// slug: 'olah2016attention'
|
||||
// authors: [
|
||||
// {
|
||||
// "personalURL": null,
|
||||
// "name": "Chris Olah",
|
||||
// "firstName": "Chris",
|
||||
// "lastName": "Olah",
|
||||
// "affiliationURL": null,
|
||||
// "affiliation": "Google Brain"
|
||||
// }
|
||||
// ],
|
||||
// bibliography: {
|
||||
// "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": "arXiv preprint arXiv:1502.04623",
|
||||
// "year": "2015",
|
||||
// "url": "https://arxiv.org/pdf/1502.04623.pdf",
|
||||
// "type": "article"
|
||||
// },
|
||||
// ...
|
||||
// },
|
||||
// citations: [
|
||||
// "gregor2015draw",
|
||||
// "mercier2011humans",
|
||||
// "dong2014image",
|
||||
// "dumoulin2016guide",
|
||||
// "mordvintsev2015inceptionism"
|
||||
// ],
|
||||
|
||||
|
||||
// citations:
|
||||
let citations = [];
|
||||
var citeTags = [].slice.apply(dom.querySelectorAll("dt-cite"));
|
||||
citeTags.forEach(el => {
|
||||
let key = el.getAttribute("key");
|
||||
if (key) {
|
||||
let citationKeys = key.split(",");
|
||||
citationKeys.forEach(key => {
|
||||
if (citations.indexOf(key) == -1){
|
||||
citations.push(key);
|
||||
if (!(key in data.bibliography)){
|
||||
console.warn("No bibliography entry found for: " + key);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
data.citations = citations;
|
||||
|
||||
|
||||
data.authors = data.authors || [];
|
||||
|
||||
// paths
|
||||
if (!data.distillPath && !data.url) {
|
||||
data.url = "http://distill.pub/";
|
||||
} else if (!data.url) {
|
||||
data.url = "http://distill.pub/" + data.distillPath;
|
||||
}
|
||||
data.githubUrl = "https://github.com/" + data.githubPath;
|
||||
|
||||
data.previewURL = data.previewURL ? data.previewURL : data.url + "/thumbnail.jpg"
|
||||
|
||||
// Homepage
|
||||
//data.homepage = !post.noHomepage;
|
||||
data.journal = data.journal || {};
|
||||
|
||||
// Dates
|
||||
if (data.publishedDate){//} && data.journal) {
|
||||
data.volume = data.publishedDate.getFullYear() - 2015;
|
||||
data.issue = data.publishedDate.getMonth() + 1;
|
||||
}
|
||||
|
||||
data.publishedDate = data.publishedDate ? data.publishedDate : new Date("Invalid");
|
||||
data.updatedDate = data.updatedDate ? data.updatedDate : new Date("Invalid");
|
||||
|
||||
data.publishedDateRFC
|
||||
let RFC = timeFormat("%a, %d %b %Y %H:%M:%S %Z");
|
||||
let months = ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"];
|
||||
let zeroPad = (n) => { return n < 10 ? "0" + n : n; };
|
||||
data.publishedDateRFC = RFC(data.publishedDate);
|
||||
data.publishedYear = data.publishedDate.getFullYear();
|
||||
data.publishedMonth = months[data.publishedDate.getMonth()];
|
||||
data.publishedDay = data.publishedDate.getDate();
|
||||
data.publishedMonthPadded = zeroPad(data.publishedDate.getMonth() + 1);
|
||||
data.publishedDayPadded = zeroPad(data.publishedDate.getDate());
|
||||
data.updatedDateRFC = RFC(data.updatedDate);
|
||||
|
||||
if (data.authors.length > 2) {
|
||||
data.concatenatedAuthors = data.authors[0].lastName + ", et al.";
|
||||
} else if (data.authors.length === 2) {
|
||||
data.concatenatedAuthors = data.authors[0].lastName + " & " + data.authors[1].lastName;
|
||||
} else if (data.authors.length === 1) {
|
||||
data.concatenatedAuthors = data.authors[0].lastName
|
||||
}
|
||||
|
||||
data.bibtexAuthors = data.authors.map(function(author){
|
||||
return author.lastName + ", " + author.firstName;
|
||||
}).join(" and ");
|
||||
|
||||
data.slug = data.authors.length ? data.authors[0].lastName.toLowerCase() + data.publishedYear + data.title.split(" ")[0].toLowerCase() : "Untitled";
|
||||
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 740 B After Width: | Height: | Size: 740 B |
|
Before Width: | Height: | Size: 163 B After Width: | Height: | Size: 163 B |
@@ -0,0 +1,18 @@
|
||||
import katex from "katex";
|
||||
|
||||
const html = `
|
||||
<style>
|
||||
dt-math[block] {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
export default function(dom, data) {
|
||||
let equationElements = [].slice.call(dom.querySelectorAll("dt-math"));
|
||||
equationElements.forEach(el => {
|
||||
let content = el.textContent;
|
||||
let displayMode = el.hasAttribute("block") ? true : false;
|
||||
el.innerHTML = html + katex.renderToString(content, {displayMode: displayMode});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import logo from "./distill-logo.svg";
|
||||
|
||||
let html = `
|
||||
<style>
|
||||
dt-footer {
|
||||
display: block;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-weight: 300;
|
||||
padding: 40px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background-color: hsl(200, 60%, 15%);
|
||||
text-align: center;
|
||||
}
|
||||
dt-footer .logo svg {
|
||||
width: 24px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
dt-footer .logo svg path {
|
||||
fill: none;
|
||||
stroke: rgba(255, 255, 255, 0.8);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
dt-footer .logo {
|
||||
font-size: 17px;
|
||||
font-weight: 200;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-decoration: none;
|
||||
margin-right: 6px;
|
||||
}
|
||||
dt-footer .nav {
|
||||
margin-top: 12px;
|
||||
}
|
||||
dt-footer .nav a {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
margin-right: 6px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="l-page">
|
||||
<div class="description">
|
||||
<a href="/" class="logo">
|
||||
${logo}
|
||||
Distill
|
||||
</a>
|
||||
is dedicated to clear explanations of machine learning
|
||||
</div>
|
||||
<div class="nav">
|
||||
<a href="http://distill.pub/about/">About</a>
|
||||
<a href="http://distill.pub/journal/">Submit</a>
|
||||
<a href="http://distill.pub/prize/">Prize</a>
|
||||
<a href="http://distill.pub/archive/">Archive</a>
|
||||
<a href="http://distill.pub/rss.xml">RSS</a>
|
||||
<a href="https://github.com/distillpub">GitHub</a>
|
||||
<a href="https://twitter.com/distillpub">Twitter</a>
|
||||
ISSN 2476-0757
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector("dt-footer");
|
||||
if(el) {
|
||||
el.innerHTML = html;
|
||||
} else {
|
||||
let footer = dom.createElement("dt-footer");
|
||||
footer.innerHTML = html;
|
||||
let b = dom.querySelector("body");
|
||||
b.appendChild(footer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
export default function(dom, data) {
|
||||
|
||||
var appendFootnoteHoverDiv = (function() {
|
||||
function nodeFromString(str) {
|
||||
var div = dom.createElement("div");
|
||||
div.innerHTML = str;
|
||||
return div.firstChild;
|
||||
}
|
||||
var hover_boxes_container = nodeFromString(`<div id="footnote-hover-boxes-container"></div>`)
|
||||
dom.querySelector("body").appendChild(hover_boxes_container);
|
||||
var hover_n = 0;
|
||||
return function appendHoverDiv(content) {
|
||||
var id = `dt-fn-hover-box-${hover_n}`;
|
||||
hover_n += 1;
|
||||
var str = `<div style="display:none;" class="dt-hover-box" id="${id}" >${content}</div>`;
|
||||
var div = nodeFromString(str);
|
||||
hover_boxes_container.appendChild(div);
|
||||
return id;
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
var fnTags = [].slice.apply(dom.querySelectorAll("dt-fn"));
|
||||
var fnContent = [];
|
||||
fnTags.forEach((el,n) => {
|
||||
var content = el.innerHTML;
|
||||
var ref_id = appendFootnoteHoverDiv(content)
|
||||
fnContent.push(content);
|
||||
n = (n+1)+"";
|
||||
var key = "fn-"+n;
|
||||
var escaped_content = content.replace(/"/g, "'");
|
||||
el.innerHTML = `<sup><span id="${key}" data-hover-ref="${ref_id}" style="cursor:pointer">${n}</span></sup>`;
|
||||
});
|
||||
|
||||
let fnList = dom.querySelector("dt-fn-list");
|
||||
if (fnList) {
|
||||
let ol = dom.createElement("ol");
|
||||
fnContent.forEach(content => {
|
||||
let el = dom.createElement("li");
|
||||
el.innerHTML = content;
|
||||
ol.appendChild(el);
|
||||
})
|
||||
fnList.appendChild(ol);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import ymlParse from 'js-yaml';
|
||||
import ymlParse from "js-yaml";
|
||||
|
||||
export default function(dom, data) {
|
||||
let localData = {};
|
||||
@@ -8,27 +8,27 @@ export default function(dom, data) {
|
||||
localData = ymlParse.safeLoad(text);
|
||||
}
|
||||
|
||||
data.title = localData.title ? localData.title : 'Untitled';
|
||||
data.description = localData.description ? localData.description : 'No description.';
|
||||
data.title = localData.title ? localData.title : "Untitled";
|
||||
data.description = localData.description ? localData.description : "No description.";
|
||||
|
||||
data.authors = localData.authors ? localData.authors : [];
|
||||
|
||||
data.authors = data.authors.map((author, i) =>{
|
||||
let a = {};
|
||||
let name = Object.keys(author)[0];
|
||||
if ((typeof author) === 'string') {
|
||||
if ((typeof author) === "string") {
|
||||
name = author;
|
||||
} else {
|
||||
a.personalURL = author[name];
|
||||
}
|
||||
let names = name.split(' ');
|
||||
let names = name.split(" ");
|
||||
a.name = name;
|
||||
a.firstName = names.slice(0, names.length - 1).join(' ');
|
||||
a.firstName = names.slice(0, names.length - 1).join(" ");
|
||||
a.lastName = names[names.length -1];
|
||||
if(localData.affiliations[i]) {
|
||||
let affiliation = Object.keys(localData.affiliations[i])[0];
|
||||
if ((typeof localData.affiliations[i]) === 'string') {
|
||||
affiliation = localData.affiliations[i];
|
||||
if ((typeof localData.affiliations[i]) === "string") {
|
||||
affiliation = localData.affiliations[i]
|
||||
} else {
|
||||
a.affiliationURL = localData.affiliations[i][affiliation];
|
||||
}
|
||||
@@ -6,18 +6,18 @@ export default function(data) {
|
||||
var date = data.publishedDate;
|
||||
|
||||
var batch_timestamp = Math.floor(Date.now() / 1000);
|
||||
var batch_id = data.authors.length ? data.authors[0].lastName.toLowerCase().slice(0,20) : 'Anonymous';
|
||||
batch_id += '_' + date.getFullYear();
|
||||
batch_id += '_' + data.title.split(' ')[0].toLowerCase().slice(0,20) + '_' + batch_timestamp;
|
||||
var batch_id = data.authors.length ? data.authors[0].lastName.toLowerCase().slice(0,20) : "Anonymous";
|
||||
batch_id += "_" + date.getFullYear();
|
||||
batch_id += "_" + data.title.split(" ")[0].toLowerCase().slice(0,20) + "_" + batch_timestamp;
|
||||
// generate XML
|
||||
var crf_data =
|
||||
{doi_batch : [
|
||||
|
||||
{ _attr: {
|
||||
version: '4.3.7',
|
||||
xmlns: 'http://www.crossref.org/schema/4.3.7',
|
||||
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation': 'http://www.crossref.org/schema/4.3.7 http://www.crossref.org/schemas/crossref4.3.7.xsd',
|
||||
version: "4.3.7",
|
||||
xmlns: "http://www.crossref.org/schema/4.3.7",
|
||||
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
||||
"xsi:schemaLocation": "http://www.crossref.org/schema/4.3.7 http://www.crossref.org/schemas/crossref4.3.7.xsd",
|
||||
}},
|
||||
|
||||
{ head: [
|
||||
@@ -62,8 +62,8 @@ export default function(data) {
|
||||
data.authors.map((author, ind) => (
|
||||
{person_name: [
|
||||
{ _attr: {
|
||||
contributor_role: 'author',
|
||||
sequence: (ind == 0)? 'first' : 'additional'
|
||||
contributor_role: "author",
|
||||
sequence: (ind == 0)? "first" : "additional"
|
||||
}},
|
||||
{given_name: author.firstName},
|
||||
{surname: author.lastName},
|
||||
@@ -73,9 +73,9 @@ export default function(data) {
|
||||
))
|
||||
},
|
||||
{publication_date: [
|
||||
{month: date.getMonth()+1},
|
||||
{day: date.getDate()},
|
||||
{year: date.getFullYear()}
|
||||
{month: date.getMonth()+1},
|
||||
{day: date.getDate()},
|
||||
{year: date.getFullYear()}
|
||||
]},
|
||||
{ publisher_item: [
|
||||
{item_number: data.doi}
|
||||
@@ -87,7 +87,7 @@ export default function(data) {
|
||||
]},
|
||||
{citation_list:
|
||||
data.citations.map(key =>
|
||||
citation_xml(key, data.bibliography[key]))
|
||||
citation_xml(key, data.bibliography[key]))
|
||||
}
|
||||
|
||||
]},
|
||||
@@ -103,29 +103,29 @@ function citation_xml(key, ent){
|
||||
if (ent == undefined) return {};
|
||||
var info = [];
|
||||
info.push({_attr: {key: key}});
|
||||
if ('title' in ent)
|
||||
if ("title" in ent)
|
||||
info.push({article_title: ent.title});
|
||||
if ('author' in ent)
|
||||
info.push({author: ent.author.split(' and ')[0].split(',')[0].trim()});
|
||||
if ('journal' in ent)
|
||||
if ("author" in ent)
|
||||
info.push({author: ent.author.split(" and ")[0].split(",")[0].trim()});
|
||||
if ("journal" in ent)
|
||||
info.push({journal_title: ent.journal});
|
||||
if ('booktitle' in ent)
|
||||
if ("booktitle" in ent)
|
||||
info.push({volume_title: ent.booktitle});
|
||||
if ('volume' in ent)
|
||||
if ("volume" in ent)
|
||||
info.push({volume: ent.volume});
|
||||
if ('issue' in ent)
|
||||
if ("issue" in ent)
|
||||
info.push({issue: ent.issue});
|
||||
if ('doi' in ent)
|
||||
if ("doi" in ent)
|
||||
info.push({doi: ent.doi});
|
||||
return {citation: info};
|
||||
return {citation: info}
|
||||
}
|
||||
|
||||
function xml(obj) {
|
||||
//console.log(typeof(obj), obj)
|
||||
if (typeof obj === 'string') return obj;
|
||||
if (typeof obj === 'number') return ''+obj;
|
||||
if (typeof obj === 'number') return ""+obj;
|
||||
let keys = Object.keys(obj);
|
||||
if (keys.length != 1) console.error('can\'t interpret ', obj, 'as xml');
|
||||
if (keys.length != 1) console.error("can't interpret ", obj, "as xml");
|
||||
let name = keys[0];
|
||||
var full_content = obj[name];
|
||||
var attr = {};
|
||||
@@ -134,8 +134,8 @@ function xml(obj) {
|
||||
for (var i in full_content) {
|
||||
var obj = full_content[i];
|
||||
var obj_name = Object.keys(obj)[0];
|
||||
if ('_attr' == obj_name) {
|
||||
attr = obj['_attr'];
|
||||
if ("_attr" == obj_name) {
|
||||
attr = obj["_attr"];
|
||||
} else {
|
||||
//console.log(Object.keys(obj)[0])
|
||||
content.push(obj);
|
||||
@@ -145,19 +145,19 @@ function xml(obj) {
|
||||
content = full_content;
|
||||
}
|
||||
if (content == undefined){
|
||||
content = 'undefined';
|
||||
content = "undefined"
|
||||
}
|
||||
|
||||
let attr_string = '';
|
||||
let attr_string = "";
|
||||
for (var k in attr) {
|
||||
attr_string += ` ${k}=\"${attr[k]}\"`;
|
||||
attr_string += ` ${k}=\"${attr[k]}\"`
|
||||
}
|
||||
|
||||
//console.log(typeof content, Array.isArray(content), content instanceof String, content)
|
||||
if (Array.isArray(content)){
|
||||
content = content.map(xml);
|
||||
content = content.join('\n').split('\n');
|
||||
content = content.map(s => ' ' + s).join('\n');
|
||||
content = content.join("\n").split("\n");
|
||||
content = content.map(s => " " + s).join("\n")
|
||||
var result = `<${name}${attr_string}>\n${content}\n</${name}>`;
|
||||
} else {
|
||||
content = xml(content);
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import logo from "./distill-logo.svg";
|
||||
|
||||
import logo from '../assets/distill-logo.svg';
|
||||
|
||||
const T = Template('distill-header', `
|
||||
const html = `
|
||||
<style>
|
||||
distill-header {
|
||||
dt-header {
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 60px;
|
||||
background-color: hsl(200, 60%, 15%);
|
||||
@@ -15,11 +14,10 @@ distill-header {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
distill-header .content {
|
||||
dt-header .content {
|
||||
height: 70px;
|
||||
grid-column: page;
|
||||
}
|
||||
distill-header a {
|
||||
dt-header a {
|
||||
font-size: 16px;
|
||||
height: 60px;
|
||||
line-height: 60px;
|
||||
@@ -27,47 +25,48 @@ distill-header a {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
padding: 22px 0;
|
||||
}
|
||||
distill-header a:hover {
|
||||
dt-header a:hover {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
distill-header svg {
|
||||
dt-header svg {
|
||||
width: 24px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
@media(min-width: 1080px) {
|
||||
distill-header {
|
||||
dt-header {
|
||||
height: 70px;
|
||||
}
|
||||
distill-header a {
|
||||
dt-header a {
|
||||
height: 70px;
|
||||
line-height: 70px;
|
||||
padding: 28px 0;
|
||||
}
|
||||
distill-header .logo {
|
||||
dt-header .logo {
|
||||
}
|
||||
}
|
||||
distill-header svg path {
|
||||
dt-header svg path {
|
||||
fill: none;
|
||||
stroke: rgba(255, 255, 255, 0.8);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
distill-header .logo {
|
||||
dt-header .logo {
|
||||
font-size: 17px;
|
||||
font-weight: 200;
|
||||
}
|
||||
distill-header .nav {
|
||||
dt-header .nav {
|
||||
float: right;
|
||||
font-weight: 300;
|
||||
}
|
||||
distill-header .nav a {
|
||||
dt-header .nav a {
|
||||
font-size: 12px;
|
||||
margin-left: 24px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
<div class="content">
|
||||
|
||||
<div class="content l-page">
|
||||
<a href="/" class="logo">
|
||||
${logo}
|
||||
Distill
|
||||
@@ -78,13 +77,16 @@ distill-header .nav a {
|
||||
<a href="/journal/">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
`, false);
|
||||
|
||||
// <div class="nav">
|
||||
// <a href="https://github.com/distillpub">GitHub</a>
|
||||
// <!-- https://twitter.com/distillpub -->
|
||||
// </div>
|
||||
|
||||
export class DistillHeader extends T(HTMLElement) {
|
||||
`
|
||||
|
||||
export default function(dom, data) {
|
||||
let el = dom.querySelector("dt-header");
|
||||
if(el) {
|
||||
el.innerHTML = html;
|
||||
} else {
|
||||
let header = dom.createElement("dt-header");
|
||||
header.innerHTML = html;
|
||||
let b = dom.querySelector("body");
|
||||
b.insertBefore(header, b.firstChild);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import code from './hover-box.txt';
|
||||
|
||||
export default function(dom) {
|
||||
let s = dom.createElement('script');
|
||||
let s = dom.createElement("script");
|
||||
s.textContent = code;
|
||||
dom.querySelector('body').appendChild(s);
|
||||
dom.querySelector("body").appendChild(s);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
|
||||
|
||||
function nodeFromString(str) {
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = str;
|
||||
return div.firstChild;
|
||||
}
|
||||
|
||||
function make_hover_css(pos) {
|
||||
var pretty = window.innerWidth > 600;
|
||||
var padding = pretty? 18 : 12;
|
||||
var outer_padding = pretty ? 18 : 0;
|
||||
var bbox = document.querySelector("body").getBoundingClientRect();
|
||||
var left = pos[0] - bbox.left, top = pos[1] - bbox.top;
|
||||
var width = Math.min(window.innerWidth-2*outer_padding, 648);
|
||||
left = Math.min(left, window.innerWidth-width-outer_padding);
|
||||
width = width - 2*padding;
|
||||
return (`position: absolute;
|
||||
background-color: #FFF;
|
||||
opacity: 0.95;
|
||||
max-width: ${width}px;
|
||||
top: ${top}px;
|
||||
left: ${left}px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
padding: ${padding}px;
|
||||
border-radius: ${pretty? 3 : 0}px;
|
||||
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
|
||||
z-index: ${1e6};`);
|
||||
}
|
||||
|
||||
|
||||
function DtHoverBox(div_id) {
|
||||
this.div = document.querySelector("#"+div_id);
|
||||
this.visible = false;
|
||||
this.bindDivEvents();
|
||||
DtHoverBox.box_map[div_id] = this;
|
||||
}
|
||||
|
||||
DtHoverBox.box_map = {};
|
||||
|
||||
DtHoverBox.get_box = function get_box(div_id) {
|
||||
if (div_id in DtHoverBox.box_map) {
|
||||
return DtHoverBox.box_map[div_id];
|
||||
} else {
|
||||
return new DtHoverBox(div_id);
|
||||
}
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.show = function show(pos){
|
||||
this.visible = true;
|
||||
this.div.setAttribute("style", make_hover_css(pos) );
|
||||
for (var box_id in DtHoverBox.box_map) {
|
||||
var box = DtHoverBox.box_map[box_id];
|
||||
if (box != this) box.hide();
|
||||
}
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.showAtNode = function showAtNode(node){
|
||||
var bbox = node.getBoundingClientRect();
|
||||
this.show([bbox.right, bbox.bottom]);
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.hide = function hide(){
|
||||
this.visible = false;
|
||||
if (this.div) this.div.setAttribute("style", "display:none");
|
||||
if (this.timeout) clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.stopTimeout = function stopTimeout() {
|
||||
if (this.timeout) clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.extendTimeout = function extendTimeout(T) {
|
||||
//console.log("extend", T)
|
||||
var this_ = this;
|
||||
this.stopTimeout();
|
||||
this.timeout = setTimeout(function(){this_.hide();}.bind(this), T);
|
||||
}
|
||||
|
||||
// Bind events to a link to open this box
|
||||
DtHoverBox.prototype.bind = function bind(node) {
|
||||
if (typeof node == "string"){
|
||||
node = document.querySelector(node);
|
||||
}
|
||||
|
||||
node.addEventListener("mouseover", function(){
|
||||
if (!this.visible) this.showAtNode(node);
|
||||
this.stopTimeout();
|
||||
}.bind(this));
|
||||
|
||||
node.addEventListener("mouseout", function(){this.extendTimeout(250);}.bind(this));
|
||||
|
||||
node.addEventListener("touchstart", function(e) {
|
||||
if (this.visible) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.showAtNode(node);
|
||||
}
|
||||
// Don't trigger body touchstart event when touching link
|
||||
e.stopPropagation();
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
DtHoverBox.prototype.bindDivEvents = function bindDivEvents(){
|
||||
// For mice, same behavior as hovering on links
|
||||
this.div.addEventListener("mouseover", function(){
|
||||
if (!this.visible) this.showAtNode(node);
|
||||
this.stopTimeout();
|
||||
}.bind(this));
|
||||
this.div.addEventListener("mouseout", function(){this.extendTimeout(250);}.bind(this));
|
||||
|
||||
// Don't trigger body touchstart event when touching within box
|
||||
this.div.addEventListener("touchstart", function(e){e.stopPropagation();});
|
||||
// Close box when touching outside box
|
||||
document.body.addEventListener("touchstart", function(){this.hide();}.bind(this));
|
||||
}
|
||||
|
||||
var hover_es = document.querySelectorAll("span[data-hover-ref]");
|
||||
hover_es = [].slice.apply(hover_es);
|
||||
hover_es.forEach(function(e,n){
|
||||
var ref_id = e.getAttribute("data-hover-ref");
|
||||
DtHoverBox.get_box(ref_id).bind(e);
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
export default function(dom) {
|
||||
if (!dom.querySelector("html").getAttribute("lang")) {
|
||||
dom.querySelector("html").setAttribute("lang", "en")
|
||||
}
|
||||
|
||||
let head = dom.querySelector("head");
|
||||
|
||||
if (!dom.querySelector("meta[charset]")) {
|
||||
let meta = dom.createElement("meta");
|
||||
meta.setAttribute("charset", "utf-8");
|
||||
head.appendChild(meta);
|
||||
}
|
||||
if (!dom.querySelector("meta[name=viewport]")) {
|
||||
let meta = dom.createElement("meta");
|
||||
meta.setAttribute("name", "viewport");
|
||||
meta.setAttribute("content", "width=device-width, initial-scale=1");
|
||||
head.appendChild(meta);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
import fetch from 'fetch';
|
||||
let fetchUrl = fetch.fetchUrl;
|
||||
import fetch from "fetch";
|
||||
let fetchUrl = fetch.fetchUrl
|
||||
|
||||
export default function(dom, data) {
|
||||
|
||||
var includeTags = [].slice.apply(dom.querySelectorAll('dt-include'));
|
||||
var includeTags = [].slice.apply(dom.querySelectorAll("dt-include"));
|
||||
|
||||
includeTags.forEach(el => {
|
||||
let src = el.getAttribute('src');
|
||||
let src = el.getAttribute("src");
|
||||
fetchUrl(src, (err, meta, body) => {
|
||||
console.log(err, meta, body);
|
||||
el.innerHTML = body.toString();
|
||||
});
|
||||
})
|
||||
});
|
||||
data.bibliography = bibliography;
|
||||
data.citations = citations;
|
||||
@@ -10,9 +10,9 @@ export default function(dom, data) {
|
||||
markdownElements.forEach(el => {
|
||||
let content = el.innerHTML;
|
||||
// Set default indents
|
||||
content = content.replace(/\n/, '');
|
||||
content = content.replace(/\n/, "");
|
||||
let tabs = content.match(/\s*/);
|
||||
content = content.replace(new RegExp('\n' + tabs, 'g'), '\n');
|
||||
content = content.replace(new RegExp("\n" + tabs, "g"), "\n");
|
||||
content = content.trim();
|
||||
|
||||
el.innerHTML = marked(content);
|
||||
@@ -0,0 +1,141 @@
|
||||
import favicon from './distill-favicon.base64';
|
||||
import escape from 'escape-html';
|
||||
|
||||
export default function(dom, data) {
|
||||
let head = dom.querySelector("head");
|
||||
let appendHead = html => appendHtml(head, html);
|
||||
|
||||
function meta(name, content, force) {
|
||||
if (content || force)
|
||||
appendHead(` <meta name="${name}" content="${escape(content)}" >\n`);
|
||||
}
|
||||
|
||||
appendHead(`
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,${favicon}">
|
||||
<link href="/rss.xml" rel="alternate" type="application/rss+xml" title="Articles from Distill">
|
||||
<link rel="canonical" href="${data.url}">
|
||||
<title>${data.title}</title>
|
||||
`);
|
||||
|
||||
appendHead(`
|
||||
<!-- https://schema.org/Article -->
|
||||
<meta property="article:published" itemprop="datePublished" content="${data.publishedYear}-${data.publishedMonthPadded}-${data.publishedDayPadded}" />
|
||||
<meta property="article:created" itemprop="dateCreated" content="${data.publishedDate}" />
|
||||
<meta property="article:modified" itemprop="dateModified" content="${data.updatedDate}" />
|
||||
`);
|
||||
data.authors.forEach((a) => {
|
||||
appendHtml(head, `
|
||||
<meta property="article:author" content="${a.firstName} ${a.lastName}" />`)
|
||||
});
|
||||
|
||||
appendHead(`
|
||||
<!-- https://developers.facebook.com/docs/sharing/webmasters#markup -->
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta property="og:title" content="${data.title}"/>
|
||||
<meta property="og:description" content="${data.description}">
|
||||
<meta property="og:url" content="${data.url}"/>
|
||||
<meta property="og:image" content="${data.previewURL}"/>
|
||||
<meta property="og:locale" content="en_US" />
|
||||
<meta property="og:site_name" content="Distill" />
|
||||
`);
|
||||
|
||||
appendHead(`
|
||||
<!-- https://dev.twitter.com/cards/types/summary -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="${data.title}">
|
||||
<meta name="twitter:description" content="${data.description}">
|
||||
<meta name="twitter:url" content="${data.url}">
|
||||
<meta name="twitter:image" content="${data.previewURL}">
|
||||
<meta name="twitter:image:width" content="560">
|
||||
<meta name="twitter:image:height" content="295">
|
||||
`);
|
||||
|
||||
// if this is a proprer article, generate Google Scholar meta data
|
||||
if (data.doiSuffix){
|
||||
appendHead(`
|
||||
<!-- https://scholar.google.com/intl/en/scholar/inclusion.html#indexing -->\n`);
|
||||
|
||||
meta("citation_title", data.title);
|
||||
//meta("citation_fulltext_html_url", data.url);
|
||||
meta("citation_volume", data.volume);
|
||||
meta("citation_issue", data.issue);
|
||||
meta("citation_firstpage", data.doiSuffix? `e${data.doiSuffix}` : undefined);
|
||||
meta("citation_doi", data.doi);
|
||||
|
||||
let journal = data.journal || {};
|
||||
meta("citation_journal_title", journal.full_title || journal.title);
|
||||
meta("citation_journal_abbrev", journal.abbrev_title);
|
||||
meta("citation_issn", journal.issn);
|
||||
meta("citation_publisher", journal.publisher);
|
||||
meta("citation_fulltext_world_readable", "", true);
|
||||
|
||||
if (data.publishedDate){
|
||||
let zeroPad = (n) => { return n < 10 ? "0" + n : n; };
|
||||
meta("citation_online_date", `${data.publishedYear}/${data.publishedMonthPadded}/${data.publishedDayPadded}`);
|
||||
// Should we do something different here?
|
||||
meta("citation_publication_date", `${data.publishedYear}/${data.publishedMonthPadded}/${data.publishedDayPadded}`);
|
||||
}
|
||||
|
||||
(data.authors || []).forEach((a) => {
|
||||
meta("citation_author", `${a.lastName}, ${a.firstName}`);
|
||||
meta("citation_author_institution", a.affiliation);
|
||||
});
|
||||
|
||||
if (data.citations) {
|
||||
data.citations.forEach(key => {
|
||||
let d = data.bibliography[key];
|
||||
if(!d) {
|
||||
console.warn("No bibliography data fround for " + key)
|
||||
} else {
|
||||
meta("citation_reference", citation_meta_content(data.bibliography[key]) )
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function appendHtml(el, html) {
|
||||
el.innerHTML += html;
|
||||
}
|
||||
|
||||
function citation_meta_content(ref){
|
||||
// Special test for arxiv
|
||||
var content = `citation_title=${ref.title};`;
|
||||
|
||||
let name_strings = ref.author.split(" and ").forEach(name => {
|
||||
name = name.trim();
|
||||
if (name.indexOf(",") != -1){
|
||||
var last = name.split(",")[0].trim();
|
||||
var firsts = name.split(",")[1].trim();
|
||||
} else {
|
||||
var last = name.split(" ").slice(-1)[0].trim();
|
||||
var firsts = name.split(" ").slice(0,-1).join(" ");
|
||||
}
|
||||
content += `citation_author=${firsts} ${last};`;
|
||||
});
|
||||
|
||||
if ("year" in ref) {
|
||||
content += `citation_publication_date=${ref.year};`;
|
||||
}
|
||||
|
||||
var arxiv_id_search = /https?:\/\/arxiv\.org\/pdf\/([0-9]*\.[0-9]*)\.pdf/.exec(ref.url);
|
||||
arxiv_id_search = arxiv_id_search || /https?:\/\/arxiv\.org\/abs\/([0-9]*\.[0-9]*)/.exec(ref.url);
|
||||
arxiv_id_search = arxiv_id_search || /arXiv preprint arXiv:([0-9]*\.[0-9]*)/.exec(ref.journal);
|
||||
if (arxiv_id_search && arxiv_id_search[1]){
|
||||
content += `citation_arxiv_id=${arxiv_id_search[1]};`;
|
||||
return content;
|
||||
}
|
||||
if ("journal" in ref){
|
||||
content += `citation_journal_title=${ref.journal};`;
|
||||
}
|
||||
if ("volume" in ref) {
|
||||
content += `citation_volume=${ref.volume};`;
|
||||
}
|
||||
if ("issue" in ref || "number" in ref){
|
||||
content += `citation_number=${ref.issue || ref.number};`;
|
||||
}
|
||||
/*content += `citation_first_page=${};`;
|
||||
content += `citation_publication_date=${};`;*/
|
||||
return content;
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
dt-article {
|
||||
display: block;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
font: 17px/1.55em -apple-system, BlinkMacSystemFont, "Roboto", sans-serif;
|
||||
padding-bottom: 72px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
dt-article {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H1 */
|
||||
|
||||
dt-article h1 {
|
||||
margin-top: 18px;
|
||||
font-weight: 400;
|
||||
font-size: 40px;
|
||||
line-height: 1em;
|
||||
font-family: HoeflerText-Regular, Cochin, Georgia, serif;
|
||||
}
|
||||
@media(min-width: 768px) {
|
||||
dt-article h1 {
|
||||
font-size: 46px;
|
||||
margin-top: 48px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
.centered h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
dt-article h1 {
|
||||
font-size: 50px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
dt-article > h1:first-of-type,
|
||||
dt-article section > h1:first-of-type {
|
||||
margin-top: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media(min-width: 1200px) {
|
||||
dt-article h1 {
|
||||
font-size: 56px;
|
||||
}
|
||||
|
||||
dt-article > h1:first-of-type {
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H2 */
|
||||
|
||||
dt-article h2 {
|
||||
font-family: HoeflerText-Regular, Cochin, Georgia, serif;
|
||||
font-weight: 400;
|
||||
font-size: 26px;
|
||||
line-height: 1.25em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
dt-article h2 {
|
||||
margin-top: 48px;
|
||||
font-size: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
dt-article h1 + h2 {
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 8px;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
.centered h1 + h2 {
|
||||
text-align: center;
|
||||
}
|
||||
dt-article h1 + h2 {
|
||||
margin-top: 12px;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H3 */
|
||||
|
||||
dt-article h3 {
|
||||
font-family: HoeflerText-Regular, Georgia, serif;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
line-height: 1.4em;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 18px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dt-article h1 + h3 {
|
||||
margin-top: 48px;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
dt-article h3 {
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H4 */
|
||||
|
||||
dt-article h4 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
dt-article a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
dt-article p,
|
||||
dt-article ul,
|
||||
dt-article ol {
|
||||
margin-bottom: 24px;
|
||||
font-family: Georgia, serif;
|
||||
}
|
||||
|
||||
dt-article p b,
|
||||
dt-article ul b,
|
||||
dt-article ol b {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
dt-article a {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
dt-article a:hover {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
dt-article .link {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
dt-article ul,
|
||||
dt-article ol {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
dt-article li {
|
||||
margin-bottom: 24px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
dt-article pre {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
dt-article hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
dt-article section {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
|
||||
dt-article table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
dt-article table th {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
dt-article table td {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
dt-article table th,
|
||||
dt-article table td {
|
||||
font-size: 15px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
/* Figure */
|
||||
|
||||
dt-article figure {
|
||||
position: relative;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
dt-article figure {
|
||||
margin-top: 48px;
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
dt-article figure img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
dt-article figure svg text,
|
||||
dt-article figure svg tspan {
|
||||
}
|
||||
|
||||
dt-article figure figcaption {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
@media(min-width: 1024px) {
|
||||
dt-article figure figcaption {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
dt-article figure.external img {
|
||||
background: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
dt-article figure figcaption a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
dt-article span.equation-mimic {
|
||||
font-family: georgia;
|
||||
font-size: 115%;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
dt-article figure figcaption b {
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 1.0);
|
||||
}
|
||||
|
||||
dt-article > dt-code,
|
||||
dt-article section > dt-code {
|
||||
display: block;
|
||||
}
|
||||
|
||||
dt-article .citation {
|
||||
color: #668;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
dt-include {
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
html {
|
||||
font: 400 16px/1.55em -apple-system, BlinkMacSystemFont, "Roboto", Helvetica, sans-serif;
|
||||
/*background-color: hsl(223, 9%, 25%);*/
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
text-size-adjust: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
/*background-color: hsl(223, 9%, 25%);*/
|
||||
}
|
||||
|
||||
a {
|
||||
color: #004276;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: Cochin, Georgia, serif;
|
||||
}
|
||||
|
||||
/*
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}*/
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 2px;
|
||||
padding: 4px 7px;
|
||||
font-size: 15px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: block;
|
||||
background: white;
|
||||
border-left: 3px solid rgba(0, 0, 0, 0.05);
|
||||
padding: 0 0 0 24px;
|
||||
}
|
||||
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection, code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #a67f59;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
Column: 60px
|
||||
Gutter: 24px
|
||||
|
||||
Body: 648px
|
||||
- 8 columns
|
||||
- 7 gutters
|
||||
Middle: 816px
|
||||
Page: 984px
|
||||
- 12 columns
|
||||
- 11 gutters
|
||||
*/
|
||||
|
||||
.l-body,
|
||||
.l-body-outset,
|
||||
.l-page,
|
||||
.l-page-outset,
|
||||
.l-middle,
|
||||
.l-middle-outset,
|
||||
dt-article > div,
|
||||
dt-article > p,
|
||||
dt-article > h1,
|
||||
dt-article > h2,
|
||||
dt-article > h3,
|
||||
dt-article > h4,
|
||||
dt-article > figure,
|
||||
dt-article > table,
|
||||
dt-article > ol,
|
||||
dt-article > ul,
|
||||
dt-article > dt-byline,
|
||||
dt-article > dt-math,
|
||||
dt-article > dt-code,
|
||||
dt-article section > div,
|
||||
dt-article section > p,
|
||||
dt-article section > h1,
|
||||
dt-article section > h2,
|
||||
dt-article section > h3,
|
||||
dt-article section > h4,
|
||||
dt-article section > figure,
|
||||
dt-article section > table,
|
||||
dt-article section > ol,
|
||||
dt-article section > ul,
|
||||
dt-article section > dt-byline,
|
||||
dt-article section > dt-code {
|
||||
width: auto;
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
.l-body,
|
||||
.l-body-outset,
|
||||
.l-page,
|
||||
.l-page-outset,
|
||||
.l-middle,
|
||||
.l-middle-outset,
|
||||
dt-article > div,
|
||||
dt-article > p,
|
||||
dt-article > h1,
|
||||
dt-article > h2,
|
||||
dt-article > h3,
|
||||
dt-article > h4,
|
||||
dt-article > figure,
|
||||
dt-article > table,
|
||||
dt-article > ol,
|
||||
dt-article > ul,
|
||||
dt-article > dt-byline,
|
||||
dt-article > dt-math,
|
||||
dt-article > dt-code,
|
||||
dt-article section > div,
|
||||
dt-article section > p,
|
||||
dt-article section > h1,
|
||||
dt-article section > h2,
|
||||
dt-article section > h3,
|
||||
dt-article section > h4,
|
||||
dt-article section > figure,
|
||||
dt-article section > table,
|
||||
dt-article section > ol,
|
||||
dt-article section > ul,
|
||||
dt-article section > dt-byline,
|
||||
dt-article section > dt-code {
|
||||
margin-left: 72px;
|
||||
margin-right: 72px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
.l-body,
|
||||
dt-article > div,
|
||||
dt-article > p,
|
||||
dt-article > h2,
|
||||
dt-article > h3,
|
||||
dt-article > h4,
|
||||
dt-article > figure,
|
||||
dt-article > table,
|
||||
dt-article > ol,
|
||||
dt-article > ul,
|
||||
dt-article > dt-byline,
|
||||
dt-article > dt-math,
|
||||
dt-article > dt-code,
|
||||
dt-article section > div,
|
||||
dt-article section > p,
|
||||
dt-article section > h2,
|
||||
dt-article section > h3,
|
||||
dt-article section > h4,
|
||||
dt-article section > figure,
|
||||
dt-article section > table,
|
||||
dt-article section > ol,
|
||||
dt-article section > ul,
|
||||
dt-article section > dt-byline,
|
||||
dt-article section > dt-code {
|
||||
margin-left: calc(50% - 984px / 2);
|
||||
width: 648px;
|
||||
}
|
||||
.l-body-outset,
|
||||
dt-article .l-body-outset {
|
||||
margin-left: calc(50% - 984px / 2 - 96px/2);
|
||||
width: calc(648px + 96px);
|
||||
}
|
||||
.l-middle,
|
||||
dt-article .l-middle {
|
||||
width: 816px;
|
||||
margin-left: calc(50% - 984px / 2);
|
||||
margin-right: auto;
|
||||
}
|
||||
.l-middle-outset,
|
||||
dt-article .l-middle-outset {
|
||||
width: calc(816px + 96px);
|
||||
margin-left: calc(50% - 984px / 2 - 48px);
|
||||
margin-right: auto;
|
||||
}
|
||||
dt-article > h1,
|
||||
dt-article section > h1,
|
||||
.l-page,
|
||||
dt-article .l-page,
|
||||
dt-article.centered .l-page {
|
||||
width: 984px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.l-page-outset,
|
||||
dt-article .l-page-outset,
|
||||
dt-article.centered .l-page-outset {
|
||||
width: 1080px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.l-screen,
|
||||
dt-article .l-screen,
|
||||
dt-article.centered .l-screen {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: auto;
|
||||
}
|
||||
.l-screen-inset,
|
||||
dt-article .l-screen-inset,
|
||||
dt-article.centered .l-screen-inset {
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
width: auto;
|
||||
}
|
||||
.l-gutter,
|
||||
dt-article .l-gutter {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 24px;
|
||||
margin-right: calc((100vw - 984px) / 2 + 168px);
|
||||
width: calc((984px - 648px) / 2 - 24px);
|
||||
}
|
||||
|
||||
/* Side */
|
||||
.side.l-body,
|
||||
dt-article .side.l-body {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px + 648px) / 2);
|
||||
width: calc(648px / 2 - 24px - 84px);
|
||||
}
|
||||
.side.l-body-outset,
|
||||
dt-article .side.l-body-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px + 648px - 48px) / 2);
|
||||
width: calc(648px / 2 - 48px + 24px);
|
||||
}
|
||||
.side.l-middle,
|
||||
dt-article .side.l-middle {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: calc(456px - 84px);
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px) / 2 + 168px);
|
||||
}
|
||||
.side.l-middle-outset,
|
||||
dt-article .side.l-middle-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 456px;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px) / 2 + 168px);
|
||||
}
|
||||
.side.l-page,
|
||||
dt-article .side.l-page {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-left: 48px;
|
||||
width: calc(624px - 84px);
|
||||
margin-right: calc((100vw - 984px) / 2);
|
||||
}
|
||||
.side.l-page-outset,
|
||||
dt-article .side.l-page-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 624px;
|
||||
margin-right: calc((100vw - 984px) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Centered */
|
||||
|
||||
@media(min-width: 1080px) {
|
||||
.centered .l-body,
|
||||
.centered.l-body,
|
||||
dt-article.centered > div,
|
||||
dt-article.centered > p,
|
||||
dt-article.centered > h2,
|
||||
dt-article.centered > h3,
|
||||
dt-article.centered > h4,
|
||||
dt-article.centered > figure,
|
||||
dt-article.centered > table,
|
||||
dt-article.centered > ol,
|
||||
dt-article.centered > ul,
|
||||
dt-article.centered > dt-byline,
|
||||
dt-article.centered > dt-code,
|
||||
dt-article.centered section > div,
|
||||
dt-article.centered section > p,
|
||||
dt-article.centered section > h2,
|
||||
dt-article.centered section > h3,
|
||||
dt-article.centered section > h4,
|
||||
dt-article.centered section > figure,
|
||||
dt-article.centered section > table,
|
||||
dt-article.cebtered section > ol,
|
||||
dt-article.centered section > ul,
|
||||
dt-article.centered section > dt-byline,
|
||||
dt-article.centered section > dt-code,
|
||||
dt-article section.centered > div,
|
||||
dt-article section.centered > p,
|
||||
dt-article section.centered > h2,
|
||||
dt-article section.centered > h3,
|
||||
dt-article section.centered > h4,
|
||||
dt-article section.centered > figure,
|
||||
dt-article section.centered > table,
|
||||
dt-article section.centered > ol,
|
||||
dt-article section.centered > ul,
|
||||
dt-article section.centered > dt-byline,
|
||||
dt-article section.centered > dt-code {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 648px;
|
||||
}
|
||||
.centered .l-body-outset,
|
||||
.centered.l-body-outset,
|
||||
dt-article.centered .l-body-outset {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: calc(648px + 96px);
|
||||
}
|
||||
dt-article.centered > h1,
|
||||
dt-article.centered section > h1,
|
||||
dt-article section.centered > h1,
|
||||
.centered .l-middle,
|
||||
.centered.l-middle,
|
||||
dt-article.centered .l-middle {
|
||||
width: 816px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.centered .l-middle-outset,
|
||||
.centered.l-middle-outset,
|
||||
dt-article.centered .l-middle-outset {
|
||||
width: calc(816px + 96px);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* page and screen are already centered */
|
||||
|
||||
/* Side */
|
||||
|
||||
.centered .side.l-body,
|
||||
.centered dt-article .side.l-body {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 648px) / 2);
|
||||
width: calc(4 * 60px + 3 * 24px);
|
||||
}
|
||||
.centered .side.l-body-outset,
|
||||
.centered dt-article .side.l-body-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 648px) / 2);
|
||||
width: calc(4 * 60px + 3 * 24px);
|
||||
}
|
||||
.centered .side.l-middle,
|
||||
.centered dt-article .side.l-middle {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 396px;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px) / 2 + 168px / 2);
|
||||
}
|
||||
.centered .side.l-middle-outset,
|
||||
.centered dt-article .side.l-middle-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 456px;
|
||||
margin-left: 48px;
|
||||
margin-right: calc((100vw - 984px) / 2 + 168px);
|
||||
}
|
||||
.centered .side.l-page,
|
||||
.centered dt-article .side.l-page {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 480px;
|
||||
margin-right: calc((100vw - 984px) / 2);
|
||||
}
|
||||
.centered .side.l-page-outset,
|
||||
.centered dt-article .side.l-page-outset {
|
||||
clear: both;
|
||||
float: right;
|
||||
width: 480px;
|
||||
margin-right: calc((100vw - 984px) / 2);
|
||||
}
|
||||
.centered .l-gutter,
|
||||
.centered.l-gutter,
|
||||
dt-article.centered .l-gutter {
|
||||
clear: both;
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
margin-left: 24px;
|
||||
margin-right: calc((100vw - 984px) / 2);
|
||||
width: calc((984px - 648px) / 2 - 24px);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Rows and Columns */
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
}
|
||||
.column {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
margin-right: 24px;
|
||||
margin-left: 24px;
|
||||
}
|
||||
.row > .column:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
.row > .column:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
@@ -1,30 +1,20 @@
|
||||
@media print {
|
||||
|
||||
@media print {
|
||||
@page {
|
||||
size: 8in 11in;
|
||||
@bottom-right {
|
||||
content: counter(page) " of " counter(pages);
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
/* no general margins -- CSS Grid takes care of those */
|
||||
}
|
||||
|
||||
p, code {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
h2, h3 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
|
||||
d-header {
|
||||
dt-header {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
d-footer {
|
||||
dt-footer {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import base from './styles-base.css';
|
||||
import layout from './styles-layout.css';
|
||||
import article from './styles-article.css';
|
||||
import code from './styles-code.css';
|
||||
import print from './styles-print.css';
|
||||
|
||||
export default function(dom) {
|
||||
let s = dom.createElement("style");
|
||||
s.textContent = base + layout + article + code + print;
|
||||
dom.querySelector("head").appendChild(s);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function(dom) {
|
||||
export default function(dom, data) {
|
||||
|
||||
var textNodes = dom.createTreeWalker(
|
||||
dom.body,
|
||||
@@ -6,11 +6,10 @@ export default function(dom) {
|
||||
);
|
||||
while (textNodes.nextNode()) {
|
||||
var n = textNodes.currentNode,
|
||||
text = n.nodeValue;
|
||||
text = n.nodeValue;
|
||||
if (text && acceptNode(n)) {
|
||||
text = quotes(text);
|
||||
text = punctuation(text);
|
||||
text = ligatures(text);
|
||||
n.nodeValue = text;
|
||||
}
|
||||
}
|
||||
@@ -18,22 +17,19 @@ export default function(dom) {
|
||||
|
||||
function acceptNode(node) {
|
||||
var parent = node.parentElement;
|
||||
var isMath = (parent && parent.getAttribute && parent.getAttribute('class')) ? parent.getAttribute('class').includes('katex') || parent.getAttribute('class').includes('MathJax') : false;
|
||||
var isMath = (parent && parent.getAttribute && parent.getAttribute("class")) ? parent.getAttribute("class").includes("katex") || parent.getAttribute("class").includes("MathJax") : false;
|
||||
return parent &&
|
||||
parent.nodeName !== 'SCRIPT' &&
|
||||
parent.nodeName !== 'STYLE' &&
|
||||
parent.nodeName !== 'CODE' &&
|
||||
parent.nodeName !== 'PRE' &&
|
||||
parent.nodeName !== 'SPAN' &&
|
||||
parent.nodeName !== 'D-HEADER' &&
|
||||
parent.nodeName !== 'D-BYLINE' &&
|
||||
parent.nodeName !== 'D-MATH' &&
|
||||
parent.nodeName !== 'D-CODE' &&
|
||||
parent.nodeName !== 'D-BIBLIOGRAPHY' &&
|
||||
parent.nodeName !== 'D-FOOTER' &&
|
||||
parent.nodeName !== 'D-APPENDIX' &&
|
||||
parent.nodeName !== 'D-FRONTMATTER' &&
|
||||
parent.nodeName !== 'D-TOC' &&
|
||||
parent.nodeName !== "SCRIPT" &&
|
||||
parent.nodeName !== "STYLE" &&
|
||||
parent.nodeName !== "CODE" &&
|
||||
parent.nodeName !== "PRE" &&
|
||||
parent.nodeName !== "SPAN" &&
|
||||
parent.nodeName !== "DT-HEADER" &&
|
||||
parent.nodeName !== "DT-BYLINE" &&
|
||||
parent.nodeName !== "DT-MATH" &&
|
||||
parent.nodeName !== "DT-CODE" &&
|
||||
parent.nodeName !== "DT-BIBLIOGRAPHY" &&
|
||||
parent.nodeName !== "DT-FOOTER" &&
|
||||
parent.nodeType !== 8 && //comment nodes
|
||||
!isMath;
|
||||
}
|
||||
@@ -45,26 +41,29 @@ function acceptNode(node) {
|
||||
* @link https://github.com/davidmerfield/Typeset.js
|
||||
* @author David Merfield
|
||||
*/
|
||||
// which has a CC0 license
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
// which has a CC0 license
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
|
||||
function punctuation(text){
|
||||
|
||||
// Dashes
|
||||
text = text.replace(/--/g, '\u2014');
|
||||
text = text.replace(/\s*\u2014\s*/g,'\u2009\u2014\u2009'); //this has thin spaces
|
||||
text = text.replace(/ \u2014 /g,"\u2009\u2014\u2009"); //this has thin spaces
|
||||
|
||||
// The following are temporary commented out because incompatibility
|
||||
// with katex
|
||||
|
||||
// Elipses
|
||||
text = text.replace(/\.\.\./g,'…');
|
||||
// text = text.replace(/\.\.\./g,'…');
|
||||
|
||||
// Nbsp for punc with spaces
|
||||
var NBSP = '\u00a0';
|
||||
var NBSP_PUNCTUATION_START = /([«¿¡]) /g;
|
||||
var NBSP_PUNCTUATION_END = / ([!?:;.,‽»])/g;
|
||||
// var NBSP = "\u00a0";
|
||||
// var NBSP_PUNCTUATION_START = /([«¿¡]) /g;
|
||||
// var NBSP_PUNCTUATION_END = / ([\!\?:;\.,‽»])/g;
|
||||
|
||||
text = text.replace(NBSP_PUNCTUATION_START, '$1' + NBSP);
|
||||
text = text.replace(NBSP_PUNCTUATION_END, NBSP + '$1');
|
||||
// text = text.replace(NBSP_PUNCTUATION_START, '$1' + NBSP);
|
||||
// text = text.replace(NBSP_PUNCTUATION_END, NBSP + '$1');
|
||||
|
||||
return text;
|
||||
}
|
||||
@@ -72,7 +71,7 @@ function punctuation(text){
|
||||
function quotes(text) {
|
||||
|
||||
text = text
|
||||
.replace(/(\W|^)"([^\s!?:;.,‽»])/g, '$1\u201c$2') // beginning "
|
||||
.replace(/(\W|^)"([^\s\!\?:;\.,‽»])/g, '$1\u201c$2') // beginning "
|
||||
.replace(/(\u201c[^"]*)"([^"]*$|[^\u201c"]*\u201c)/g, '$1\u201d$2') // ending "
|
||||
.replace(/([^0-9])"/g,'$1\u201d') // remaining " at end of word
|
||||
.replace(/(\W|^)'(\S)/g, '$1\u2018$2') // beginning '
|
||||
@@ -85,8 +84,8 @@ function quotes(text) {
|
||||
.replace(/'/g, '\u2032');
|
||||
|
||||
// Allow escaped quotes
|
||||
text = text.replace(/\\“/, '"');
|
||||
text = text.replace(/\\”/, '"');
|
||||
text = text.replace(/\\“/, '\"');
|
||||
text = text.replace(/\\”/, '\"');
|
||||
text = text.replace(/\\’/, '\'');
|
||||
text = text.replace(/\\‘/, '\'');
|
||||
|
||||
@@ -95,8 +94,8 @@ function quotes(text) {
|
||||
|
||||
function ligatures(text){
|
||||
|
||||
text = text.replace(/fi/g, 'fi');
|
||||
text = text.replace(/fl/g, 'fl');
|
||||
// text = text.replace(/fi/g, 'fi');
|
||||
// text = text.replace(/fl/g, 'fl');
|
||||
|
||||
return text;
|
||||
}
|
||||
return text;
|
||||
};
|
||||
@@ -1,188 +0,0 @@
|
||||
<!doctype html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
|
||||
<script src="../dist/components.js"></script>
|
||||
|
||||
<d-front-matter>
|
||||
<script type="text/yml">
|
||||
title: Demo Title Attention and Augmented Recurrent Neural Networks
|
||||
published: Jan 10, 2017
|
||||
authors:
|
||||
- Chris Olah:
|
||||
- Shan Carter: http://shancarter.com
|
||||
affiliations:
|
||||
- Google Brain
|
||||
- Google Brain: http://g.co/brain
|
||||
</script>
|
||||
</d-front-matter>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<d-article>
|
||||
<d-title>
|
||||
<h1>Attention and Augmented Recurrent Neural Networks</h1>
|
||||
<!-- <h2>Some people want a deck</h2> -->
|
||||
<d-byline></d-byline>
|
||||
</d-title>
|
||||
<d-abstract>
|
||||
<p>This is the first paragraph of the article. Test a long — dash -- here it is.</p>
|
||||
</d-abstract>
|
||||
<p>This is the first paragraph of the article. Test a long — 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>
|
||||
<hr>
|
||||
<div style="max-width: 800px; background-color: red; height: 100px; border-radius: 50px;"></div>
|
||||
<p>Here's a test of an inline equation <d-math>c = a^2 + b^2</d-math>. And then there's a block equation:</p>
|
||||
<d-math block>
|
||||
c = \pm \sqrt{ \sum_{i=0}^{n}{a^{222} + b^2}}
|
||||
</d-math>
|
||||
<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>
|
||||
<h2>Displaying code snippets</h2>
|
||||
<p>Some inline javascript:<d-code language="javascript">var x = 25;</d-code></p>
|
||||
<p>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>That's it for the example article!</p>
|
||||
<aside>Some text.</aside>
|
||||
</d-article>
|
||||
|
||||
<d-appendix>
|
||||
<d-acknowledgements>
|
||||
<h3>Contributions</h3>
|
||||
<p>Some text describing who did what.</p>
|
||||
<h4>Reviewers</h4>
|
||||
<p>Some text with links describing who reviewed the article.</p>
|
||||
</d-acknowledgements>
|
||||
|
||||
<d-footnote-list></d-footnote-list>
|
||||
|
||||
<d-bibliography><script type="text/bibtex">
|
||||
|
||||
@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={arXiv preprint arXiv:1502.04623},
|
||||
year={2015},
|
||||
url ={https://arxiv.org/pdf/1502.04623.pdf}
|
||||
}
|
||||
@article{mercier2011humans,
|
||||
title={Why do humans reason? Arguments for an argumentative theory},
|
||||
author={Mercier, Hugo and Sperber, Dan},
|
||||
journal={Behavioral and brain sciences},
|
||||
volume={34},
|
||||
number={02},
|
||||
pages={57--74},
|
||||
year={2011},
|
||||
publisher={Cambridge Univ Press},
|
||||
doi={10.1017/S0140525X10000968}
|
||||
}
|
||||
|
||||
@article{dong2014image,
|
||||
title={Image super-resolution using deep convolutional networks},
|
||||
author={Dong, Chao and Loy, Chen Change and He, Kaiming and Tang, Xiaoou},
|
||||
journal={arXiv preprint arXiv:1501.00092},
|
||||
year={2014},
|
||||
url={https://arxiv.org/pdf/1501.00092.pdf}
|
||||
}
|
||||
|
||||
@article{dumoulin2016adversarially,
|
||||
title={Adversarially Learned Inference},
|
||||
author={Dumoulin, Vincent and Belghazi, Ishmael and Poole, Ben and Lamb, Alex and Arjovsky, Martin and Mastropietro, Olivier and Courville, Aaron},
|
||||
journal={arXiv preprint arXiv:1606.00704},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.00704.pdf}
|
||||
}
|
||||
|
||||
@article{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}
|
||||
}
|
||||
|
||||
@article{gauthier2014conditional,
|
||||
title={Conditional generative adversarial nets for convolutional face generation},
|
||||
author={Gauthier, Jon},
|
||||
journal={Class Project for Stanford CS231N: Convolutional Neural Networks for Visual Recognition, Winter semester},
|
||||
volume={2014},
|
||||
year={2014},
|
||||
url={http://www.foldl.me/uploads/papers/tr-cgans.pdf}
|
||||
}
|
||||
|
||||
@article{johnson2016perceptual,
|
||||
title={Perceptual losses for real-time style transfer and super-resolution},
|
||||
author={Johnson, Justin and Alahi, Alexandre and Fei-Fei, Li},
|
||||
journal={arXiv preprint arXiv:1603.08155},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1603.08155.pdf}
|
||||
}
|
||||
|
||||
@article{mordvintsev2015inceptionism,
|
||||
title={Inceptionism: Going deeper into neural networks},
|
||||
author={Mordvintsev, Alexander and Olah, Christopher and Tyka, Mike},
|
||||
journal={Google Research Blog},
|
||||
year={2015},
|
||||
url={https://research.googleblog.com/2015/06/inceptionism-going-deeper-into-neural.html}
|
||||
}
|
||||
|
||||
@misc{mordvintsev2016deepdreaming,
|
||||
title={DeepDreaming with TensorFlow},
|
||||
author={Mordvintsev, Alexander},
|
||||
year={2016},
|
||||
url={https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/deepdream/deepdream.ipynb},
|
||||
}
|
||||
|
||||
@article{radford2015unsupervised,
|
||||
title={Unsupervised representation learning with deep convolutional generative adversarial networks},
|
||||
author={Radford, Alec and Metz, Luke and Chintala, Soumith},
|
||||
journal={arXiv preprint arXiv:1511.06434},
|
||||
year={2015},
|
||||
url={https://arxiv.org/pdf/1511.06434.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{salimans2016improved,
|
||||
title={Improved techniques for training gans},
|
||||
author={Salimans, Tim and Goodfellow, Ian and Zaremba, Wojciech and Cheung, Vicki and Radford, Alec and Chen, Xi},
|
||||
booktitle={Advances in Neural Information Processing Systems},
|
||||
pages={2226--2234},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.03498.pdf}
|
||||
}
|
||||
|
||||
@article{shi2016deconvolution,
|
||||
title={Is the deconvolution layer the same as a convolutional layer?},
|
||||
author={Shi, Wenzhe and Caballero, Jose and Theis, Lucas and Huszar, Ferenc and Aitken, Andrew and Ledig, Christian and Wang, Zehan},
|
||||
journal={arXiv preprint arXiv:1609.07009},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1609.07009.pdf}
|
||||
}
|
||||
|
||||
</script></d-bibliography>
|
||||
|
||||
<distill-appendix> </distill-appendix>
|
||||
</d-appendix>
|
||||
</body>
|
||||
@@ -1,232 +0,0 @@
|
||||
<!DOCTYPE html><html lang="en"><head>
|
||||
<meta charset="utf8">
|
||||
|
||||
<script id="polyfills">
|
||||
if ('registerElement' in document &&
|
||||
'import' in document.createElement('link') &&
|
||||
'content' in document.createElement('template')) {
|
||||
// Platform supports webcomponents natively! :-)
|
||||
} else {
|
||||
// Platform does not support webcomponents--loading polyfills synchronously.
|
||||
const scriptTag = document.createElement('script');
|
||||
scriptTag.src = '../dist/webcomponents-lite.js';
|
||||
scriptTag.async = false;
|
||||
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
|
||||
}
|
||||
</script><script src="../dist/components.js"></script>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA99JREFUeNrsG4t1ozDMzQSM4A2ODUonKBucN2hugtIJ6E1AboLcBiQTkJsANiAb9OCd/OpzMWBJBl5TvaeXPiiyJetry0J8wW3D3QpjRh3GjneXDq+fSQA9s2mH9x3KDhN4foJfCb8N/Jrv+2fnDn8vLRQOplWHVYdvHZYdZsBcZP1vBmh/n8DzEmhUQDPaOuP9pFuY+JwJHwHnCLQE2tnWBGEyXozY9xCUgHMhhjE2I4heVWtgIkZ83wL6Qgxj1obfWBxymPwe+b00BCCRNPbwfb60yleAkkBHGT5AEehIYz7eJrFDMF9CvH4wwhcGHiHMneFvLDQwlwvMLQq58trRcYBWfYn0A0OgHWQUSu25mE+BnoYKnnEJoeIWAifzOv7vLWd2ZKRfWAIme3tOiUaQ3UnLkb0xj1FxRIeEGKaGIHOs9nEgLaaA9i0JRYo1Ic67wJW86KSKE/ZAM8KuVMk8ITVhmxUxJ3Cl2xlm9Vtkeju1+mpCQNxaEGNCY8bs9X2YqwNoQeGjBWut/ma0QAWy/TqAsHx9wSya3I5IRxOfTC+leG+kA/4vSeEcGBtNUN6byhu3+keEZCQJUNh8MAO7HL6H8pQLnsW/Hd4T4lv93TPjfM7A46iEEqbB5EDOvwYNW6tGNZzT/o+CZ6sqZ6wUtR/wf7mi/VL8iNciT6rHih48Y55b4nKCHJCCzb4y0nwFmin3ZEMIoLfZF8F7nncFmvnWBaBj7CGAYA/WGJsUwHdYqVDwAmNsUgAx4CGgAA7GOOxADYOFWOaIKifuVYzmOpREqA21Mo7aPsgiY1PhOMAmxtR+AUbYH3Id2wc0SAFIQTsn9IUGWR8k9jx3vtXSiAacFxTAGakBk9UudkNECd6jLe+6HrshshvIuC6IlLMRy7er+JpcKma24SlE4cFZSZJDGVVrsNvitQhQrDhW0jfiOLfFd47C42eHT56D/BK0To+58Ahj+cAT8HT1UWlfLZCCd/uKawzU0Rh2EyIX/Icqth3niG8ybNroezwe6khdCNxRN+l4XGdOLVLlOOt2hTRJlr1ETIuMAltVTMz70mJrkdGAaZLSmnBEqmAE32JCMmuTlCnRgsBENtOUpHhvvsYIL0ibnBkaC6QvKcR7738GKp0AKnim7xgUSNv1bpS8QwhBt8r+EP47v/oyRK/S34yJ9nT+AN0Tkm4OdB9E4BsmXM3SnMlRFUrtp6IDpV2eKzdYvF3etm3KhQksbOLChGkSmcBdmcEwvqkrMy5BzL00NZeu3qPYJOOuCc+5NjcWKXQxFvTa3NoXJ4d8in7fiAUuTt781dkvuHX4K8AA2Usy7yNKLy0AAAAASUVORK5CYII=
|
||||
">
|
||||
<link href="/rss.xml" rel="alternate" type="application/rss+xml" title="Articles from Distill">
|
||||
<link rel="canonical" href="undefined">
|
||||
<title>Demo Title Attention and Augmented Recurrent Neural Networks</title>
|
||||
|
||||
<!-- https://schema.org/Article -->
|
||||
<meta property="article:published" itemprop="datePublished" content="undefined-undefined-undefined">
|
||||
<meta property="article:modified" itemprop="dateModified" content="undefined">
|
||||
|
||||
<meta property="article:author" content="undefined undefined">
|
||||
<meta property="article:author" content="undefined undefined">
|
||||
<!-- https://developers.facebook.com/docs/sharing/webmasters#markup -->
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:title" content="Demo Title Attention and Augmented Recurrent Neural Networks">
|
||||
<meta property="og:description" content="undefined">
|
||||
<meta property="og:url" content="undefined">
|
||||
<meta property="og:image" content="undefined/thumbnail.jpg">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:site_name" content="Distill">
|
||||
|
||||
<!-- https://dev.twitter.com/cards/types/summary -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Demo Title Attention and Augmented Recurrent Neural Networks">
|
||||
<meta name="twitter:description" content="undefined">
|
||||
<meta name="twitter:url" content="undefined">
|
||||
<meta name="twitter:image" content="undefined/thumbnail.jpg">
|
||||
<meta name="twitter:image:width" content="560">
|
||||
<meta name="twitter:image:height" content="295">
|
||||
</head><body><distill-header></distill-header><d-front-matter>
|
||||
<script type="text/yml">
|
||||
title: Demo Title Attention and Augmented Recurrent Neural Networks
|
||||
published: Jan 10, 2017
|
||||
authors:
|
||||
- Chris Olah:
|
||||
- Shan Carter: http://shancarter.com
|
||||
affiliations:
|
||||
- Google Brain:
|
||||
- Google Brain: http://g.co/brain
|
||||
</script>
|
||||
</d-front-matter>
|
||||
|
||||
|
||||
|
||||
<d-article>
|
||||
<d-title>
|
||||
<h1>Attention and Augmented Recurrent Neural Networks</h1>
|
||||
<!-- <h2>Some people want a deck</h2> -->
|
||||
<d-byline></d-byline>
|
||||
</d-title>
|
||||
|
||||
<d-abstract>
|
||||
<p>This is the first paragraph of the article. Test a long — dash — here it is.</p>
|
||||
</d-abstract>
|
||||
<p>This is the first paragraph of the article. Test a long — 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>
|
||||
<p>Here’s a test of an inline equation <d-math>c = a^2 + b^2</d-math>. 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>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></p>
|
||||
<p>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>
|
||||
<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>
|
||||
<h2>Displaying code snippets</h2>
|
||||
<p>Some inline javascript:<d-code language="javascript">var x = 25;</d-code></p>
|
||||
<p>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>That’s it for the example article!</p>
|
||||
</d-article>
|
||||
|
||||
<d-appendix>
|
||||
<d-acknowledgements>
|
||||
<h3>Contributions</h3>
|
||||
<p>Some text describing who did what.</p>
|
||||
<h4>Reviewers</h4>
|
||||
<p>Some text with links describing who reviewed the article.</p>
|
||||
</d-acknowledgements>
|
||||
|
||||
<d-footnote-list></d-footnote-list>
|
||||
|
||||
<d-bibliography>
|
||||
<script type="text/bibtex">
|
||||
|
||||
@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={arXiv preprint arXiv:1502.04623},
|
||||
year={2015},
|
||||
url ={https://arxiv.org/pdf/1502.04623.pdf}
|
||||
}
|
||||
@article{mercier2011humans,
|
||||
title={Why do humans reason? Arguments for an argumentative theory},
|
||||
author={Mercier, Hugo and Sperber, Dan},
|
||||
journal={Behavioral and brain sciences},
|
||||
volume={34},
|
||||
number={02},
|
||||
pages={57--74},
|
||||
year={2011},
|
||||
publisher={Cambridge Univ Press},
|
||||
doi={10.1017/S0140525X10000968}
|
||||
}
|
||||
|
||||
@article{dong2014image,
|
||||
title={Image super-resolution using deep convolutional networks},
|
||||
author={Dong, Chao and Loy, Chen Change and He, Kaiming and Tang, Xiaoou},
|
||||
journal={arXiv preprint arXiv:1501.00092},
|
||||
year={2014},
|
||||
url={https://arxiv.org/pdf/1501.00092.pdf}
|
||||
}
|
||||
|
||||
@article{dumoulin2016adversarially,
|
||||
title={Adversarially Learned Inference},
|
||||
author={Dumoulin, Vincent and Belghazi, Ishmael and Poole, Ben and Lamb, Alex and Arjovsky, Martin and Mastropietro, Olivier and Courville, Aaron},
|
||||
journal={arXiv preprint arXiv:1606.00704},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.00704.pdf}
|
||||
}
|
||||
|
||||
@article{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}
|
||||
}
|
||||
|
||||
@article{gauthier2014conditional,
|
||||
title={Conditional generative adversarial nets for convolutional face generation},
|
||||
author={Gauthier, Jon},
|
||||
journal={Class Project for Stanford CS231N: Convolutional Neural Networks for Visual Recognition, Winter semester},
|
||||
volume={2014},
|
||||
year={2014},
|
||||
url={http://www.foldl.me/uploads/papers/tr-cgans.pdf}
|
||||
}
|
||||
|
||||
@article{johnson2016perceptual,
|
||||
title={Perceptual losses for real-time style transfer and super-resolution},
|
||||
author={Johnson, Justin and Alahi, Alexandre and Fei-Fei, Li},
|
||||
journal={arXiv preprint arXiv:1603.08155},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1603.08155.pdf}
|
||||
}
|
||||
|
||||
@article{mordvintsev2015inceptionism,
|
||||
title={Inceptionism: Going deeper into neural networks},
|
||||
author={Mordvintsev, Alexander and Olah, Christopher and Tyka, Mike},
|
||||
journal={Google Research Blog},
|
||||
year={2015},
|
||||
url={https://research.googleblog.com/2015/06/inceptionism-going-deeper-into-neural.html}
|
||||
}
|
||||
|
||||
@misc{mordvintsev2016deepdreaming,
|
||||
title={DeepDreaming with TensorFlow},
|
||||
author={Mordvintsev, Alexander},
|
||||
year={2016},
|
||||
url={https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/deepdream/deepdream.ipynb},
|
||||
}
|
||||
|
||||
@article{radford2015unsupervised,
|
||||
title={Unsupervised representation learning with deep convolutional generative adversarial networks},
|
||||
author={Radford, Alec and Metz, Luke and Chintala, Soumith},
|
||||
journal={arXiv preprint arXiv:1511.06434},
|
||||
year={2015},
|
||||
url={https://arxiv.org/pdf/1511.06434.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{salimans2016improved,
|
||||
title={Improved techniques for training gans},
|
||||
author={Salimans, Tim and Goodfellow, Ian and Zaremba, Wojciech and Cheung, Vicki and Radford, Alec and Chen, Xi},
|
||||
booktitle={Advances in Neural Information Processing Systems},
|
||||
pages={2226--2234},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.03498.pdf}
|
||||
}
|
||||
|
||||
@article{shi2016deconvolution,
|
||||
title={Is the deconvolution layer the same as a convolutional layer?},
|
||||
author={Shi, Wenzhe and Caballero, Jose and Theis, Lucas and Huszar, Ferenc and Aitken, Andrew and Ledig, Christian and Wang, Zehan},
|
||||
journal={arXiv preprint arXiv:1609.07009},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1609.07009.pdf}
|
||||
}
|
||||
|
||||
</script>
|
||||
</d-bibliography>
|
||||
|
||||
<distill-appendix> </distill-appendix>
|
||||
</d-appendix>
|
||||
|
||||
<distill-footer></distill-footer></body></html>
|
||||
@@ -1,130 +1,187 @@
|
||||
<!doctype html>
|
||||
<meta charset="utf8">
|
||||
<script src="../dist/template.js"></script>
|
||||
|
||||
<head>
|
||||
<script src="../dist/template.v2.js"></script>
|
||||
</head>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css" integrity="sha384-wITovz90syo1dJWVh32uuETPVEtGigN07tkttEqPv+uR2SE/mbQcG7ATL28aI9H0" crossorigin="anonymous">
|
||||
|
||||
<body>
|
||||
<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/",
|
||||
"affiliation":"Google Brain",
|
||||
"affiliationURL":"https://g.co/brain"
|
||||
},
|
||||
{
|
||||
"author":"Shan Carter",
|
||||
"authorURL":"https://shancarter.com/",
|
||||
"affiliation":"Google Brain",
|
||||
"affiliationURL":"https://g.co/brain"
|
||||
},
|
||||
{
|
||||
"author":"Ludwig Schubert",
|
||||
"authorURL":"https://shancarter.com/",
|
||||
"affiliation":"Google Brain",
|
||||
"affiliationURL":"https://g.co/brain"
|
||||
}
|
||||
],
|
||||
"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 as a means of dampening oscillations and speeding up the iterations, leading to faster convergence. But it has other interesting behavior. It allows a larger range of step-sizes to be used, and creates its own oscillations. What is going on?</p>
|
||||
</d-title>
|
||||
<d-article>
|
||||
<a class="marker" href="#section-1" id="section-1"><span>1</span></a>
|
||||
<h2>A Brief Survey of Techniques</h2>
|
||||
<p>Before diving in: if you haven’t encountered t-SNE before, here’s 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>
|
||||
<script type="text/front-matter">
|
||||
title: Article Title
|
||||
published: Jan 10, 2017
|
||||
authors:
|
||||
- Chris Olah:
|
||||
- Shan Carter: http://shancarter.com
|
||||
affiliations:
|
||||
- Google Brain:
|
||||
- Google Brain: http://g.co/brain
|
||||
</script>
|
||||
|
||||
<dt-article>
|
||||
<script type="text/article"></script>
|
||||
<h1>Hello World</h1>
|
||||
<h2>A description of the article</h2>
|
||||
<dt-byline></dt-byline>
|
||||
<p>This is the first paragraph of the article. Test a long — 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"></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>
|
||||
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two.</p>
|
||||
<p>Here's a test of an inline equation <dt-math>c = a^2 + b^2</dt-math>.</p>
|
||||
<dt-math block>c = \pm\sqrt{a^2 + b^2}</dt-math>
|
||||
<p>We can also cite <dt-cite key="gregor2015draw,mercier2011humans"></dt-cite> external publications. <dt-cite key="dong2014image,dumoulin2016guide,mordvintsev2015inceptionism"></dt-cite> We should also be testing footnotes<dt-fn>This will become a hoverable footnote.</dt-fn>.</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>
|
||||
<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>
|
||||
<p>Here's a javascript code block.</p>
|
||||
<dt-code block language="javascript">
|
||||
var x = 25;
|
||||
function(x){
|
||||
return x * x;
|
||||
}
|
||||
</dt-code>
|
||||
<p>We also support python.</p>
|
||||
<dt-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
|
||||
</dt-code>
|
||||
</dt-article>
|
||||
|
||||
</d-article>
|
||||
<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={arXiv preprint arXiv:1502.04623},
|
||||
year={2015},
|
||||
url ={https://arxiv.org/pdf/1502.04623.pdf}
|
||||
}
|
||||
@article{mercier2011humans,
|
||||
title={Why do humans reason? Arguments for an argumentative theory},
|
||||
author={Mercier, Hugo and Sperber, Dan},
|
||||
journal={Behavioral and brain sciences},
|
||||
volume={34},
|
||||
number={02},
|
||||
pages={57--74},
|
||||
year={2011},
|
||||
publisher={Cambridge Univ Press},
|
||||
doi={10.1017/S0140525X10000968}
|
||||
}
|
||||
|
||||
<d-appendix>
|
||||
@article{dong2014image,
|
||||
title={Image super-resolution using deep convolutional networks},
|
||||
author={Dong, Chao and Loy, Chen Change and He, Kaiming and Tang, Xiaoou},
|
||||
journal={arXiv preprint arXiv:1501.00092},
|
||||
year={2014},
|
||||
url={https://arxiv.org/pdf/1501.00092.pdf}
|
||||
}
|
||||
|
||||
@article{dumoulin2016adversarially,
|
||||
title={Adversarially Learned Inference},
|
||||
author={Dumoulin, Vincent and Belghazi, Ishmael and Poole, Ben and Lamb, Alex and Arjovsky, Martin and Mastropietro, Olivier and Courville, Aaron},
|
||||
journal={arXiv preprint arXiv:1606.00704},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.00704.pdf}
|
||||
}
|
||||
|
||||
@article{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}
|
||||
}
|
||||
|
||||
@article{donahue2016adversarial,
|
||||
title={Adversarial Feature Learning},
|
||||
author={Donahue, Jeff and Kr{\"a}henb{\"u}hl, Philipp and Darrell, Trevor},
|
||||
journal={arXiv preprint arXiv:1605.09782},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1605.09782.pdf}
|
||||
}
|
||||
|
||||
@article{gauthier2014conditional,
|
||||
title={Conditional generative adversarial nets for convolutional face generation},
|
||||
author={Gauthier, Jon},
|
||||
journal={Class Project for Stanford CS231N: Convolutional Neural Networks for Visual Recognition, Winter semester},
|
||||
volume={2014},
|
||||
year={2014},
|
||||
url={http://www.foldl.me/uploads/papers/tr-cgans.pdf}
|
||||
}
|
||||
|
||||
@article{henaff2015geodesics,
|
||||
title={Geodesics of learned representations},
|
||||
author={H{\'e}naff, Olivier J and Simoncelli, Eero P},
|
||||
journal={arXiv preprint arXiv:1511.06394},
|
||||
year={2015},
|
||||
url={https://arxiv.org/pdf/1511.06394.pdf}
|
||||
}
|
||||
|
||||
@article{johnson2016perceptual,
|
||||
title={Perceptual losses for real-time style transfer and super-resolution},
|
||||
author={Johnson, Justin and Alahi, Alexandre and Fei-Fei, Li},
|
||||
journal={arXiv preprint arXiv:1603.08155},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1603.08155.pdf}
|
||||
}
|
||||
|
||||
@article{mordvintsev2015inceptionism,
|
||||
title={Inceptionism: Going deeper into neural networks},
|
||||
author={Mordvintsev, Alexander and Olah, Christopher and Tyka, Mike},
|
||||
journal={Google Research Blog},
|
||||
year={2015},
|
||||
url={https://research.googleblog.com/2015/06/inceptionism-going-deeper-into-neural.html}
|
||||
}
|
||||
|
||||
@misc{mordvintsev2016deepdreaming,
|
||||
title={DeepDreaming with TensorFlow},
|
||||
author={Mordvintsev, Alexander},
|
||||
year={2016},
|
||||
url={https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/deepdream/deepdream.ipynb},
|
||||
}
|
||||
|
||||
@article{radford2015unsupervised,
|
||||
title={Unsupervised representation learning with deep convolutional generative adversarial networks},
|
||||
author={Radford, Alec and Metz, Luke and Chintala, Soumith},
|
||||
journal={arXiv preprint arXiv:1511.06434},
|
||||
year={2015},
|
||||
url={https://arxiv.org/pdf/1511.06434.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{salimans2016improved,
|
||||
title={Improved techniques for training gans},
|
||||
author={Salimans, Tim and Goodfellow, Ian and Zaremba, Wojciech and Cheung, Vicki and Radford, Alec and Chen, Xi},
|
||||
booktitle={Advances in Neural Information Processing Systems},
|
||||
pages={2226--2234},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.03498.pdf}
|
||||
}
|
||||
|
||||
@article{shi2016deconvolution,
|
||||
title={Is the deconvolution layer the same as a convolutional layer?},
|
||||
author={Shi, Wenzhe and Caballero, Jose and Theis, Lucas and Huszar, Ferenc and Aitken, Andrew and Ledig, Christian and Wang, Zehan},
|
||||
journal={arXiv preprint arXiv:1609.07009},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1609.07009.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{shi2016real,
|
||||
title={Real-time single image and video super-resolution using an efficient sub-pixel convolutional neural network},
|
||||
author={Shi, Wenzhe and Caballero, Jose and Husz{\'a}r, Ferenc and Totz, Johannes and Aitken, Andrew P and Bishop, Rob and Rueckert, Daniel and Wang, Zehan},
|
||||
booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition},
|
||||
pages={1874--1883},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1609.05158.pdf},
|
||||
doi={10.1109/cvpr.2016.207}
|
||||
}
|
||||
|
||||
</script>
|
||||
<dt-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>
|
||||
<p>List of who did what</p>
|
||||
</dt-appendix>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
@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={arXiv preprint arXiv:1502.04623},
|
||||
year={2015},
|
||||
url ={https://arxiv.org/pdf/1502.04623.pdf}
|
||||
journal={arXivreprint arXiv:1502.04623},
|
||||
year={2015}
|
||||
}
|
||||
@article{mercier2011humans,
|
||||
title={Why do humans reason? Arguments for an argumentative theory},
|
||||
@@ -13,87 +12,5 @@
|
||||
number={02},
|
||||
pages={57--74},
|
||||
year={2011},
|
||||
publisher={Cambridge Univ Press},
|
||||
doi={10.1017/S0140525X10000968}
|
||||
}
|
||||
|
||||
@article{dong2014image,
|
||||
title={Image super-resolution using deep convolutional networks},
|
||||
author={Dong, Chao and Loy, Chen Change and He, Kaiming and Tang, Xiaoou},
|
||||
journal={arXiv preprint arXiv:1501.00092},
|
||||
year={2014},
|
||||
url={https://arxiv.org/pdf/1501.00092.pdf}
|
||||
}
|
||||
|
||||
@article{dumoulin2016adversarially,
|
||||
title={Adversarially Learned Inference},
|
||||
author={Dumoulin, Vincent and Belghazi, Ishmael and Poole, Ben and Lamb, Alex and Arjovsky, Martin and Mastropietro, Olivier and Courville, Aaron},
|
||||
journal={arXiv preprint arXiv:1606.00704},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.00704.pdf}
|
||||
}
|
||||
|
||||
@article{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}
|
||||
}
|
||||
|
||||
@article{gauthier2014conditional,
|
||||
title={Conditional generative adversarial nets for convolutional face generation},
|
||||
author={Gauthier, Jon},
|
||||
journal={Class Project for Stanford CS231N: Convolutional Neural Networks for Visual Recognition, Winter semester},
|
||||
volume={2014},
|
||||
year={2014},
|
||||
url={http://www.foldl.me/uploads/papers/tr-cgans.pdf}
|
||||
}
|
||||
|
||||
@article{johnson2016perceptual,
|
||||
title={Perceptual losses for real-time style transfer and super-resolution},
|
||||
author={Johnson, Justin and Alahi, Alexandre and Fei-Fei, Li},
|
||||
journal={arXiv preprint arXiv:1603.08155},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1603.08155.pdf}
|
||||
}
|
||||
|
||||
@article{mordvintsev2015inceptionism,
|
||||
title={Inceptionism: Going deeper into neural networks},
|
||||
author={Mordvintsev, Alexander and Olah, Christopher and Tyka, Mike},
|
||||
journal={Google Research Blog},
|
||||
year={2015},
|
||||
url={https://research.googleblog.com/2015/06/inceptionism-going-deeper-into-neural.html}
|
||||
}
|
||||
|
||||
@misc{mordvintsev2016deepdreaming,
|
||||
title={DeepDreaming with TensorFlow},
|
||||
author={Mordvintsev, Alexander},
|
||||
year={2016},
|
||||
url={https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/tutorials/deepdream/deepdream.ipynb},
|
||||
}
|
||||
|
||||
@article{radford2015unsupervised,
|
||||
title={Unsupervised representation learning with deep convolutional generative adversarial networks},
|
||||
author={Radford, Alec and Metz, Luke and Chintala, Soumith},
|
||||
journal={arXiv preprint arXiv:1511.06434},
|
||||
year={2015},
|
||||
url={https://arxiv.org/pdf/1511.06434.pdf}
|
||||
}
|
||||
|
||||
@inproceedings{salimans2016improved,
|
||||
title={Improved techniques for training gans},
|
||||
author={Salimans, Tim and Goodfellow, Ian and Zaremba, Wojciech and Cheung, Vicki and Radford, Alec and Chen, Xi},
|
||||
booktitle={Advances in Neural Information Processing Systems},
|
||||
pages={2226--2234},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1606.03498.pdf}
|
||||
}
|
||||
|
||||
@article{shi2016deconvolution,
|
||||
title={Is the deconvolution layer the same as a convolutional layer?},
|
||||
author={Shi, Wenzhe and Caballero, Jose and Theis, Lucas and Huszar, Ferenc and Aitken, Andrew and Ledig, Christian and Wang, Zehan},
|
||||
journal={arXiv preprint arXiv:1609.07009},
|
||||
year={2016},
|
||||
url={https://arxiv.org/pdf/1609.07009.pdf}
|
||||
publisher={Cambridge Univ Press}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 255 KiB |
@@ -0,0 +1,81 @@
|
||||
import html from "./components/html";
|
||||
import styles from "./components/styles";
|
||||
import frontMatter from "./components/front-matter";
|
||||
import bibliography from "./components/bibliography";
|
||||
import expandData from "./components/data";
|
||||
import meta from "./components/meta";
|
||||
import banner from "./components/banner";
|
||||
import byline from "./components/byline";
|
||||
import appendix from "./components/appendix";
|
||||
import appendixDistill from "./components/appendix-distill";
|
||||
import citation from "./components/citation";
|
||||
import footnote from "./components/footnote";
|
||||
import DTMath from "./components/dt-math";
|
||||
import markdown from "./components/markdown";
|
||||
import code from "./components/code";
|
||||
import typeset from "./components/typeset";
|
||||
import hoverBox from "./components/hover-box-include";
|
||||
import generateCrossref from "./components/generate-crossref";
|
||||
import header from "./components/header";
|
||||
import footer from "./components/footer";
|
||||
|
||||
function renderImmediately(dom) {
|
||||
html(dom);
|
||||
styles(dom);
|
||||
}
|
||||
|
||||
function renderOnLoad(dom, data) {
|
||||
frontMatter(dom, data);
|
||||
bibliography(dom, data);
|
||||
expandData(dom, data);
|
||||
meta(dom, data);
|
||||
byline(dom, data);
|
||||
appendix(dom, data);
|
||||
markdown(dom, data);
|
||||
DTMath(dom, data);
|
||||
code(dom, data);
|
||||
citation(dom, data);
|
||||
footnote(dom, data);
|
||||
typeset(dom, data);
|
||||
hoverBox(dom, data);
|
||||
}
|
||||
|
||||
// If we are in a browser, render automatically...
|
||||
var browser = new Function("try { return this === window; }catch(e){ return false; }");
|
||||
if (browser) {
|
||||
try {
|
||||
var data = {};
|
||||
renderImmediately(window.document);
|
||||
window.document.addEventListener("DOMContentLoaded", function (event) {
|
||||
renderOnLoad(window.document, data);
|
||||
// Add a banner if we're not on localhost.
|
||||
if (window.location.hostname !== "localhost" && window.location.origin !== "file://") {
|
||||
banner(window.document, data);
|
||||
}
|
||||
generateCrossref(data);
|
||||
// console.log(data);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Window not defined");
|
||||
}
|
||||
}
|
||||
|
||||
// If we are in node...
|
||||
function render(dom, data) {
|
||||
renderImmediately(dom);
|
||||
renderOnLoad(dom, data);
|
||||
// Remove script tag so it doesn't run again in the client
|
||||
let s = dom.querySelector('script[src*="distill.pub/template"]');
|
||||
if (s) { s.parentElement.removeChild(s); };
|
||||
}
|
||||
|
||||
// Distill specific rendering
|
||||
function distillify(dom, data) {
|
||||
header(dom, data);
|
||||
appendixDistill(dom, data);
|
||||
footer(dom, data);
|
||||
}
|
||||
|
||||
export {render as render};
|
||||
export {distillify as distillify};
|
||||
export {generateCrossref as generateCrossref};
|
||||
@@ -1,66 +1,41 @@
|
||||
{
|
||||
"name": "distill-template",
|
||||
"version": "2.2.3",
|
||||
"version": "1.1.1",
|
||||
"description": "Template for creating Distill articles.",
|
||||
"main": "dist/template.v2.js",
|
||||
"bin": {
|
||||
"distill-render": "./bin/render.js"
|
||||
"main": "dist/template.js",
|
||||
"scripts": {
|
||||
"serve": "python3 -m http.server",
|
||||
"start": "rollup -c -w",
|
||||
"build": "rollup -c",
|
||||
"test": "mocha"
|
||||
},
|
||||
"author": "Shan Carter",
|
||||
"homepage": "https://github.com/distillpub/distill-template#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/distillpub/distill-template/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "rollup -c rollup.config.dev.js -w",
|
||||
"serve": "python3 -m http.server --bind 127.0.0.1 8888",
|
||||
"test": "mocha",
|
||||
"lint": "eslint",
|
||||
"build": "rollup -c rollup.config.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"repository": {
|
||||
"url": "git+https://github.com/distillpub/distill-template.git",
|
||||
"type": "git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bugs": {
|
||||
"url": "https://github.com/distillpub/distill-template/issues"
|
||||
},
|
||||
"homepage": "https://github.com/distillpub/distill-template#readme",
|
||||
"dependencies": {
|
||||
"bibtex-parse-js": "^0.0.23",
|
||||
"chai": "^3.5.0",
|
||||
"eslint": "^4.3.0",
|
||||
"eslint-config-google": "^0.9.1",
|
||||
"js-yaml": "^3.7.0",
|
||||
"jsdom": "11.3.0",
|
||||
"jsdom-global": "3.0.2",
|
||||
"marked": "^0.3.6",
|
||||
"mocha": "^3.5.3",
|
||||
"prismjs": "^1.6.0",
|
||||
"rollup": "latest",
|
||||
"rollup-plugin-babili": "^3.1.0",
|
||||
"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-node-resolve": "^2.0.0",
|
||||
"rollup-plugin-serve": "^0.1.0",
|
||||
"rollup-plugin-string": "^2.0.2",
|
||||
"rollup-plugin-uglify": "^1.0.1",
|
||||
"rollup-watch": "^2.5.0",
|
||||
"should": "^13.1.2",
|
||||
"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",
|
||||
"escape-html": "^1.0.3",
|
||||
"intersection-observer": "^0.4.0",
|
||||
"jsdom-wc": "^11.0.0-alpha-1",
|
||||
"katex": "^0.7.1"
|
||||
"js-yaml": "^3.7.0",
|
||||
"jsdom": "^9.10.0",
|
||||
"katex": "^0.7.1",
|
||||
"marked": "^0.3.6",
|
||||
"mocha": "^3.2.0",
|
||||
"mustache": "^2.3.0",
|
||||
"prismjs": "^1.6.0",
|
||||
"rollup": "^0.36.4",
|
||||
"rollup-plugin-buble": "^0.14.0",
|
||||
"rollup-plugin-commonjs": "^7.0.0",
|
||||
"rollup-plugin-node-resolve": "^2.0.0",
|
||||
"rollup-plugin-string": "^2.0.2",
|
||||
"rollup-watch": "^2.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
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';
|
||||
|
||||
// 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' }],
|
||||
};
|
||||
|
||||
const transformsConfig = {
|
||||
input: 'src/transforms.js',
|
||||
output: [{ format: 'umd', name: 'dl', file: 'dist/transforms.v2.js', globals: {fs: 'fs'} }],
|
||||
external: ['fs']
|
||||
};
|
||||
|
||||
const defaultConfig = {
|
||||
sourcemap: true,
|
||||
plugins: [
|
||||
resolve({
|
||||
jsnext: true,
|
||||
browser: true,
|
||||
}),
|
||||
string({
|
||||
include: ['**/*.txt', '**/*.svg', '**/*.html', '**/*.css', '**/*.base64']
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
Object.assign(componentsConfig, defaultConfig);
|
||||
Object.assign(transformsConfig, defaultConfig);
|
||||
|
||||
// transpile transforms so the node render script works…
|
||||
transformsConfig.plugins.push(
|
||||
buble({
|
||||
target: { 'node': 6 }
|
||||
})
|
||||
);
|
||||
|
||||
// uncomment to show dependencies [2/2]
|
||||
// transformsConfig.plugins.push(
|
||||
// rollupGrapher({
|
||||
// dest: '/dev/null',
|
||||
// verbose: true
|
||||
// })
|
||||
// );
|
||||
|
||||
export default [
|
||||
componentsConfig,
|
||||
transformsConfig,
|
||||
];
|
||||
@@ -1,14 +1,36 @@
|
||||
import configs from './rollup.config.dev';
|
||||
import babili from 'rollup-plugin-babili';
|
||||
import buble from 'rollup-plugin-buble';
|
||||
import resolve from 'rollup-plugin-node-resolve';
|
||||
import commonjs from 'rollup-plugin-commonjs';
|
||||
import string from 'rollup-plugin-string';
|
||||
|
||||
const [componentsConfig, transformsConfig] = configs;
|
||||
// const PORT = 8080;
|
||||
// console.log(`open http://localhost:${PORT}/`);
|
||||
|
||||
componentsConfig.plugins.push(babili({
|
||||
comments: false, // means: *remove* comments
|
||||
export default {
|
||||
entry: 'index.js',
|
||||
sourceMap: true,
|
||||
}));
|
||||
|
||||
export default [
|
||||
componentsConfig,
|
||||
transformsConfig,
|
||||
];
|
||||
targets: [
|
||||
{
|
||||
format: 'umd',
|
||||
moduleName: 'dl',
|
||||
dest: `dist/template.v1.js`,
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
resolve({
|
||||
jsnext: true,
|
||||
browser: true,
|
||||
}),
|
||||
string({
|
||||
include: ["**/*.txt", "**/*.svg", "**/*.html", "**/*.css", "**/*.base64"]
|
||||
}),
|
||||
buble({
|
||||
exclude: 'node_modules',
|
||||
target: { chrome: 52, safari: 8, edge: 13, firefox: 48, }
|
||||
}),
|
||||
commonjs(),
|
||||
// uglify(),
|
||||
// liveReload(),
|
||||
// serve({port: PORT}),
|
||||
]
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Gulp with Mustache Templates
|
||||
|
||||
To get started, make sure to run `yarn install` or `npm install` to install dependencies.
|
||||
|
||||
Run `gulp` to build the project. Running `gulp serve` will run a watching server.
|
||||
|
||||
There is very little processing going on, the only thing we've added is support for mustache partials.
|
||||
@@ -1,91 +0,0 @@
|
||||
import { Controller } from './controller';
|
||||
|
||||
/* Transforms */
|
||||
import { makeStyleTag } from './styles/styles';
|
||||
import { Polyfills, polyfills } from './helpers/polyfills';
|
||||
|
||||
/* Components */
|
||||
import { Abstract } from './components/d-abstract';
|
||||
import { Appendix } from './components/d-appendix';
|
||||
import { Article } from './components/d-article';
|
||||
import { Bibliography } from './components/d-bibliography';
|
||||
import { Byline } from './components/d-byline';
|
||||
import { Cite } from './components/d-cite';
|
||||
import { CitationList } from './components/d-citation-list';
|
||||
import { Code } from './components/d-code';
|
||||
import { Footnote } from './components/d-footnote';
|
||||
import { FootnoteList } from './components/d-footnote-list';
|
||||
import { FrontMatter } from './components/d-front-matter';
|
||||
import { Title } from './components/d-title';
|
||||
import { DMath } from './components/d-math';
|
||||
import { References } from './components/d-references';
|
||||
import { TOC } from './components/d-toc';
|
||||
import { Figure } from './components/d-figure';
|
||||
import { Interstitial } from './components/d-interstitial';
|
||||
import { Slider } from './ui/d-slider';
|
||||
|
||||
/* Distill website specific components */
|
||||
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!');
|
||||
}
|
||||
|
||||
/* 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!');
|
||||
} else {
|
||||
window.distillTemplateIsLoading = true;
|
||||
console.info('Runlevel 1: Distill Template has started loading.');
|
||||
}
|
||||
|
||||
/* 2. Add styles if they weren't added during prerendering */
|
||||
makeStyleTag(document);
|
||||
console.info('Runlevel 1: Static Distill styles have been added.');
|
||||
console.info('Runlevel 1->2.');
|
||||
window.distillRunlevel = 2;
|
||||
|
||||
/* 3. Register components */
|
||||
/* Article will register controller which takes control from there */
|
||||
const components = [
|
||||
Abstract, Appendix, Article, Bibliography, Byline, Cite, CitationList, Code,
|
||||
Footnote, FootnoteList, FrontMatter, Title, DMath, References, TOC, Figure,
|
||||
Slider, Interstitial
|
||||
];
|
||||
|
||||
const distillComponents = [
|
||||
DistillHeader, DistillAppendix, DistillFooter,
|
||||
];
|
||||
|
||||
if (window.distillRunlevel < 2) {
|
||||
throw new Error('Insufficient Runlevel for adding custom elements!');
|
||||
}
|
||||
const allComponents = components.concat(distillComponents);
|
||||
for (const component of allComponents) {
|
||||
console.info('Runlevel 2: Registering custom element: ' + component.is);
|
||||
customElements.define(component.is, component);
|
||||
}
|
||||
|
||||
console.info('Runlevel 2: Distill Template finished registering custom elements.');
|
||||
console.info('Runlevel 2->3.');
|
||||
window.distillRunlevel = 3;
|
||||
console.info('Distill Template initialisation complete.');
|
||||
Controller.listeners.DOMContentLoaded();
|
||||
|
||||
};
|
||||
|
||||
window.distillRunlevel = 0;
|
||||
/* 0. Check browser feature support; synchronously polyfill if needed */
|
||||
if (Polyfills.browserSupportsAllFeatures()) {
|
||||
console.info('Runlevel 0: No need for polyfills.');
|
||||
console.info('Runlevel 0->1.');
|
||||
window.distillRunlevel = 1;
|
||||
distillMain();
|
||||
} else {
|
||||
console.info('Runlevel 0: Distill Template is loading polyfills.');
|
||||
Polyfills.load(distillMain);
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import { body } from '../helpers/layout';
|
||||
|
||||
const T = Template('d-abstract', `
|
||||
<style>
|
||||
:host {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.6em;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
::slotted(p) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
grid-column: text-start / middle-end;
|
||||
}
|
||||
${body('d-abstract')}
|
||||
</style>
|
||||
|
||||
<slot></slot>
|
||||
`);
|
||||
|
||||
export class Abstract extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import { body } from '../helpers/layout';
|
||||
|
||||
const T = Template('d-appendix', `
|
||||
<style>
|
||||
|
||||
d-appendix {
|
||||
contain: content;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.7em;
|
||||
margin-top: 60px;
|
||||
margin-bottom: 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
color: rgba(0,0,0,0.5);
|
||||
padding-top: 60px;
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
|
||||
d-appendix h3 {
|
||||
grid-column: page-start / text-start;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0;
|
||||
color: rgba(0,0,0,0.65);
|
||||
}
|
||||
|
||||
d-appendix h3 + * {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
d-appendix ol {
|
||||
padding: 0 0 0 15px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
d-appendix ol {
|
||||
padding: 0 0 0 30px;
|
||||
margin-left: -30px;
|
||||
}
|
||||
}
|
||||
|
||||
d-appendix li {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
d-appendix a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
d-appendix > * {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
d-appendix > d-footnote-list,
|
||||
d-appendix > d-citation-list,
|
||||
d-appendix > distill-appendix {
|
||||
grid-column: screen;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
`, false);
|
||||
|
||||
export class Appendix extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import { Controller } from '../controller';
|
||||
import style from '../styles/d-article.css';
|
||||
|
||||
const isOnlyWhitespace = /^\s*$/;
|
||||
|
||||
export class Article extends HTMLElement {
|
||||
static get is() { return 'd-article'; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
new MutationObserver( (mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
for (const addedNode of mutation.addedNodes) {
|
||||
switch (addedNode.nodeName) {
|
||||
case '#text': { // usually text nodes are only linebreaks.
|
||||
const text = addedNode.nodeValue;
|
||||
if (!isOnlyWhitespace.test(text)) {
|
||||
console.warn('Use of unwrapped text in distill articles is discouraged as it breaks layout! Please wrap any text in a <span> or <p> tag. We found the following text: ' + text);
|
||||
const wrapper = document.createElement('span');
|
||||
wrapper.innerHTML = addedNode.nodeValue;
|
||||
addedNode.parentNode.insertBefore(wrapper, addedNode);
|
||||
addedNode.parentNode.removeChild(addedNode);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}).observe(this, {childList: true});
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
document.onreadystatechange = function () {
|
||||
console.log("onreadystatechange:");
|
||||
console.log(document.readyState);
|
||||
};
|
||||
console.info('Article tag connected, we can now listen to controller events.');
|
||||
console.info('Runlevel 3->4.');
|
||||
for (const [functionName, callback] of Object.entries(Controller.listeners)) {
|
||||
if (typeof callback === 'function') {
|
||||
document.addEventListener(functionName, callback);
|
||||
} else {
|
||||
console.error('Controller listeners need to be functions!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import { parseBibtex } from '../helpers/bibtex';
|
||||
|
||||
export function parseBibliography(element) {
|
||||
const scriptTag = element.firstElementChild;
|
||||
if (scriptTag && scriptTag.tagName === 'SCRIPT') {
|
||||
if (scriptTag.type == 'text/bibtex') {
|
||||
const bibtex = element.firstElementChild.textContent;
|
||||
return parseBibtex(bibtex);
|
||||
} else if (scriptTag.type == 'text/json') {
|
||||
return new Map(JSON.parse(scriptTag.textContent));
|
||||
} else {
|
||||
console.warn('Unsupported bibliography script tag type: ' + scriptTag.type);
|
||||
}
|
||||
} else {
|
||||
console.warn('Bibliography did not have any script tag.');
|
||||
}
|
||||
}
|
||||
|
||||
export class Bibliography extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-bibliography'; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// set up mutation observer
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver( (entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.target.nodeName === 'SCRIPT' || entry.type === 'characterData') {
|
||||
this.parseIfPossible();
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
parseIfPossible() {
|
||||
const scriptTag = this.querySelector('script');
|
||||
if (!scriptTag) return;
|
||||
if (scriptTag.type == 'text/bibtex') {
|
||||
const newBibtex = scriptTag.textContent;
|
||||
if (this.bibtex !== newBibtex) {
|
||||
this.bibtex = newBibtex;
|
||||
const bibliography = parseBibtex(this.bibtex);
|
||||
this.notify(bibliography);
|
||||
}
|
||||
} else if (scriptTag.type == 'text/json') {
|
||||
const bibliography = new Map(JSON.parse(scriptTag.textContent));
|
||||
this.notify(bibliography);
|
||||
} else {
|
||||
console.warn('Unsupported bibliography script tag type: ' + scriptTag.type);
|
||||
}
|
||||
}
|
||||
|
||||
notify(bibliography) {
|
||||
const options = { detail: bibliography, bubbles: true };
|
||||
const event = new CustomEvent('onBibliographyChanged', options);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/* observe 'src' attribute */
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['src'];
|
||||
}
|
||||
|
||||
receivedBibtex(event) {
|
||||
const bibliography = parseBibtex(event.target.response);
|
||||
this.notify(bibliography);
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
var oReq = new XMLHttpRequest();
|
||||
oReq.onload = (e) => this.receivedBibtex(e);
|
||||
oReq.onerror = () => console.warn(`Could not load Bibtex! (tried ${newValue})`);
|
||||
oReq.responseType = 'text';
|
||||
oReq.open('GET', newValue, true);
|
||||
oReq.send();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// import style from '../styles/d-byline.css';
|
||||
|
||||
export function bylineTemplate(frontMatter) {
|
||||
return `
|
||||
<div class="byline grid">
|
||||
<div class="authors-affiliations grid">
|
||||
<h3>Authors</h3>
|
||||
<h3>Affiliations</h3>
|
||||
${frontMatter.authors.map(author => `
|
||||
<p class="author">
|
||||
${author.personalURL ? `
|
||||
<a class="name" href="${author.personalURL}">${author.name}</a>` : `
|
||||
<div class="name">${author.name}</div>`}
|
||||
</p>
|
||||
<p class="affiliation">
|
||||
${author.affiliationURL ? `
|
||||
<a class="affiliation" href="${author.affiliationURL}">${author.affiliation}</a>` : `
|
||||
<div class="affiliation">${author.affiliation}</div>`}
|
||||
</p>
|
||||
`).join('')}
|
||||
</div>
|
||||
<div>
|
||||
<h3>Published</h3>
|
||||
${frontMatter.publishedDate ? `
|
||||
<p>${frontMatter.publishedMonth} ${frontMatter.publishedDay}, ${frontMatter.publishedYear}</p> ` : `
|
||||
<p><em>Not published yet.</em></p>`}
|
||||
</div>
|
||||
<div>
|
||||
<h3>DOI</h3>
|
||||
${frontMatter.doi ? `
|
||||
<p><a href="https://doi.org/${frontMatter.doi}">${frontMatter.doi}</a></p>` : `
|
||||
<p><em>No DOI yet.</em></p>`}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
export class Byline extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-byline'; }
|
||||
|
||||
set frontMatter(frontMatter) {
|
||||
this.innerHTML = bylineTemplate(frontMatter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { bibliography_cite } from '../helpers/citation';
|
||||
|
||||
const styles = `
|
||||
d-citation-list {
|
||||
contain: content;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
d-citation-list .references {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
d-citation-list .references .title {
|
||||
font-weight: 500;
|
||||
}
|
||||
`;
|
||||
|
||||
export function renderCitationList(element, entries, dom=document) {
|
||||
if (entries.size > 0) {
|
||||
element.style.display = '';
|
||||
let list = element.querySelector('.references');
|
||||
if (list) {
|
||||
list.innerHTML = '';
|
||||
} else {
|
||||
const stylesTag = dom.createElement('style');
|
||||
stylesTag.innerHTML = styles;
|
||||
element.appendChild(stylesTag);
|
||||
|
||||
const heading = dom.createElement('h3');
|
||||
heading.id = 'references';
|
||||
heading.textContent = 'References';
|
||||
element.appendChild(heading);
|
||||
|
||||
list = dom.createElement('ol');
|
||||
list.id = 'references-list';
|
||||
list.className = 'references';
|
||||
element.appendChild(list);
|
||||
}
|
||||
|
||||
for (const [key, entry] of entries) {
|
||||
const listItem = dom.createElement('li');
|
||||
listItem.id = key;
|
||||
listItem.innerHTML = bibliography_cite(entry);
|
||||
list.appendChild(listItem);
|
||||
}
|
||||
} else {
|
||||
element.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
export class CitationList extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-citation-list'; }
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.hasAttribute('distill-prerendered')) {
|
||||
this.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
set citations(citations) {
|
||||
renderCitationList(this, citations);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import { hover_cite, bibliography_cite } from '../helpers/citation';
|
||||
import { HoverBox } from '../helpers/hover-box';
|
||||
|
||||
const T = Template('d-cite', `
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.citation {
|
||||
display: inline-block;
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
}
|
||||
|
||||
.citation-number {
|
||||
cursor: default;
|
||||
white-space: nowrap;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Roboto", Helvetica, sans-serif;
|
||||
font-size: 75%;
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
display: inline-block;
|
||||
line-height: 1.1em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
figcaption .citation-number {
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
top: -2px;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
z-index: 10000;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.dt-hover-box {
|
||||
margin: 0 auto;
|
||||
width: 400px;
|
||||
max-width: 700px;
|
||||
background-color: #FFF;
|
||||
opacity: 0.95;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
padding: 8px 16px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<div id="hover-box" class="dt-hover-box"></div>
|
||||
</div>
|
||||
|
||||
<div id="citation-" class="citation"><slot></slot><span class="citation-number"></span></div>
|
||||
`);
|
||||
|
||||
export class Cite extends T(HTMLElement) {
|
||||
|
||||
/* Lifecycle */
|
||||
|
||||
// constructor() {
|
||||
// super();
|
||||
// // Cite.currentId += 1;
|
||||
// // this.citeId = Cite.currentId;
|
||||
// }
|
||||
|
||||
connectedCallback() {
|
||||
// this.notify();
|
||||
|
||||
this.hoverDiv = this.root.querySelector('.dt-hover-box');
|
||||
this.outerSpan = this.root.querySelector('#citation-');
|
||||
this.innerSpan = this.root.querySelector('.citation-number');
|
||||
// this.outerSpan.id = `citation-${this.citeId}`;
|
||||
// this.hoverDiv.id = `dt-cite-hover-box-${this.citeId}`;
|
||||
// console.log(this, this.hoverDiv, this.outerSpan, this.innerSpan);
|
||||
this.hoverbox = new HoverBox(this.hoverDiv, this.outerSpan);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
const options = { detail: [this, this.keys], bubbles: true };
|
||||
const event = new CustomEvent('onCiteKeyRemoved', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/* Observed Attributes */
|
||||
|
||||
// renderCitationNumbers(citations) {
|
||||
// const numbers = this._keys.map( (key) => {
|
||||
// const index = citations.indexOf(key);
|
||||
// return index == -1 ? '?' : index + 1 + '';
|
||||
// });
|
||||
// const text = "[" + numbers.join(", ") + "]";
|
||||
// this.innerSpan.textContent = text;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
/* observe 'key' attribute */
|
||||
|
||||
static get observedAttributes() {
|
||||
return ['key'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
const eventName = oldValue ? 'onCiteKeyChanged' : 'onCiteKeyCreated';
|
||||
const keys = newValue.split(',');
|
||||
const options = { detail: [this, keys], bubbles: true };
|
||||
const event = new CustomEvent(eventName, options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
set key(value) {
|
||||
this.setAttribute('key', value);
|
||||
}
|
||||
|
||||
get key() {
|
||||
return this.getAttribute('key');
|
||||
}
|
||||
|
||||
get keys() {
|
||||
return this.getAttribute('key').split(',');
|
||||
}
|
||||
|
||||
/* Setters & Rendering */
|
||||
|
||||
set numbers(numbers) {
|
||||
const numberStrings = numbers.map( index => {
|
||||
return index == -1 ? '?' : index + 1 + '';
|
||||
});
|
||||
const textContent = '[' + numberStrings.join(', ') + ']';
|
||||
const innerSpan = this.root.querySelector('.citation-number');
|
||||
innerSpan.textContent = textContent;
|
||||
}
|
||||
|
||||
set entries(entries) {
|
||||
const div = this.root.querySelector('#hover-box');
|
||||
div.innerHTML = entries.map(hover_cite).join('<br><br>');
|
||||
}
|
||||
|
||||
// renderContent() {
|
||||
// const bibliography = document.querySelector('d-bibliography');
|
||||
// if (bibliography && bibliography.finishedLoading) {
|
||||
// customElements.whenDefined('d-bibliography').then( () => {
|
||||
// const keys = this.key.split(",");
|
||||
//
|
||||
// // set up hidden hover box
|
||||
// const div = this.root.querySelector('.dt-hover-box');
|
||||
// div.innerHTML = keys.map( (key) => {
|
||||
// return bibliography.getEntry(key);
|
||||
// }).map(hover_cite).join('<br><br>');
|
||||
// div.id ='dt-cite-hover-box-' + this.citeId;
|
||||
//
|
||||
// // set up visible citation marker
|
||||
// const outerSpan = this.root.querySelector('#citation-');
|
||||
// outerSpan.id = `citation-${this.citeId}`;
|
||||
// // outerSpan.setAttribute('data-hover', dataHoverString); // directly tell HoverBox instead?
|
||||
// const innerSpan = this.root.querySelector('.citation-number');
|
||||
// innerSpan.textContent = inline_cite_short(keys, bibliography);
|
||||
//
|
||||
// HoverBox.get_box(div).bind(outerSpan);
|
||||
// });
|
||||
// } else {
|
||||
// console.error(`You used a d-cite tag (${key}) without including a d-bibliography tag in your article. We can't lookup your citation this way.`)
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import Prism from 'prismjs';
|
||||
import 'prismjs/components/prism-python';
|
||||
import 'prismjs/components/prism-clike';
|
||||
import 'prismjs/components/prism-python';
|
||||
import 'prismjs/components/prism-clike';
|
||||
import 'prismjs/components/prism-lua';
|
||||
import 'prismjs/components/prism-bash';
|
||||
import 'prismjs/components/prism-go';
|
||||
import 'prismjs/components/prism-markdown';
|
||||
import 'prismjs/components/prism-julia';
|
||||
import css from 'prismjs/themes/prism.css';
|
||||
|
||||
import { Template } from '../mixins/template.js';
|
||||
import { Mutating } from '../mixins/mutating.js';
|
||||
|
||||
const T = Template('d-code', `
|
||||
<style>
|
||||
|
||||
code {
|
||||
white-space: nowrap;
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
border-radius: 2px;
|
||||
padding: 4px 7px;
|
||||
font-size: 15px;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
pre code {
|
||||
display: block;
|
||||
border-left: 2px solid rgba(0, 0, 0, .1);
|
||||
padding: 0 0 0 36px;
|
||||
}
|
||||
|
||||
${css}
|
||||
</style>
|
||||
|
||||
<code id="code-container"></code>
|
||||
|
||||
`);
|
||||
|
||||
export class Code extends Mutating(T(HTMLElement)) {
|
||||
|
||||
renderContent() {
|
||||
|
||||
// check if language can be highlighted
|
||||
this.languageName = this.getAttribute('language');
|
||||
if (!this.languageName) {
|
||||
console.warn('You need to provide a language attribute to your <d-code> block to let us know how to highlight your code; e.g.:\n <d-code language="python">zeros = np.zeros(shape)</d-code>.');
|
||||
return;
|
||||
}
|
||||
const language = Prism.languages[this.languageName];
|
||||
if (language == undefined) {
|
||||
console.warn(`Distill does not yet support highlighting your code block in "${this.languageName}'.`);
|
||||
return;
|
||||
}
|
||||
|
||||
let content = this.textContent;
|
||||
const codeTag = this.shadowRoot.querySelector('#code-container');
|
||||
|
||||
if (this.hasAttribute('block')) {
|
||||
// normalize the tab indents
|
||||
content = content.replace(/\n/, '');
|
||||
const tabs = content.match(/\s*/);
|
||||
content = content.replace(new RegExp('\n' + tabs, 'g'), '\n');
|
||||
content = content.trim();
|
||||
// wrap code block in pre tag if needed
|
||||
if (codeTag.parentNode instanceof ShadowRoot) {
|
||||
const preTag = document.createElement('pre');
|
||||
this.shadowRoot.removeChild(codeTag);
|
||||
preTag.appendChild(codeTag);
|
||||
this.shadowRoot.appendChild(preTag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
codeTag.className = `language-${this.languageName}`;
|
||||
codeTag.innerHTML = Prism.highlight(content, language);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
// Figure
|
||||
//
|
||||
// d-figure provides a state-machine of visibility events:
|
||||
//
|
||||
// scroll out of view
|
||||
// +----------------+
|
||||
// *do work here* | |
|
||||
// +----------------+ +-+---------+ +-v---------+
|
||||
// | ready +----> onscreen | | offscreen |
|
||||
// +----------------+ +---------^-+ +---------+-+
|
||||
// | |
|
||||
// +----------------+
|
||||
// scroll into view
|
||||
//
|
||||
|
||||
export class Figure extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-figure'; }
|
||||
|
||||
static get readyQueue() {
|
||||
if (!Figure._readyQueue) {
|
||||
Figure._readyQueue = [];
|
||||
}
|
||||
return Figure._readyQueue;
|
||||
}
|
||||
|
||||
static addToReadyQueue(figure) {
|
||||
if (Figure.readyQueue.indexOf(figure) === -1) {
|
||||
Figure.readyQueue.push(figure);
|
||||
Figure.runReadyQueue();
|
||||
}
|
||||
}
|
||||
|
||||
static runReadyQueue() {
|
||||
// console.log("Checking to run readyQueue, length: " + Figure.readyQueue.length + ", scrolling: " + Figure.isScrolling);
|
||||
// if (Figure.isScrolling) return;
|
||||
// console.log("Running ready Queue");
|
||||
const figure = Figure.readyQueue
|
||||
.sort((a,b) => a._seenOnScreen - b._seenOnScreen )
|
||||
.filter((figure) => !figure._ready)
|
||||
.pop();
|
||||
if (figure) {
|
||||
figure.ready();
|
||||
requestAnimationFrame(Figure.runReadyQueue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// debugger
|
||||
this._ready = false;
|
||||
this._onscreen = false;
|
||||
this._offscreen = true;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.loadsWhileScrolling = this.hasAttribute('loadsWhileScrolling');
|
||||
Figure.marginObserver.observe(this);
|
||||
Figure.directObserver.observe(this);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
Figure.marginObserver.unobserve(this);
|
||||
Figure.directObserver.unobserve(this);
|
||||
}
|
||||
|
||||
// We use two separate observers:
|
||||
// One with an extra 1000px margin to warn if the viewpoint gets close,
|
||||
// And one for the actual on/off screen events
|
||||
|
||||
static get marginObserver() {
|
||||
if (!Figure._marginObserver) {
|
||||
// if (!('IntersectionObserver' in window)) {
|
||||
// throw new Error('no interscetionobbserver!');
|
||||
// }
|
||||
const viewportHeight = window.innerHeight;
|
||||
const margin = Math.floor(2 * viewportHeight);
|
||||
const options = {rootMargin: margin + 'px 0px ' + margin + 'px 0px', threshold: 0.01};
|
||||
const callback = Figure.didObserveMarginIntersection;
|
||||
const observer = new IntersectionObserver(callback, options);
|
||||
Figure._marginObserver = observer;
|
||||
}
|
||||
return Figure._marginObserver;
|
||||
}
|
||||
|
||||
static didObserveMarginIntersection(entries) {
|
||||
for (const entry of entries) {
|
||||
const figure = entry.target;
|
||||
if (entry.isIntersecting && !figure._ready) {
|
||||
Figure.addToReadyQueue(figure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get directObserver() {
|
||||
if (!Figure._directObserver) {
|
||||
Figure._directObserver = new IntersectionObserver(
|
||||
Figure.didObserveDirectIntersection, {
|
||||
rootMargin: '0px', threshold: [0, 1.0],
|
||||
}
|
||||
);
|
||||
}
|
||||
return Figure._directObserver;
|
||||
}
|
||||
|
||||
static didObserveDirectIntersection(entries) {
|
||||
for (const entry of entries) {
|
||||
const figure = entry.target;
|
||||
if (entry.isIntersecting) {
|
||||
figure._seenOnScreen = new Date();
|
||||
// if (!figure._ready) { figure.ready(); }
|
||||
if (figure._offscreen) { figure.onscreen(); }
|
||||
} else {
|
||||
if (figure._onscreen) { figure.offscreen(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify listeners that registered late, too:
|
||||
|
||||
addEventListener(eventName, callback) {
|
||||
super.addEventListener(eventName, callback);
|
||||
// if we had already dispatched something while presumingly no one was listening, we do so again
|
||||
// debugger
|
||||
if (eventName === 'ready') {
|
||||
if (Figure.readyQueue.indexOf(this) !== -1) {
|
||||
this._ready = false;
|
||||
Figure.runReadyQueue();
|
||||
}
|
||||
}
|
||||
if (eventName === 'onscreen') {
|
||||
this.onscreen();
|
||||
}
|
||||
}
|
||||
|
||||
// Custom Events
|
||||
|
||||
ready() {
|
||||
// debugger
|
||||
this._ready = true;
|
||||
Figure.marginObserver.unobserve(this);
|
||||
const event = new CustomEvent('ready');
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
onscreen() {
|
||||
this._onscreen = true;
|
||||
this._offscreen = false;
|
||||
const event = new CustomEvent('onscreen');
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
offscreen() {
|
||||
this._onscreen = false;
|
||||
this._offscreen = true;
|
||||
const event = new CustomEvent('offscreen');
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
|
||||
Figure.isScrolling = false;
|
||||
let timeout;
|
||||
const resetTimer = () => {
|
||||
Figure.isScrolling = true;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
Figure.isScrolling = false;
|
||||
Figure.runReadyQueue();
|
||||
}, 500);
|
||||
};
|
||||
window.addEventListener('scroll', resetTimer, true);
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
|
||||
const T = Template('d-footnote-list', `
|
||||
<style>
|
||||
|
||||
d-footnote-list {
|
||||
contain: content;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
d-footnote-list > * {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
d-footnote-list a.footnote-backlink {
|
||||
color: rgba(0,0,0,0.3);
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<h3>Footnotes</h3>
|
||||
<ol></ol>
|
||||
`, false);
|
||||
|
||||
export class FootnoteList extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.list = this.root.querySelector('ol');
|
||||
// footnotes list is initially hidden
|
||||
this.root.style.display = 'none';
|
||||
// look through document and register existing footnotes
|
||||
// Store.subscribeTo('footnotes', (footnote) => {
|
||||
// this.renderFootnote(footnote);
|
||||
// });
|
||||
}
|
||||
|
||||
// TODO: could optimize this to accept individual footnotes?
|
||||
set footnotes(footnotes) {
|
||||
this.list.innerHTML = '';
|
||||
if (footnotes.length) {
|
||||
// ensure footnote list is visible
|
||||
this.root.style.display = '';
|
||||
|
||||
for (const footnote of footnotes) {
|
||||
// construct and append list item to show footnote
|
||||
const listItem = document.createElement('li');
|
||||
listItem.id = footnote.id + '-listing';
|
||||
listItem.innerHTML = footnote.innerHTML;
|
||||
|
||||
const backlink = document.createElement('a');
|
||||
backlink.setAttribute('class', 'footnote-backlink');
|
||||
backlink.textContent = '[↩]';
|
||||
backlink.href = '#' + footnote.id;
|
||||
|
||||
listItem.appendChild(backlink);
|
||||
this.list.appendChild(listItem);
|
||||
}
|
||||
} else {
|
||||
// ensure footnote list is invisible
|
||||
this.root.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import { Template } from '../mixins/template.js';
|
||||
import { HoverBox } from '../helpers/hover-box';
|
||||
|
||||
const T = Template('d-footnote', `
|
||||
<style>
|
||||
|
||||
d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:host {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
sup {
|
||||
line-height: 1em;
|
||||
font-size: 0.75em;
|
||||
position: relative;
|
||||
top: -.5em;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
span {
|
||||
color: hsla(206, 90%, 20%, 0.7);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.dt-hover-box {
|
||||
margin: 0 auto;
|
||||
width: 400px;
|
||||
max-width: 700px;
|
||||
background-color: #FFF;
|
||||
opacity: 0.95;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
padding: 8px 16px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<div id="hover-box" class="dt-hover-box">
|
||||
<slot id="slot"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<sup>
|
||||
<span id="fn-" data-hover-ref=""></span>
|
||||
</sup>
|
||||
|
||||
`);
|
||||
|
||||
export class Footnote extends T(HTMLElement) {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver(this.notify);
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
notify() {
|
||||
const options = { detail: this, bubbles: true };
|
||||
const event = new CustomEvent('onFootnoteChanged', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
// listen and notify about changes to slotted content
|
||||
// const slot = this.shadowRoot.querySelector('#slot');
|
||||
// console.warn(slot.textContent);
|
||||
// slot.addEventListener('slotchange', this.notify);
|
||||
|
||||
// create numeric ID
|
||||
Footnote.currentFootnoteId += 1;
|
||||
const IdString = Footnote.currentFootnoteId.toString();
|
||||
this.root.host.id = 'd-footnote-' + IdString;
|
||||
|
||||
// set up hidden hover box
|
||||
const div = this.root.querySelector('.dt-hover-box');
|
||||
div.id = 'dt-fn-hover-box-' + IdString;
|
||||
|
||||
// set up visible footnote marker
|
||||
const span = this.root.querySelector('#fn-');
|
||||
span.setAttribute('id', 'fn-' + IdString);
|
||||
span.setAttribute('data-hover-ref', div.id);
|
||||
span.textContent = IdString;
|
||||
|
||||
this.hoverbox = new HoverBox(div, span);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Footnote.currentFootnoteId = 0;
|
||||
@@ -1,42 +0,0 @@
|
||||
export function parseFrontmatter(element) {
|
||||
const scriptTag = element.querySelector('script');
|
||||
if (scriptTag) {
|
||||
const type = scriptTag.getAttribute('type');
|
||||
if (type.split('/')[1] == 'json') {
|
||||
const content = scriptTag.textContent;
|
||||
return JSON.parse(content);
|
||||
} else {
|
||||
console.error('Distill only supports JSON frontmatter tags anymore; no more YAML.');
|
||||
}
|
||||
} else {
|
||||
console.error('You added a frontmatter tag but did not provide a script tag with front matter data in it. Please take a look at our templates.');
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
export class FrontMatter extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-front-matter'; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver( (entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.target.nodeName === 'SCRIPT' || entry.type === 'characterData') {
|
||||
const data = parseFrontmatter(this);
|
||||
this.notify(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
notify(data) {
|
||||
const options = { detail: data, bubbles: true };
|
||||
const event = new CustomEvent('onFrontMatterChanged', options);
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
|
||||
// This overlay is not secure.
|
||||
// It is only meant as a social deterrent.
|
||||
|
||||
const T = Template('d-interstitial', `
|
||||
<style>
|
||||
|
||||
.overlay {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: white;
|
||||
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
z-index: 2147483647 /* MaxInt32 */
|
||||
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 420px;
|
||||
padding: 2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-decoration: underline;
|
||||
text-decoration-color: hsl(0,100%,40%);
|
||||
-webkit-text-decoration-color: hsl(0,100%,40%);
|
||||
margin-bottom: 1em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
input[type="password"] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
-webkit-border-radius: none;
|
||||
-moz-border-radius: none;
|
||||
-ms-border-radius: none;
|
||||
-o-border-radius: none;
|
||||
border-radius: none;
|
||||
outline: none;
|
||||
|
||||
font-size: 18px;
|
||||
background: none;
|
||||
width: 25%;
|
||||
padding: 10px;
|
||||
border: none;
|
||||
border-bottom: solid 2px #999;
|
||||
transition: border .3s;
|
||||
}
|
||||
|
||||
input[type="password"]:focus {
|
||||
border-bottom: solid 2px #333;
|
||||
}
|
||||
|
||||
input[type="password"].wrong {
|
||||
border-bottom: solid 2px hsl(0,100%,40%);
|
||||
}
|
||||
|
||||
p small {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: relative;
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
|
||||
.logo svg {
|
||||
width: 36px;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.logo svg path {
|
||||
fill: none;
|
||||
stroke: black;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="overlay">
|
||||
<div class="container">
|
||||
<h1>This article is in review.</h1>
|
||||
<p>Do not share this URL or the contents of this article. Thank you!</p>
|
||||
<input id="interstitial-password-input" type="password" name="password" autofocus/>
|
||||
<p><small>Enter the password we shared with you as part of the review process to view the article.</small></p>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
export class Interstitial extends T(HTMLElement) {
|
||||
|
||||
connectedCallback() {
|
||||
const passwordInput = this.root.querySelector('#interstitial-password-input');
|
||||
passwordInput.oninput = (event) => this.passwordChanged(event);
|
||||
if (typeof(Storage) !== 'undefined') {
|
||||
if (localStorage.getItem('distill-interstitial-password-correct') === 'true') {
|
||||
console.log('Loaded that correct password was entered before; skipping interstitial.');
|
||||
this.parentElement.removeChild(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
passwordChanged(event) {
|
||||
const entered = event.target.value;
|
||||
if (entered === this.password) {
|
||||
console.log('Correct password entered.');
|
||||
this.parentElement.removeChild(this);
|
||||
if (typeof(Storage) !== 'undefined') {
|
||||
console.log('Saved that correct password was entered.');
|
||||
localStorage.setItem('distill-interstitial-password-correct', 'true');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*global katex */
|
||||
import { Mutating } from '../mixins/mutating.js';
|
||||
import { Template } from '../mixins/template.js';
|
||||
|
||||
import style from '../styles/d-math.css';
|
||||
|
||||
// attaches renderMathInElement to window
|
||||
import { renderMathInElement } from '../helpers/katex-auto-render';
|
||||
|
||||
export const katexJSURL = 'https://distill.pub/third-party/katex/katex.min.js';
|
||||
export const katexCSSTag = '<link rel="stylesheet" href="https://distill.pub/third-party/katex/katex.min.css" crossorigin="anonymous">';
|
||||
|
||||
const T = Template('d-math', `
|
||||
${katexCSSTag}
|
||||
<style>
|
||||
|
||||
:host {
|
||||
display: inline-block;
|
||||
contain: content;
|
||||
}
|
||||
|
||||
:host([block]) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
${style}
|
||||
</style>
|
||||
<span id='katex-container'></span>
|
||||
`);
|
||||
|
||||
// DMath, not Math, because that would conflict with the JS built-in
|
||||
export class DMath extends Mutating(T(HTMLElement)) {
|
||||
|
||||
static set katexOptions(options) {
|
||||
DMath._katexOptions = options;
|
||||
if (DMath.katexOptions.delimiters) {
|
||||
if (!DMath.katexAdded) {
|
||||
DMath.addKatex();
|
||||
} else {
|
||||
DMath.katexLoadedCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get katexOptions() {
|
||||
if (!DMath._katexOptions) {
|
||||
DMath._katexOptions = {
|
||||
delimiters: [ { 'left':'$$', 'right':'$$', 'display': false } ]
|
||||
};
|
||||
}
|
||||
return DMath._katexOptions;
|
||||
}
|
||||
|
||||
static katexLoadedCallback() {
|
||||
// render all d-math tags
|
||||
const mathTags = document.querySelectorAll('d-math');
|
||||
for (const mathTag of mathTags) {
|
||||
mathTag.renderContent();
|
||||
}
|
||||
// transform inline delimited math to d-math tags
|
||||
if (DMath.katexOptions.delimiters) {
|
||||
const article = document.querySelector('d-article');
|
||||
renderMathInElement(article, DMath.katexOptions);
|
||||
}
|
||||
}
|
||||
|
||||
static addKatex() {
|
||||
// css tag can use this convenience function
|
||||
document.head.insertAdjacentHTML('beforeend', katexCSSTag);
|
||||
// script tag has to be created to work properly
|
||||
const scriptTag = document.createElement('script');
|
||||
scriptTag.src = katexJSURL;
|
||||
scriptTag.async = true;
|
||||
scriptTag.onload = DMath.katexLoadedCallback;
|
||||
scriptTag.crossorigin = 'anonymous';
|
||||
document.head.appendChild(scriptTag);
|
||||
|
||||
DMath.katexAdded = true;
|
||||
}
|
||||
|
||||
get options() {
|
||||
const localOptions = { displayMode: this.hasAttribute('block') };
|
||||
return Object.assign(localOptions, DMath.katexOptions);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (!DMath.katexAdded) {
|
||||
DMath.addKatex();
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
if (typeof katex !== 'undefined') {
|
||||
const container = this.root.querySelector('#katex-container');
|
||||
katex.render(this.textContent, container, this.options);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DMath.katexAdded = false;
|
||||
DMath.inlineMathRendered = false;
|
||||
window.DMath = DMath; // TODO: check if this can be removed, or if we should expose a distill global
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
|
||||
const T = Template('d-references', `
|
||||
<style>
|
||||
d-references {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
`, false);
|
||||
|
||||
export class References extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
|
||||
const T = Template('d-title', `
|
||||
<style>
|
||||
|
||||
:host {
|
||||
padding: 4rem 0 1.5rem;
|
||||
contain: content;
|
||||
display: block;
|
||||
}
|
||||
|
||||
::slotted(h1) {
|
||||
grid-column: text;
|
||||
font-size: 60px;
|
||||
font-weight: 600;
|
||||
line-height: 1.05em;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
::slotted(p) {
|
||||
font-weight: 300;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.2em;
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 0px;
|
||||
font-size: 12px;
|
||||
color: #009688;
|
||||
opacity: 0.8;
|
||||
grid-column: kicker;
|
||||
}
|
||||
.status span {
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
padding: 6px 0;
|
||||
border-bottom: 1px solid #80cbc4;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- <div class="status"><span>✓ Peer Reviewed</span></div> -->
|
||||
<slot></slot>
|
||||
`);
|
||||
|
||||
export class Title extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
export class TOC extends HTMLElement {
|
||||
|
||||
static get is() { return 'd-toc'; }
|
||||
|
||||
connectedCallback() {
|
||||
if (!this.getAttribute('prerendered')) {
|
||||
window.onload = () => {
|
||||
const article = document.querySelector('d-article');
|
||||
const headings = article.querySelectorAll('h2, h3');
|
||||
renderTOC(this, headings);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function renderTOC(element, headings) {
|
||||
|
||||
let ToC =`
|
||||
<style>
|
||||
|
||||
d-toc {
|
||||
contain: content;
|
||||
display: block;
|
||||
}
|
||||
|
||||
d-toc ul {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
d-toc ul > ul {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
d-toc a {
|
||||
border-bottom: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<nav role="navigation" class="table-of-contents"></nav>
|
||||
<h2>Table of contents</h2>
|
||||
<ul>`;
|
||||
|
||||
for (const el of headings) {
|
||||
// should element be included in TOC?
|
||||
const isInTitle = el.parentElement.tagName == 'D-TITLE';
|
||||
const isException = el.getAttribute('no-toc');
|
||||
if (isInTitle || isException) continue;
|
||||
// create TOC entry
|
||||
const title = el.textContent;
|
||||
const link = '#' + el.getAttribute('id');
|
||||
|
||||
let newLine = '<li>' + '<a href="' + link + '">' + title + '</a>' + '</li>';
|
||||
if (el.tagName == 'H3') {
|
||||
newLine = '<ul>' + newLine + '</ul>';
|
||||
} else {
|
||||
newLine += '<br>';
|
||||
}
|
||||
ToC += newLine;
|
||||
|
||||
}
|
||||
|
||||
ToC += '</ul></nav>';
|
||||
element.innerHTML = ToC;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
import { FrontMatter, mergeFromYMLFrontmatter } from './front-matter';
|
||||
import { DMath } from './components/d-math';
|
||||
import { collect_citations } from './helpers/citation.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: [],
|
||||
},
|
||||
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));
|
||||
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));
|
||||
return;
|
||||
}
|
||||
|
||||
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
|
||||
citeTag.numbers = numbers;
|
||||
const entries = keys.map( key => frontMatter.bibliography.get(key) );
|
||||
citeTag.entries = entries;
|
||||
},
|
||||
|
||||
onCiteKeyChanged(event) {
|
||||
// const [citeTag, keys] = event.detail;
|
||||
|
||||
// update citations
|
||||
frontMatter.citations = collect_citations();
|
||||
frontMatter.citationsCollected = true;
|
||||
for (const waitingCallback of Controller.waitingOn.citations.slice()) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
// update bibliography
|
||||
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');
|
||||
for (const citeTag of citeTags) {
|
||||
const keys = citeTag.keys;
|
||||
const numbers = keys.map( key => frontMatter.citations.indexOf(key) );
|
||||
citeTag.numbers = numbers;
|
||||
const entries = keys.map( key => frontMatter.bibliography.get(key) );
|
||||
citeTag.entries = entries;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
onCiteKeyRemoved(event) {
|
||||
Controller.listeners.onCiteKeyChanged(event);
|
||||
},
|
||||
|
||||
onBibliographyChanged(event) {
|
||||
console.info('BibliographyChanged');
|
||||
const citationListTag = document.querySelector('d-citation-list');
|
||||
|
||||
const bibliography = event.detail;
|
||||
|
||||
frontMatter.bibliography = bibliography;
|
||||
frontMatter.bibliographyParsed = true;
|
||||
for (const waitingCallback of Controller.waitingOn.bibliography.slice()) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
// ensure we have citations
|
||||
if (!frontMatter.citationsCollected) {
|
||||
Controller.waitingOn.citations.push( function() {
|
||||
Controller.listeners.onBibliographyChanged({target: event.target, detail: event.detail});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (citationListTag.hasAttribute('distill-prerendered')) {
|
||||
console.info('Citation list was prerendered; not updating it.');
|
||||
} else {
|
||||
const entries = new Map(frontMatter.citations.map( citationKey => {
|
||||
return [citationKey, frontMatter.bibliography.get(citationKey)];
|
||||
}));
|
||||
citationListTag.citations = entries;
|
||||
}
|
||||
},
|
||||
|
||||
onFootnoteChanged() {
|
||||
// const footnote = event.detail;
|
||||
//TODO: optimize to only update current footnote
|
||||
const footnotesList = document.querySelector('d-footnote-list');
|
||||
if (footnotesList) {
|
||||
const footnotes = document.querySelectorAll('d-footnote');
|
||||
footnotesList.footnotes = footnotes;
|
||||
}
|
||||
},
|
||||
|
||||
onFrontMatterChanged(event) {
|
||||
const data = event.detail;
|
||||
mergeFromYMLFrontmatter(frontMatter, data);
|
||||
|
||||
const interstitial = document.querySelector('d-interstitial');
|
||||
if (interstitial) {
|
||||
interstitial.password = frontMatter.password;
|
||||
}
|
||||
|
||||
const prerendered = document.body.hasAttribute('distill-prerendered');
|
||||
if (!prerendered) {
|
||||
optionalComponents(document, frontMatter);
|
||||
|
||||
const appendix = document.querySelector('distill-appendix');
|
||||
if (appendix) {
|
||||
appendix.frontMatter = frontMatter;
|
||||
}
|
||||
|
||||
const byline = document.querySelector('d-byline');
|
||||
if (byline) {
|
||||
byline.frontMatter = frontMatter;
|
||||
}
|
||||
|
||||
if (data.katex) {
|
||||
DMath.katexOptions = data.katex;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
DOMContentLoaded() {
|
||||
if (Controller.loaded || ['interactive', 'complete'].indexOf(document.readyState) === -1) {
|
||||
return;
|
||||
} else {
|
||||
Controller.loaded = true;
|
||||
console.log('Controller running DOMContentLoaded')
|
||||
}
|
||||
|
||||
const frontMatterTag = document.querySelector('d-front-matter');
|
||||
const data = parseFrontmatter(frontMatterTag);
|
||||
Controller.listeners.onFrontMatterChanged({detail: data});
|
||||
|
||||
// console.debug('Resolving "citations" dependency due to initial DOM load.');
|
||||
frontMatter.citations = collect_citations();
|
||||
frontMatter.citationsCollected = true;
|
||||
for (const waitingCallback of Controller.waitingOn.citations.slice()) {
|
||||
waitingCallback();
|
||||
}
|
||||
|
||||
if (frontMatter.bibliographyParsed) {
|
||||
for (const waitingCallback of Controller.waitingOn.bibliography.slice()) {
|
||||
waitingCallback();
|
||||
}
|
||||
}
|
||||
|
||||
const footnotesList = document.querySelector('d-footnote-list');
|
||||
if (footnotesList) {
|
||||
const footnotes = document.querySelectorAll('d-footnote');
|
||||
footnotesList.footnotes = footnotes;
|
||||
}
|
||||
}
|
||||
|
||||
}, // listeners
|
||||
|
||||
}; // Controller
|
||||
@@ -1,76 +0,0 @@
|
||||
import { serializeFrontmatterToBibtex } from '../helpers/bibtex';
|
||||
|
||||
const styles = `
|
||||
<style>
|
||||
distill-appendix {
|
||||
contain: content;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
distill-appendix .citation {
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
border-left: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-left: 18px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
padding: 10px 18px;
|
||||
border-radius: 3px;
|
||||
color: rgba(150, 150, 150, 1);
|
||||
overflow: hidden;
|
||||
margin-top: -12px;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
distill-appendix > * {
|
||||
grid-column: text;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
export function appendixTemplate(frontMatter) {
|
||||
let html = styles;
|
||||
|
||||
if (typeof frontMatter.githubUrl !== 'undefined') {
|
||||
html += `
|
||||
<h3 id="updates-and-corrections">Updates and Corrections</h3>
|
||||
<p>`;
|
||||
if (frontMatter.githubCompareUpdatesUrl) {
|
||||
html += `<a href="${frontMatter.githubCompareUpdatesUrl}">View all changes</a> to this article since it was first published.`;
|
||||
}
|
||||
html += `
|
||||
If you see mistakes or want to suggest changes, please <a href="${frontMatter.githubUrl + '/issues/new'}">create an issue on GitHub</a>. </p>
|
||||
`;
|
||||
}
|
||||
|
||||
const journal = frontMatter.journal;
|
||||
if (typeof journal !== 'undefined' && journal.title === 'Distill') {
|
||||
html += `
|
||||
<h3 id="reuse">Reuse</h3>
|
||||
<p>Diagrams and text are licensed under Creative Commons Attribution <a href="https://creativecommons.org/licenses/by/4.0/">CC-BY 4.0</a> with the <a class="github" href="${frontMatter.githubUrl}">source available on GitHub</a>, unless noted otherwise. The figures that have been reused from other sources don’t fall under this license and can be recognized by a note in their caption: “Figure from …”.</p>
|
||||
`;
|
||||
}
|
||||
|
||||
if (typeof frontMatter.publishedDate !== 'undefined') {
|
||||
html += `
|
||||
<h3 id="citation">Citation</h3>
|
||||
<p>For attribution in academic contexts, please cite this work as</p>
|
||||
<pre class="citation short">${frontMatter.concatenatedAuthors}, "${frontMatter.title}", Distill, ${frontMatter.publishedYear}.</pre>
|
||||
<p>BibTeX citation</p>
|
||||
<pre class="citation long">${serializeFrontmatterToBibtex(frontMatter)}</pre>
|
||||
`;
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
export class DistillAppendix extends HTMLElement {
|
||||
|
||||
static get is() { return 'distill-appendix'; }
|
||||
|
||||
set frontMatter(frontMatter) {
|
||||
this.innerHTML = appendixTemplate(frontMatter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import { Template } from '../mixins/template';
|
||||
import logo from '../assets/distill-logo.svg';
|
||||
|
||||
const T = Template('distill-footer', `
|
||||
<style>
|
||||
|
||||
:host {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-weight: 300;
|
||||
padding: 60px 0;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
background-color: hsl(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
|
||||
text-align: left;
|
||||
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>
|
||||
ISSN 2476-0757
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
`);
|
||||
|
||||
export class DistillFooter extends T(HTMLElement) {
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { appendixTemplate } from '../distill-components/distill-appendix';
|
||||
|
||||
export default function(dom, data) {
|
||||
|
||||
const appendixTag = dom.querySelector('d-appendix');
|
||||
if (!appendixTag) {
|
||||
console.warn('No appendix tag found!');
|
||||
return;
|
||||
}
|
||||
const distillAppendixTag = appendixTag.querySelector('distill-appendix');
|
||||
if (!distillAppendixTag) {
|
||||
const distillAppendix = dom.createElement('distill-appendix');
|
||||
appendixTag.appendChild(distillAppendix);
|
||||
distillAppendix.innerHTML = appendixTemplate(data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default function(dom) {
|
||||
const footerTag = dom.querySelector('distill-footer');
|
||||
if(!footerTag) {
|
||||
const footer = dom.createElement('distill-footer');
|
||||
const body = dom.querySelector('body');
|
||||
body.appendChild(footer);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
export default function(dom) {
|
||||
const headerTag = dom.querySelector('distill-header');
|
||||
if (!headerTag) {
|
||||
const header = dom.createElement('distill-header');
|
||||
const body = dom.querySelector('body');
|
||||
body.insertBefore(header, body.firstChild);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { parseBibtex } from '../helpers/bibtex';
|
||||
import fs from 'fs';
|
||||
import { parseBibliography } from '../components/d-bibliography';
|
||||
|
||||
export default function(dom, data) {
|
||||
const bibliographyTag = dom.querySelector('d-bibliography');
|
||||
if (!bibliographyTag) {
|
||||
console.warn('No bibliography tag found!');
|
||||
return;
|
||||
}
|
||||
|
||||
const src = bibliographyTag.getAttribute('src');
|
||||
if (src) {
|
||||
const path = data.inputDirectory + '/' + src;
|
||||
const text = fs.readFileSync(path, 'utf-8');
|
||||
const bibliography = parseBibtex(text);
|
||||
const scriptTag = dom.createElement('script');
|
||||
scriptTag.type = 'text/json';
|
||||
scriptTag.textContent = JSON.stringify([...bibliography]);
|
||||
bibliographyTag.appendChild(scriptTag);
|
||||
bibliographyTag.removeAttribute('src');
|
||||
}
|
||||
|
||||
data.bibliography = parseBibliography(bibliographyTag);
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { collect_citations } from '../helpers/citation.js';
|
||||
|
||||
export default function(dom, data) {
|
||||
const citations = new Set(data.citations);
|
||||
const newCitations = collect_citations(dom);
|
||||
for (const citation of newCitations) {
|
||||
citations.add(citation);
|
||||
}
|
||||
data.citations = Array.from(citations);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { parseFrontmatter } from '../components/d-front-matter';
|
||||
import { mergeFromYMLFrontmatter } from '../front-matter.js';
|
||||
|
||||
export default function(dom, data) {
|
||||
const frontMatterTag = dom.querySelector('d-front-matter');
|
||||
if (!frontMatterTag) {
|
||||
console.warn('No front matter tag found!');
|
||||
return;
|
||||
}
|
||||
const extractedData = parseFrontmatter(frontMatterTag);
|
||||
mergeFromYMLFrontmatter(data, extractedData);
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
||||
const months = ['Jan.', 'Feb.', 'March', 'April', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'];
|
||||
const zeroPad = n => n < 10 ? '0' + n : n;
|
||||
|
||||
const RFC = function(date) {
|
||||
const day = days[date.getDay()].substring(0, 3);
|
||||
const paddedDate = zeroPad(date.getDate());
|
||||
const month = months[date.getMonth()].substring(0,3);
|
||||
const year = date.getFullYear().toString();
|
||||
const hours = date.getUTCHours().toString();
|
||||
const minutes = date.getUTCMinutes().toString();
|
||||
const seconds = date.getUTCSeconds().toString();
|
||||
return `${day}, ${paddedDate} ${month} ${year} ${hours}:${minutes}:${seconds} Z`;
|
||||
};
|
||||
|
||||
const objectFromMap = function(map) {
|
||||
const object = Array.from(map).reduce((object, [key, value]) => (
|
||||
Object.assign(object, { [key]: value }) // Be careful! Maps can have non-String keys; object literals can't.
|
||||
), {});
|
||||
return object;
|
||||
};
|
||||
|
||||
const mapFromObject = function(object) {
|
||||
const map = new Map();
|
||||
for (var property in object) {
|
||||
if (object.hasOwnProperty(property)) {
|
||||
map.set(property, object[property]);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
};
|
||||
|
||||
class Author {
|
||||
|
||||
// constructor(name='', personalURL='', affiliation='', affiliationURL='') {
|
||||
// this.name = name; // 'Chris Olah'
|
||||
// this.personalURL = personalURL; // 'https://colah.github.io'
|
||||
// this.affiliation = affiliation; // 'Google Brain'
|
||||
// this.affiliationURL = affiliationURL; // 'https://g.co/brain'
|
||||
// }
|
||||
|
||||
constructor(object) {
|
||||
this.name = object.author; // 'Chris Olah'
|
||||
this.personalURL = object.authorURL; // 'https://colah.github.io'
|
||||
this.affiliation = object.affiliation; // 'Google Brain'
|
||||
this.affiliationURL = object.affiliationURL; // 'https://g.co/brain'
|
||||
}
|
||||
|
||||
// 'Chris'
|
||||
get firstName() {
|
||||
const names = this.name.split(' ');
|
||||
return names.slice(0, names.length - 1).join(' ');
|
||||
}
|
||||
|
||||
// 'Olah'
|
||||
get lastName() {
|
||||
const names = this.name.split(' ');
|
||||
return names[names.length -1];
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeFromYMLFrontmatter(target, source) {
|
||||
target.title = source.title;
|
||||
if (source.published) {
|
||||
if (source.published instanceof Date) {
|
||||
target.publishedDate = source.published;
|
||||
} else if (source.published.constructor === String) {
|
||||
target.publishedDate = new Date(source.published);
|
||||
}
|
||||
}
|
||||
if (source.publishedDate) {
|
||||
if (source.publishedDate instanceof Date) {
|
||||
target.publishedDate = source.publishedDate;
|
||||
} else if (source.publishedDate.constructor === String) {
|
||||
target.publishedDate = new Date(source.publishedDate);
|
||||
}
|
||||
}
|
||||
target.description = source.description;
|
||||
target.authors = source.authors.map( (authorObject) => new Author(authorObject));
|
||||
target.katex = source.katex;
|
||||
target.password = source.password;
|
||||
}
|
||||
|
||||
export class FrontMatter {
|
||||
constructor() {
|
||||
this.title = 'unnamed article'; // 'Attention and Augmented Recurrent Neural Networks'
|
||||
this.description = ''; // 'A visual overview of neural attention...'
|
||||
this.authors = []; // Array of Author(s)
|
||||
|
||||
this.bibliography = new Map();
|
||||
this.bibliographyParsed = false;
|
||||
// {
|
||||
// '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': 'arXiv preprint arXiv:1502.04623',
|
||||
// 'year': '2015',
|
||||
// 'url': 'https://arxiv.org/pdf/1502.04623.pdf',
|
||||
// 'type': 'article'
|
||||
// },
|
||||
// }
|
||||
|
||||
// Citation keys should be listed in the order that they are appear in the document.
|
||||
// Each key refers to a key in the bibliography dictionary.
|
||||
this.citations = []; // [ 'gregor2015draw', 'mercier2011humans' ]
|
||||
this.citationsCollected = false;
|
||||
|
||||
//
|
||||
// Assigned from posts.csv
|
||||
//
|
||||
|
||||
// publishedDate: 2016-09-08T07:00:00.000Z,
|
||||
// tags: [ 'rnn' ],
|
||||
// distillPath: '2016/augmented-rnns',
|
||||
// githubPath: 'distillpub/post--augmented-rnns',
|
||||
// doiSuffix: 1,
|
||||
|
||||
//
|
||||
// Assigned from journal
|
||||
//
|
||||
this.journal = {};
|
||||
// journal: {
|
||||
// 'title': 'Distill',
|
||||
// 'full_title': 'Distill',
|
||||
// 'abbrev_title': 'Distill',
|
||||
// 'url': 'http://distill.pub',
|
||||
// 'doi': '10.23915/distill',
|
||||
// 'publisherName': 'Distill Working Group',
|
||||
// 'publisherEmail': 'admin@distill.pub',
|
||||
// 'issn': '2476-0757',
|
||||
// 'editors': [...],
|
||||
// 'committee': [...]
|
||||
// }
|
||||
// volume: 1,
|
||||
// issue: 9,
|
||||
|
||||
this.katex = {};
|
||||
|
||||
//
|
||||
// Assigned from publishing process
|
||||
//
|
||||
|
||||
// githubCompareUpdatesUrl: 'https://github.com/distillpub/post--augmented-rnns/compare/1596e094d8943d2dc0ea445d92071129c6419c59...3bd9209e0c24d020f87cf6152dcecc6017cbc193',
|
||||
// updatedDate: 2017-03-21T07:13:16.000Z,
|
||||
// doi: '10.23915/distill.00001',
|
||||
this.publishedDate = undefined;
|
||||
}
|
||||
|
||||
// Example:
|
||||
// title: Demo Title Attention and Augmented Recurrent Neural Networks
|
||||
// published: Jan 10, 2017
|
||||
// authors:
|
||||
// - Chris Olah:
|
||||
// - Shan Carter: http://shancarter.com
|
||||
// affiliations:
|
||||
// - Google Brain:
|
||||
// - Google Brain: http://g.co/brain
|
||||
|
||||
//
|
||||
// Computed Properties
|
||||
//
|
||||
|
||||
// 'http://distill.pub/2016/augmented-rnns',
|
||||
set url(value) {
|
||||
this._url = value;
|
||||
}
|
||||
get url() {
|
||||
if (this._url) {
|
||||
return this._url;
|
||||
} else if (this.distillPath && this.journal.url) {
|
||||
return this.journal.url + '/' + this.distillPath;
|
||||
} else if (this.journal.url) {
|
||||
return this.journal.url;
|
||||
}
|
||||
}
|
||||
|
||||
// 'https://github.com/distillpub/post--augmented-rnns',
|
||||
get githubUrl() {
|
||||
if (this.githubPath) {
|
||||
return 'https://github.com/' + this.githubPath;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO resolve differences in naming of URL/Url/url.
|
||||
// 'http://distill.pub/2016/augmented-rnns/thumbnail.jpg',
|
||||
set previewURL(value) {
|
||||
this._previewURL = value;
|
||||
}
|
||||
get previewURL() {
|
||||
return this._previewURL ? this._previewURL : this.url + '/thumbnail.jpg';
|
||||
}
|
||||
|
||||
// 'Thu, 08 Sep 2016 00:00:00 -0700',
|
||||
get publishedDateRFC() {
|
||||
return RFC(this.publishedDate);
|
||||
}
|
||||
|
||||
// 'Thu, 08 Sep 2016 00:00:00 -0700',
|
||||
get updatedDateRFC() {
|
||||
return RFC(this.updatedDate);
|
||||
}
|
||||
|
||||
// 2016,
|
||||
get publishedYear() {
|
||||
return this.publishedDate.getFullYear();
|
||||
}
|
||||
|
||||
// 'Sept',
|
||||
get publishedMonth() {
|
||||
return months[this.publishedDate.getMonth()];
|
||||
}
|
||||
|
||||
// 8,
|
||||
get publishedDay() {
|
||||
return this.publishedDate.getDate();
|
||||
}
|
||||
|
||||
// '09',
|
||||
get publishedMonthPadded() {
|
||||
return zeroPad(this.publishedDate.getMonth() + 1);
|
||||
}
|
||||
|
||||
// '08',
|
||||
get publishedDayPadded() {
|
||||
return zeroPad(this.publishedDate.getDate());
|
||||
}
|
||||
|
||||
get publishedISODateOnly() {
|
||||
return this.publishedDate.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
get volume() {
|
||||
const volume = this.publishedYear - 2015;
|
||||
if (volume < 1) {
|
||||
throw new Error('Invalid publish date detected during computing volume');
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
get issue() {
|
||||
return this.publishedDate.getMonth() + 1;
|
||||
}
|
||||
|
||||
// 'Olah & Carter',
|
||||
get concatenatedAuthors() {
|
||||
if (this.authors.length > 2) {
|
||||
return this.authors[0].lastName + ', et al.';
|
||||
} else if (this.authors.length === 2) {
|
||||
return this.authors[0].lastName + ' & ' + this.authors[1].lastName;
|
||||
} else if (this.authors.length === 1) {
|
||||
return this.authors[0].lastName;
|
||||
}
|
||||
}
|
||||
|
||||
// 'Olah, Chris and Carter, Shan',
|
||||
get bibtexAuthors() {
|
||||
return this.authors.map(author => {
|
||||
return author.lastName + ', ' + author.firstName;
|
||||
}).join(' and ');
|
||||
}
|
||||
|
||||
// 'olah2016attention'
|
||||
get slug() {
|
||||
let slug = '';
|
||||
if (this.authors.length) {
|
||||
slug += this.authors[0].lastName.toLowerCase();
|
||||
slug += this.publishedYear;
|
||||
slug += this.title.split(' ')[0].toLowerCase();
|
||||
}
|
||||
return slug || 'Untitled';
|
||||
}
|
||||
|
||||
get bibliographyEntries() {
|
||||
return new Map(this.citations.map( citationKey => {
|
||||
const entry = this.bibliography.get(citationKey);
|
||||
return [citationKey, entry];
|
||||
}));
|
||||
}
|
||||
|
||||
set bibliography(bibliography) {
|
||||
if (bibliography instanceof Map) {
|
||||
this._bibliography = bibliography;
|
||||
} else if (typeof bibliography === 'object') {
|
||||
this._bibliography = mapFromObject(bibliography);
|
||||
}
|
||||
}
|
||||
|
||||
get bibliography() {
|
||||
return this._bibliography;
|
||||
}
|
||||
|
||||
static fromObject(source) {
|
||||
const frontMatter = new FrontMatter();
|
||||
Object.assign(frontMatter, source);
|
||||
return frontMatter;
|
||||
}
|
||||
|
||||
assignToObject(target) {
|
||||
Object.assign(target, this);
|
||||
target.bibliography = objectFromMap(this.bibliographyEntries);
|
||||
target.url = this.url;
|
||||
target.githubUrl = this.githubUrl;
|
||||
target.previewURL = this.previewURL;
|
||||
target.volume = this.volume;
|
||||
target.issue = this.issue;
|
||||
target.publishedDateRFC = this.publishedDateRFC;
|
||||
target.publishedYear = this.publishedYear;
|
||||
target.publishedMonth = this.publishedMonth;
|
||||
target.publishedDay = this.publishedDay;
|
||||
target.publishedMonthPadded = this.publishedMonthPadded;
|
||||
target.publishedDayPadded = this.publishedDayPadded;
|
||||
target.updatedDateRFC = this.updatedDateRFC;
|
||||
target.concatenatedAuthors = this.concatenatedAuthors;
|
||||
target.bibtexAuthors = this.bibtexAuthors;
|
||||
target.slug = this.slug;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import bibtexParse from 'bibtex-parse-js';
|
||||
|
||||
function normalizeTag(string) {
|
||||
return string
|
||||
.replace(/[\t\n ]+/g, ' ')
|
||||
.replace(/{\\["^`.'acu~Hvs]( )?([a-zA-Z])}/g, (full, x, char) => char)
|
||||
.replace(/{\\([a-zA-Z])}/g, (full, char) => char);
|
||||
}
|
||||
|
||||
export function parseBibtex(bibtex) {
|
||||
const bibliography = new Map();
|
||||
const parsedEntries = bibtexParse.toJSON(bibtex);
|
||||
for (const entry of parsedEntries) {
|
||||
// normalize tags; note entryTags is an object, not Map
|
||||
for (const [key, value] of Object.entries(entry.entryTags)) {
|
||||
entry.entryTags[key.toLowerCase()] = normalizeTag(value);
|
||||
}
|
||||
entry.entryTags.type = entry.entryType;
|
||||
// add to bibliography
|
||||
bibliography.set(entry.citationKey, entry.entryTags);
|
||||
}
|
||||
return bibliography;
|
||||
}
|
||||
|
||||
export function serializeFrontmatterToBibtex(frontMatter) {
|
||||
return `@article{${frontMatter.slug},
|
||||
author = {${frontMatter.bibtexAuthors}},
|
||||
title = {${frontMatter.title}},
|
||||
journal = {${frontMatter.journal.title}},
|
||||
year = {${frontMatter.publishedYear}},
|
||||
note = {${frontMatter.url}}
|
||||
}`;
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
export function collect_citations(dom=document) {
|
||||
const citations = new Set();
|
||||
const citeTags = dom.querySelectorAll('d-cite');
|
||||
for (const tag of citeTags) {
|
||||
const keys = tag.getAttribute('key').split(',');
|
||||
for (const key of keys) {
|
||||
citations.add(key);
|
||||
}
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
return '['+keys.map(cite_string).join(', ')+']';
|
||||
}
|
||||
|
||||
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 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;
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
return keys.map(cite_string).join(', ');
|
||||
}
|
||||
|
||||
function author_string(ent, template, sep, finalSep){
|
||||
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 {
|
||||
var last = name.split(' ').slice(-1)[0].trim();
|
||||
var firsts = name.split(' ').slice(0,-1).join(' ');
|
||||
}
|
||||
var initials = '';
|
||||
if (firsts != undefined) {
|
||||
initials = firsts.trim().split(' ').map(s => s.trim()[0]);
|
||||
initials = initials.join('.')+'.';
|
||||
}
|
||||
return template.replace('${F}', firsts)
|
||||
.replace('${L}', last)
|
||||
.replace('${I}', initials);
|
||||
});
|
||||
if (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];
|
||||
}
|
||||
}
|
||||
|
||||
function venue_string(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;
|
||||
}
|
||||
if ('pages' in ent){
|
||||
cite += ', pp. ' + ent.pages;
|
||||
}
|
||||
if (cite != '') cite += '. ';
|
||||
if ('publisher' in ent){
|
||||
cite += ent.publisher;
|
||||
if (cite[cite.length-1] != '.') cite += '.';
|
||||
}
|
||||
return cite;
|
||||
}
|
||||
|
||||
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){
|
||||
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';
|
||||
}
|
||||
return `  <a href="${url}">[${label||'link'}]</a>`;
|
||||
}/* else if ("doi" in ent){
|
||||
return `  <a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
|
||||
}*/ else {
|
||||
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>`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
export function bibliography_cite(ent, fancy){
|
||||
if (ent){
|
||||
var cite = '<span class="title">' + ent.title + '</span> ';
|
||||
cite += link_string(ent) + '<br>';
|
||||
cite += author_string(ent, '${L}, ${I}', ', ', ' and ');
|
||||
if (ent.year || ent.date){
|
||||
cite += ', ' + (ent.year || ent.date) + '. ';
|
||||
} else {
|
||||
cite += '. ';
|
||||
}
|
||||
cite += venue_string(ent);
|
||||
cite += doi_string(ent);
|
||||
return cite;
|
||||
/*var cite = author_string(ent, "${L}, ${I}", ", ", " and ");
|
||||
if (ent.year || ent.date){
|
||||
cite += ", " + (ent.year || ent.date) + ". "
|
||||
} else {
|
||||
cite += ". "
|
||||
}
|
||||
cite += "<b>" + ent.title + "</b>. ";
|
||||
cite += venue_string(ent);
|
||||
cite += doi_string(ent);
|
||||
cite += link_string(ent);
|
||||
return cite*/
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
export function hover_cite(ent){
|
||||
if (ent){
|
||||
var cite = '';
|
||||
cite += '<b>' + ent.title + '</b>';
|
||||
cite += link_string(ent);
|
||||
cite += '<br>';
|
||||
|
||||
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;
|
||||
} else {
|
||||
cite += a_str + '<br>' + v_str;
|
||||
}
|
||||
return cite;
|
||||
} else {
|
||||
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(' ')});
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
function make_hover_css(target_node, pos) {
|
||||
const pretty = window.innerWidth > 600;
|
||||
const padding = pretty? 18 : 12;
|
||||
const outer_padding = pretty ? 18 : 0;
|
||||
// const bbox = document.querySelector('body').getBoundingClientRect();
|
||||
const bbox = target_node.offsetParent.getBoundingClientRect();
|
||||
let left = pos[0] - bbox.left, top = pos[1] - bbox.top;
|
||||
let width = Math.min(window.innerWidth-2*outer_padding, 648);
|
||||
left = Math.min(left, window.innerWidth-width-outer_padding);
|
||||
width = width - 2 * padding;
|
||||
return (`position: absolute;
|
||||
background-color: #FFF;
|
||||
opacity: 0.95;
|
||||
max-width: ${width}px;
|
||||
top: ${top}px;
|
||||
left: ${left}px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
padding: ${padding}px;
|
||||
border-radius: ${pretty? 3 : 0}px;
|
||||
box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.2);
|
||||
z-index: ${1e6};`);
|
||||
}
|
||||
|
||||
export class HoverBox {
|
||||
|
||||
constructor(contentHTML, triggerElement) {
|
||||
this.visible = false;
|
||||
// div hold teh contents of the box that will become visible
|
||||
this.div = contentHTML;
|
||||
this.bindDivEvents(this.div);
|
||||
// triggerElement holds the element that needs to be hovered etc to show contents
|
||||
this.triggerElement = triggerElement;
|
||||
this.bindTriggerEvents(this.triggerElement);
|
||||
this.hide();
|
||||
}
|
||||
|
||||
bindDivEvents(node) {
|
||||
// For mice, same behavior as hovering on links
|
||||
this.div.addEventListener('mouseover', () => {
|
||||
if (!this.visible) this.showAtNode(node);
|
||||
this.stopTimeout();
|
||||
});
|
||||
this.div.addEventListener('mouseout', () => {
|
||||
this.extendTimeout(500);
|
||||
});
|
||||
// Don't trigger body touchstart event when touching within box
|
||||
this.div.addEventListener('touchstart', (event) => {
|
||||
event.stopPropagation();
|
||||
}, {passive: true});
|
||||
// Close box when touching outside box
|
||||
document.body.addEventListener('touchstart', () => {
|
||||
this.hide();
|
||||
}, {passive: true});
|
||||
}
|
||||
|
||||
bindTriggerEvents(node) {
|
||||
node.addEventListener('mouseover', () => {
|
||||
if (!this.visible) {
|
||||
this.showAtNode(node);
|
||||
}
|
||||
this.stopTimeout();
|
||||
});
|
||||
|
||||
node.addEventListener('mouseout', () => {
|
||||
this.extendTimeout(500);
|
||||
});
|
||||
|
||||
node.addEventListener('touchstart', (event) => {
|
||||
if (this.visible) {
|
||||
this.hide();
|
||||
} else {
|
||||
this.showAtNode(node);
|
||||
}
|
||||
// Don't trigger body touchstart event when touching link
|
||||
event.stopPropagation();
|
||||
}, {passive: true});
|
||||
}
|
||||
|
||||
show(position) {
|
||||
this.visible = true;
|
||||
// const css = make_hover_css(this.triggerElement, position);
|
||||
this.div.setAttribute('style', 'display: block;' );
|
||||
}
|
||||
|
||||
showAtNode(node) {
|
||||
const bbox = node.getBoundingClientRect();
|
||||
this.show([bbox.right, bbox.bottom]);
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.visible = false;
|
||||
this.div.setAttribute('style', 'display: none;');
|
||||
this.stopTimeout();
|
||||
}
|
||||
|
||||
stopTimeout() {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
extendTimeout(time) {
|
||||
this.stopTimeout();
|
||||
this.timeout = setTimeout(() => {
|
||||
this.hide();
|
||||
}, time);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
// This is a straight concatenation of code from KaTeX's contrib folder,
|
||||
// but we aren't using some of their helpers that don't work well outside a browser environment.
|
||||
|
||||
/*global katex */
|
||||
|
||||
const findEndOfMath = function(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
let index = startIndex;
|
||||
let braceLevel = 0;
|
||||
|
||||
const delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
const character = text[index];
|
||||
|
||||
if (braceLevel <= 0 &&
|
||||
text.slice(index, index + delimLength) === delimiter) {
|
||||
return index;
|
||||
} else if (character === '\\') {
|
||||
index++;
|
||||
} else if (character === '{') {
|
||||
braceLevel++;
|
||||
} else if (character === '}') {
|
||||
braceLevel--;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
const splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
|
||||
const finalData = [];
|
||||
|
||||
for (let i = 0; i < startData.length; i++) {
|
||||
if (startData[i].type === 'text') {
|
||||
const text = startData[i].data;
|
||||
|
||||
let lookingForLeft = true;
|
||||
let currIndex = 0;
|
||||
let nextIndex;
|
||||
|
||||
nextIndex = text.indexOf(leftDelim);
|
||||
if (nextIndex !== -1) {
|
||||
currIndex = nextIndex;
|
||||
finalData.push({
|
||||
type: 'text',
|
||||
data: text.slice(0, currIndex),
|
||||
});
|
||||
lookingForLeft = false;
|
||||
}
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
if (lookingForLeft) {
|
||||
nextIndex = text.indexOf(leftDelim, currIndex);
|
||||
if (nextIndex === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
finalData.push({
|
||||
type: 'text',
|
||||
data: text.slice(currIndex, nextIndex),
|
||||
});
|
||||
|
||||
currIndex = nextIndex;
|
||||
} else {
|
||||
nextIndex = findEndOfMath(
|
||||
rightDelim,
|
||||
text,
|
||||
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,
|
||||
});
|
||||
|
||||
currIndex = nextIndex + rightDelim.length;
|
||||
}
|
||||
|
||||
lookingForLeft = !lookingForLeft;
|
||||
}
|
||||
|
||||
finalData.push({
|
||||
type: 'text',
|
||||
data: text.slice(currIndex),
|
||||
});
|
||||
} else {
|
||||
finalData.push(startData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return finalData;
|
||||
};
|
||||
|
||||
|
||||
const splitWithDelimiters = function(text, delimiters) {
|
||||
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);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
const renderMathInText = function(text, optionsCopy) {
|
||||
const data = splitWithDelimiters(text, optionsCopy.delimiters);
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === 'text') {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
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
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
try {
|
||||
tag.textContent = math;
|
||||
if (optionsCopy.displayMode) {
|
||||
tag.setAttribute('block', '');
|
||||
}
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
optionsCopy.errorCallback(
|
||||
'KaTeX auto-render: Failed to parse `' + data[i].data +
|
||||
'` with ',
|
||||
e
|
||||
);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
fragment.appendChild(tag);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
const renderElem = function(elem, optionsCopy) {
|
||||
for (let i = 0; i < elem.childNodes.length; i++) {
|
||||
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);
|
||||
} else if (childNode.nodeType === 1) {
|
||||
// Element node
|
||||
const shouldRender = optionsCopy.ignoredTags.indexOf(
|
||||
childNode.nodeName.toLowerCase()) === -1;
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
}
|
||||
// Otherwise, it's something else, and ignore it.
|
||||
}
|
||||
};
|
||||
|
||||
const defaultAutoRenderOptions = {
|
||||
delimiters: [
|
||||
{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',
|
||||
],
|
||||
|
||||
errorCallback: function(msg, err) {
|
||||
console.error(msg, err);
|
||||
},
|
||||
};
|
||||
|
||||
export const renderMathInElement = function(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error('No element provided to render');
|
||||
}
|
||||
|
||||
const optionsCopy = Object.assign({}, defaultAutoRenderOptions, options);
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
// const marginSmall = 16;
|
||||
// const marginLarge = 3 * marginSmall;
|
||||
// const margin = marginSmall + marginLarge;
|
||||
// const gutter = marginSmall;
|
||||
// const outsetAmount = margin / 2;
|
||||
// const numCols = 4;
|
||||
// const numGutters = numCols - 1;
|
||||
// const columnWidth = (768 - 2 * marginLarge - numGutters * gutter) / numCols;
|
||||
//
|
||||
// const screenwidth = 768;
|
||||
// const pageWidth = screenwidth - 2 * marginLarge;
|
||||
// const bodyWidth = pageWidth - columnWidth - gutter;
|
||||
|
||||
export function body(selector) {
|
||||
return `${selector} {
|
||||
grid-column: left / text;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
export function page(selector) {
|
||||
return `${selector} {
|
||||
grid-column: left / page;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
export function screen(selector) {
|
||||
return `${selector} {
|
||||
grid-column: start / end;
|
||||
}
|
||||
`;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
export function addPolyfill(polyfill, polyfillLoadedCallback) {
|
||||
console.info('Runlevel 0: Polyfill required: ' + polyfill.name);
|
||||
const script = document.createElement('script');
|
||||
script.src = polyfill.url;
|
||||
script.async = false;
|
||||
if (polyfillLoadedCallback) {
|
||||
script.onload = function() { polyfillLoadedCallback(polyfill); };
|
||||
}
|
||||
script.onerror = function() {
|
||||
new Error('Runlevel 0: Polyfills failed to load script ' + polyfill.name);
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
export const polyfills = [
|
||||
{
|
||||
name: 'WebComponents',
|
||||
support: function() {
|
||||
return 'customElements' in window &&
|
||||
'attachShadow' in Element.prototype &&
|
||||
'getRootNode' in Element.prototype &&
|
||||
'content' in document.createElement('template') &&
|
||||
'Promise' in window &&
|
||||
'from' in Array;
|
||||
},
|
||||
url: 'https://distill.pub/third-party/polyfills/webcomponents-lite.js'
|
||||
}, {
|
||||
name: 'IntersectionObserver',
|
||||
support: function() {
|
||||
return 'IntersectionObserver' in window &&
|
||||
'IntersectionObserverEntry' in window;
|
||||
},
|
||||
url: 'https://distill.pub/third-party/polyfills/intersection-observer.js'
|
||||
},
|
||||
];
|
||||
|
||||
export class Polyfills {
|
||||
|
||||
static browserSupportsAllFeatures() {
|
||||
return polyfills.every((poly) => poly.support());
|
||||
}
|
||||
|
||||
static load(callback) {
|
||||
// Define an intermediate callback that checks if all is loaded.
|
||||
const polyfillLoaded = function(polyfill) {
|
||||
polyfill.loaded = true;
|
||||
console.info('Runlevel 0: Polyfill has finished loading: ' + polyfill.name);
|
||||
// console.info(window[polyfill.name]);
|
||||
if (Polyfills.neededPolyfills.every((poly) => poly.loaded)) {
|
||||
console.info('Runlevel 0: All required polyfills have finished loading.');
|
||||
console.info('Runlevel 0->1.');
|
||||
window.distillRunlevel = 1;
|
||||
callback();
|
||||
}
|
||||
};
|
||||
// Add polyfill script tags
|
||||
for (const polyfill of Polyfills.neededPolyfills) {
|
||||
addPolyfill(polyfill, polyfillLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
static get neededPolyfills() {
|
||||
if (!Polyfills._neededPolyfills) {
|
||||
Polyfills._neededPolyfills = polyfills.filter((poly) => !poly.support());
|
||||
}
|
||||
return Polyfills._neededPolyfills;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
export const Mutating = (superclass) => {
|
||||
return class extends superclass {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// set up mutation observer
|
||||
const options = {childList: true, characterData: true, subtree: true};
|
||||
const observer = new MutationObserver( () => {
|
||||
observer.disconnect();
|
||||
this.renderIfPossible();
|
||||
observer.observe(this, options);
|
||||
});
|
||||
|
||||
// ...and listen for changes
|
||||
observer.observe(this, options);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.renderIfPossible();
|
||||
}
|
||||
|
||||
// potential TODO: check if this is enough for all our usecases
|
||||
// maybe provide a custom function to tell if we have enough information to render
|
||||
renderIfPossible() {
|
||||
if (this.textContent && this.root) {
|
||||
this.renderContent();
|
||||
}
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
console.error(`Your class ${this.constructor.name} must provide a custom renderContent() method!` );
|
||||
}
|
||||
|
||||
}; // end class
|
||||
}; // end mixin function
|
||||
@@ -1,85 +0,0 @@
|
||||
export function propName(attr) {
|
||||
return attr.replace(/(-[a-z])/g, (s) => s.toUpperCase().replace('-', ''));
|
||||
}
|
||||
|
||||
export function attrName(prop) {
|
||||
return prop.replace(/([A-Z])/g, (s) => '-' + s.toLowerCase());
|
||||
}
|
||||
|
||||
export function deserializeAttribute(value, type) {
|
||||
switch (type) {
|
||||
case String:
|
||||
break;
|
||||
case Array:
|
||||
case Object:
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch (e) {}
|
||||
break;
|
||||
case Boolean:
|
||||
value = value != 'false' && value != '0' && value;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const immediately = window.setImmediate || function(fn, args) {
|
||||
window.setTimeout(function() {
|
||||
fn.apply(this, args);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
export const Properties = (properties) => {
|
||||
const keys = Object.keys(properties);
|
||||
const attrs = keys.map((k) => attrName(k));
|
||||
return (superclass) => {
|
||||
const cls = class extends superclass {
|
||||
static get observedAttributes() {
|
||||
return attrs;
|
||||
}
|
||||
attributeChangedCallback(attr, oldValue, newValue) {
|
||||
const prop = propName(attr);
|
||||
const value = deserializeAttribute(newValue, properties[prop].type);
|
||||
this[prop] = value;
|
||||
}
|
||||
_propertiesChanged() {
|
||||
if (!this.propertiesChangedCallback) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(this._propertiesChangedTimeout);
|
||||
this._propertiesChangedTimeout = immediately(() => {
|
||||
this.propertiesChangedCallback(this);
|
||||
});
|
||||
}
|
||||
};
|
||||
keys.forEach(function(k) {
|
||||
const secret = `_${k}`;
|
||||
const callback = `${k}Changed`;
|
||||
const defaultValue = properties[k].value;
|
||||
Object.defineProperty(cls.prototype, k, {
|
||||
get: function() {
|
||||
let value = this[secret];
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
if (defaultValue && typeof defaultValue == 'function') {
|
||||
this[secret] = defaultValue();
|
||||
} else {
|
||||
this[secret] = defaultValue;
|
||||
}
|
||||
return this[secret];
|
||||
},
|
||||
set: function(value) {
|
||||
const oldValue = this[secret];
|
||||
this[secret] = value;
|
||||
if (this[callback]) {
|
||||
this[callback](value, oldValue);
|
||||
}
|
||||
this._propertiesChanged();
|
||||
}
|
||||
});
|
||||
});
|
||||
return cls;
|
||||
};
|
||||
};
|
||||
@@ -1,56 +0,0 @@
|
||||
/*global ShadyCSS*/
|
||||
|
||||
export const Template = (name, templateString, useShadow = true) => {
|
||||
|
||||
return (superclass) => {
|
||||
|
||||
const template = document.createElement('template');
|
||||
template.innerHTML = templateString;
|
||||
|
||||
if (useShadow && 'ShadyCSS' in window) {
|
||||
ShadyCSS.prepareTemplate(template, name);
|
||||
}
|
||||
|
||||
return class extends superclass {
|
||||
|
||||
static get is() { return name; }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.clone = document.importNode(template.content, true);
|
||||
if (useShadow) {
|
||||
this.attachShadow({mode: 'open'});
|
||||
this.shadowRoot.appendChild(this.clone);
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (useShadow) {
|
||||
if ('ShadyCSS' in window) {
|
||||
ShadyCSS.styleElement(this);
|
||||
}
|
||||
} else {
|
||||
this.insertBefore(this.clone, this.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
get root() {
|
||||
if (useShadow) {
|
||||
return this.shadowRoot;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Are we using these? Should we even? */
|
||||
$(query) {
|
||||
return this.root.querySelector(query);
|
||||
}
|
||||
|
||||
$$(query) {
|
||||
return this.root.querySelectorAll(query);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,225 +0,0 @@
|
||||
d-article {
|
||||
contain: content;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-top: 2rem;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
d-article > * {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
d-article {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
d-article {
|
||||
font-size: 1rem;
|
||||
line-height: 1.7em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* H2 */
|
||||
|
||||
|
||||
d-article .marker {
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
counter-reset: section;
|
||||
grid-column: kicker;
|
||||
line-height: 1.7em;
|
||||
}
|
||||
|
||||
d-article .marker:hover {
|
||||
border: none;
|
||||
}
|
||||
|
||||
d-article .marker span {
|
||||
padding: 0 3px 4px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
d-article .marker:hover span {
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
d-article h2 {
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 1.25em;
|
||||
margin: 2rem 0 1.5rem 0;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
d-article h2 {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H3 */
|
||||
|
||||
d-article h3 {
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
line-height: 1.4em;
|
||||
margin-bottom: 1em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
d-article h3 {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* H4 */
|
||||
|
||||
d-article h4 {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
d-article a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
d-article p,
|
||||
d-article ul,
|
||||
d-article ol,
|
||||
d-article blockquote {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
d-article blockquote {
|
||||
border-left: 2px solid rgba(0, 0, 0, 0.2);
|
||||
padding-left: 2em;
|
||||
font-style: italic;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
d-article a {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.4);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
d-article a:hover {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
d-article .link {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
d-article ul,
|
||||
d-article ol {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
d-article li {
|
||||
margin-bottom: 24px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
d-article pre {
|
||||
font-size: 14px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
d-article hr {
|
||||
grid-column: screen;
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
d-article section {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
d-article span.equation-mimic {
|
||||
font-family: georgia;
|
||||
font-size: 115%;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
d-article > d-code,
|
||||
d-article section > d-code {
|
||||
display: block;
|
||||
}
|
||||
|
||||
d-article > d-math[block],
|
||||
d-article section > d-math[block] {
|
||||
display: block;
|
||||
}
|
||||
|
||||
d-article .citation {
|
||||
color: #668;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
d-include {
|
||||
width: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
d-figure {
|
||||
contain: content;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* KaTeX */
|
||||
|
||||
.katex, .katex-prerendered {
|
||||
contain: content;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
|
||||
d-article table {
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1.5rem;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
d-article table th {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
d-article table td {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
d-article table tr:last-of-type td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
d-article table th,
|
||||
d-article table td {
|
||||
font-size: 15px;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
|
||||
d-article table tbody :first-child td {
|
||||
padding-top: 2px;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
d-byline {
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
contain: content;
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.8em;
|
||||
padding: 1.5rem 0;
|
||||
min-height: 1.8em;
|
||||
}
|
||||
|
||||
d-byline .byline {
|
||||
grid-template-columns: 2fr 1fr 1fr;
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
d-byline .authors-affiliations {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
}
|
||||
|
||||
d-byline h3 {
|
||||
font-size: 0.6rem;
|
||||
font-weight: 400;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
d-byline p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
d-byline a,
|
||||
d-article d-byline a {
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
text-decoration: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
d-article d-byline a:hover {
|
||||
text-decoration: underline;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
d-byline p.author {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
d-byline .affiliations {
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
span.katex-display {
|
||||
text-align: left;
|
||||
padding: 8px 0 8px 0;
|
||||
margin: 0.5em 0 0.5em 1em;
|
||||
}
|
||||
|
||||
span.katex {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
font-size: 1.18em;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
html {
|
||||
font-size: 16px;
|
||||
line-height: 1.6em;
|
||||
/* font-family: "Libre Franklin", "Helvetica Neue", sans-serif; */
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif;
|
||||
/*, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/
|
||||
text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #004276;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table thead {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
table thead th {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
table tbody :first-child td {
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
sup, sub {
|
||||
vertical-align: baseline;
|
||||
position: relative;
|
||||
top: -0.4em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
sub {
|
||||
top: 0.4em;
|
||||
}
|
||||
|
||||
.kicker,
|
||||
.marker {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
|
||||
/* Headline */
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
d-title h1 span {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Figure */
|
||||
|
||||
figure {
|
||||
position: relative;
|
||||
margin-bottom: 2.5em;
|
||||
margin-top: 2.5em;
|
||||
}
|
||||
|
||||
figcaption+figure {
|
||||
|
||||
}
|
||||
|
||||
figure img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
figure svg text,
|
||||
figure svg tspan {
|
||||
}
|
||||
|
||||
figcaption {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
font-size: 12px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
@media(min-width: 1024px) {
|
||||
figcaption {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
figure.external img {
|
||||
background: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.1);
|
||||
padding: 18px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
figcaption a {
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
figcaption b {
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 1.0);
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
@supports not (display: grid) {
|
||||
.base-grid,
|
||||
distill-header,
|
||||
d-title,
|
||||
d-abstract,
|
||||
d-article,
|
||||
d-appendix,
|
||||
distill-appendix,
|
||||
d-byline,
|
||||
d-footnote-list,
|
||||
d-citation-list,
|
||||
distill-footer {
|
||||
display: block;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.base-grid,
|
||||
distill-header,
|
||||
d-title,
|
||||
d-abstract,
|
||||
d-article,
|
||||
d-appendix,
|
||||
distill-appendix,
|
||||
d-byline,
|
||||
d-footnote-list,
|
||||
d-citation-list,
|
||||
distill-footer {
|
||||
display: grid;
|
||||
justify-items: stretch;
|
||||
grid-template-columns: [screen-start] 8px [page-start kicker-start text-start gutter-start middle-start] 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr [text-end page-end gutter-end kicker-end middle-end] 8px [screen-end];
|
||||
grid-column-gap: 8px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-column-gap: 8px;
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
.base-grid,
|
||||
distill-header,
|
||||
d-title,
|
||||
d-abstract,
|
||||
d-article,
|
||||
d-appendix,
|
||||
distill-appendix,
|
||||
d-byline,
|
||||
d-footnote-list,
|
||||
d-citation-list,
|
||||
distill-footer {
|
||||
grid-template-columns: [screen-start] 1fr [page-start kicker-start middle-start text-start] 45px 45px 45px 45px 45px 45px 45px 45px [ kicker-end text-end gutter-start] 45px [middle-end] 45px [page-end gutter-end] 1fr [screen-end];
|
||||
grid-column-gap: 16px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-column-gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1000px) {
|
||||
.base-grid,
|
||||
distill-header,
|
||||
d-title,
|
||||
d-abstract,
|
||||
d-article,
|
||||
d-appendix,
|
||||
distill-appendix,
|
||||
d-byline,
|
||||
d-footnote-list,
|
||||
d-citation-list,
|
||||
distill-footer {
|
||||
grid-template-columns: [screen-start] 1fr [page-start kicker-start] 50px [middle-start] 50px [text-start kicker-end] 50px 50px 50px 50px 50px 50px 50px 50px [text-end gutter-start] 50px [middle-end] 50px [page-end gutter-end] 1fr [screen-end];
|
||||
grid-column-gap: 16px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-column-gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 1280px) {
|
||||
.base-grid,
|
||||
distill-header,
|
||||
d-title,
|
||||
d-abstract,
|
||||
d-article,
|
||||
d-appendix,
|
||||
distill-appendix,
|
||||
d-byline,
|
||||
d-footnote-list,
|
||||
d-citation-list,
|
||||
distill-footer {
|
||||
grid-template-columns: [screen-start] 1fr [page-start kicker-start] 60px [middle-start] 60px [text-start kicker-end] 60px 60px 60px 60px 60px 60px 60px 60px [text-end gutter-start] 60px [middle-end] 60px [page-end gutter-end] 1fr [screen-end];
|
||||
grid-column-gap: 32px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
grid-column-gap: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.base-grid {
|
||||
grid-column: screen;
|
||||
}
|
||||
|
||||
/* .l-body,
|
||||
d-article > * {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
.l-page,
|
||||
d-title > *,
|
||||
d-figure {
|
||||
grid-column: page;
|
||||
} */
|
||||
|
||||
.l-gutter {
|
||||
grid-column: gutter;
|
||||
}
|
||||
|
||||
.l-text,
|
||||
.l-body {
|
||||
grid-column: text;
|
||||
}
|
||||
|
||||
.l-page {
|
||||
grid-column: page;
|
||||
}
|
||||
|
||||
.l-body-outset {
|
||||
grid-column: middle;
|
||||
}
|
||||
|
||||
.l-page-outset {
|
||||
grid-column: page;
|
||||
}
|
||||
|
||||
.l-screen {
|
||||
grid-column: screen;
|
||||
}
|
||||
|
||||
.l-screen-inset {
|
||||
grid-column: screen;
|
||||
padding-left: 16px;
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* Aside */
|
||||
|
||||
d-article aside {
|
||||
grid-column: gutter;
|
||||
font-size: 12px;
|
||||
line-height: 1.6em;
|
||||
color: rgba(0, 0, 0, 0.6)
|
||||
}
|
||||
|
||||
@media(min-width: 768px) {
|
||||
aside {
|
||||
grid-column: gutter;
|
||||
}
|
||||
|
||||
.side {
|
||||
grid-column: gutter;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import base from './styles-base.css';
|
||||
import layout from './styles-layout.css';
|
||||
import print from './styles-print.css';
|
||||
import byline from './d-byline.css';
|
||||
import article from './d-article.css';
|
||||
import math from './d-math.css';
|
||||
|
||||
export const styles = base + layout + byline + article + math + print;
|
||||
|
||||
export function makeStyleTag(dom) {
|
||||
|
||||
const styleTagId = 'distill-prerendered-styles';
|
||||
const prerenderedTag = dom.getElementById(styleTagId);
|
||||
if (!prerenderedTag) {
|
||||
const styleTag = dom.createElement('style');
|
||||
styleTag.id = styleTagId;
|
||||
styleTag.type = 'text/css';
|
||||
const cssTextTag = dom.createTextNode(styles);
|
||||
styleTag.appendChild(cssTextTag);
|
||||
const firstScriptTag = dom.head.querySelector('script');
|
||||
dom.head.insertBefore(styleTag, firstScriptTag);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/* eslint-env node, mocha */
|
||||
|
||||
import { FrontMatter } from './front-matter';
|
||||
|
||||
/* Extractors */
|
||||
import ExtractFrontmatter from './extractors/front-matter';
|
||||
import ExtractBibliography from './extractors/bibliography';
|
||||
import ExtractCitations from './extractors/citations';
|
||||
|
||||
const extractors = new Map([
|
||||
['ExtractFrontmatter', ExtractFrontmatter],
|
||||
['ExtractBibliography', ExtractBibliography],
|
||||
['ExtractCitations', ExtractCitations],
|
||||
]);
|
||||
|
||||
/* Transforms */
|
||||
import HTML from './transforms/html';
|
||||
import Byline from './transforms/byline';
|
||||
import OptionalComponents from './transforms/optional-components';
|
||||
import Mathematics from './transforms/mathematics';
|
||||
import Meta from './transforms/meta';
|
||||
import { makeStyleTag } from './styles/styles';
|
||||
import TOC from './transforms/toc';
|
||||
import Typeset from './transforms/typeset';
|
||||
import Polyfills from './transforms/polyfills';
|
||||
import CitationList from './transforms/citation-list';
|
||||
import Reorder from './transforms/reorder';
|
||||
|
||||
const transforms = new Map([
|
||||
['HTML', HTML],
|
||||
['makeStyleTag', makeStyleTag],
|
||||
['OptionalComponents', OptionalComponents],
|
||||
['TOC', TOC],
|
||||
['Byline', Byline],
|
||||
['Mathematics', Mathematics],
|
||||
['Meta', Meta],
|
||||
['Typeset', Typeset],
|
||||
['Polyfills', Polyfills],
|
||||
['CitationList', CitationList],
|
||||
['Reorder', Reorder] // keep last
|
||||
]);
|
||||
|
||||
/* Distill Transforms */
|
||||
import DistillHeader from './distill-transforms/distill-header';
|
||||
import DistillAppendix from './distill-transforms/distill-appendix';
|
||||
import DistillFooter from './distill-transforms/distill-footer';
|
||||
|
||||
const distillTransforms = new Map([
|
||||
['DistillHeader', DistillHeader],
|
||||
['DistillAppendix', DistillAppendix],
|
||||
['DistillFooter', DistillFooter],
|
||||
]);
|
||||
|
||||
/* Exported functions */
|
||||
|
||||
export function render(dom, data, verbose=true) {
|
||||
let frontMatter;
|
||||
if (data instanceof FrontMatter) {
|
||||
frontMatter = data;
|
||||
} else {
|
||||
frontMatter = FrontMatter.fromObject(data);
|
||||
}
|
||||
// first, we collect static data from the dom
|
||||
for (const [name, extract] of extractors.entries()) {
|
||||
if (verbose) console.warn('Running extractor: ' + name);
|
||||
extract(dom, frontMatter, verbose);
|
||||
}
|
||||
// secondly we use it to transform parts of the dom
|
||||
for (const [name, transform] of transforms.entries()) {
|
||||
if (verbose) console.warn('Running transform: ' + name);
|
||||
// console.warn('Running transform: ', transform);
|
||||
transform(dom, frontMatter, verbose);
|
||||
}
|
||||
dom.body.setAttribute('distill-prerendered', '');
|
||||
// the function calling us can now use the transformed dom and filled data object
|
||||
if (data instanceof FrontMatter) {
|
||||
// frontMatter will already have needed properties
|
||||
} else {
|
||||
frontMatter.assignToObject(data);
|
||||
}
|
||||
}
|
||||
|
||||
export function distillify(dom, data, verbose=true) {
|
||||
// thirdly, we can use these additional transforms when publishing on the Distill website
|
||||
for (const [name, transform] of distillTransforms.entries()) {
|
||||
if (verbose) console.warn('Running distillify: ', name);
|
||||
transform(dom, data, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
export function usesTemplateV2(dom) {
|
||||
const tags = dom.querySelectorAll('script');
|
||||
let usesV2 = undefined;
|
||||
for (const tag of tags) {
|
||||
const src = tag.src;
|
||||
if (src.includes('template.v1.js')) {
|
||||
usesV2 = false;
|
||||
} else if (src.includes('template.v2.js')) {
|
||||
usesV2 = true;
|
||||
} else if (src.includes('template.')) {
|
||||
throw new Error('Uses distill template, but unknown version?!');
|
||||
}
|
||||
}
|
||||
|
||||
if (usesV2 === undefined) {
|
||||
throw new Error('Does not seem to use Distill template at all.');
|
||||
} else {
|
||||
return usesV2;
|
||||
}
|
||||
}
|
||||
|
||||
export { FrontMatter }; // TODO: removable?
|
||||
|
||||
export const testing = {
|
||||
extractors: extractors,
|
||||
transforms: transforms,
|
||||
distillTransforms: distillTransforms
|
||||
};
|
||||