Compare commits

...

147 Commits

Author SHA1 Message Date
Ludwig Schubert a8d0e143cf Update example article 2017-08-24 10:35:17 -07:00
Ludwig Schubert a778d30946 Don't bundle katex anymore 2017-08-24 10:34:53 -07:00
Ludwig Schubert daf07f1f39 Minify on build, but not during development 2017-08-24 10:31:18 -07:00
Ludwig Schubert 9d180de631 Minor perf tweaks 2017-08-24 10:30:36 -07:00
Ludwig Schubert 8d23e288ae Minor style changes 2017-08-24 10:30:09 -07:00
Ludwig Schubert 50a3a49fd5 Fix crash in d-figure 2017-08-23 11:50:33 -07:00
Ludwig Schubert 75cca6c7cd Minor layout tweaks 2017-08-23 11:50:06 -07:00
Ludwig Schubert a15a9ba7a3 export embedded katex as window global 2017-08-23 11:49:47 -07:00
Ludwig Schubert 9993a679c1 Finish initial work on d-figure 2017-08-22 15:18:05 -07:00
Ludwig Schubert 08fafcf2ee Fix: crash if no byline was present 2017-08-21 18:43:58 -07:00
Ludwig Schubert 5e237be027 First work on d-figure 2017-08-21 18:43:26 -07:00
Ludwig Schubert dea6f27995 Wrap pure text nodes and warn about them 2017-08-10 13:00:41 -07:00
Ludwig Schubert a53817cd43 Merge branch 'v2' of github.com:distillpub/template into v2 2017-08-10 11:20:09 -07:00
Ludwig Schubert 8f4722173a Fix infinite loop when no citations were present 2017-08-10 11:19:32 -07:00
Shan Carter 991ed9bd11 Cleanup files 2017-08-09 16:58:45 -07:00
Shan Carter b4f2c4863f Fixing wecomponents dependency 2017-08-09 16:55:26 -07:00
Ludwig Schubert a1800ca2b3 Design changes 2017-08-09 16:48:07 -07:00
Ludwig Schubert 27fbe9a932 Fix linter warnings except for /transforms 2017-08-09 16:47:35 -07:00
Ludwig Schubert 11eda0fc49 Project reorganization, add editorconfig and linter 2017-08-09 16:47:35 -07:00
Ludwig Schubert 07c7527734 Remove mustache/handlebars dependency by switching to ES6 template literals 2017-08-09 16:47:35 -07:00
Ludwig Schubert 9fe826447b Switch to central controller for distributed control flow 2017-08-09 16:47:35 -07:00
Shan Carter 929b159aaa Adding Authors class, for computed first and last name properties. 2017-08-01 14:51:56 -07:00
Shan Carter 41764d28ba Cleaning up data.js 2017-08-01 14:39:53 -07:00
Shan Carter 09d60579d2 Adding first attempt at documenting data
:
2017-08-01 12:52:45 -07:00
Ludwig Schubert 7d48a5d6e8 WIP most components now on Shadow DOM 2017-07-27 17:44:18 -07:00
Ludwig Schubert 291864acae WIP move d-code and d-math and d-footnote to ShadowDOM 2017-07-25 19:22:11 -07:00
Ludwig Schubert 4f3ddce184 Add d-code and d-math componenents. Needs styling. 2017-07-21 17:48:39 -07:00
Shan Carter 031e3b52b9 Adding polyfills 2017-03-13 22:27:23 -07:00
Shan Carter 560f8bb4bf Checkpoint 2017-03-13 18:35:43 -07:00
Shan Carter 38aadd3332 Checkpoint 2017-03-13 15:47:33 -07:00
Shan Carter f544f1ec2d checkpoint 2017-03-13 13:08:06 -07:00
Shan Carter 5b2e2867f0 Appendix 2017-03-13 11:42:55 -07:00
Shan Carter feea10ed4e v2 start 2017-03-10 11:10:04 -08:00
Shan Carter 8807bb1778 Renaming and adding two configs 2017-03-01 09:35:06 -08:00
Shan Carter a1651d2195 Saving 2017-02-22 13:53:25 -08:00
Shan Carter 4ba3780f88 Saving 2017-02-14 14:39:03 -08:00
Christopher Olah 23889d702e add issn to crossref 2017-02-14 14:36:01 -08:00
Shan Carter 815758622d 0.0.21 2017-02-10 10:08:16 -08:00
Shan Carter b78eaf1a49 Style fixes 2017-02-10 10:08:11 -08:00
Shan Carter f19e65c68c Build 2017-02-08 12:20:35 -08:00
Shan Carter 056c74d2dd 0.0.20 2017-02-08 11:54:36 -08:00
Shan Carter 174edd5973 Adding updates link 2017-02-08 11:54:24 -08:00
Shan Carter 8162b8ea2d Adding diff link 2017-02-08 11:45:20 -08:00
Shan Carter 97acdc60d6 Adding updatedDate 2017-02-08 10:45:27 -08:00
Shan Carter de7ec5fc58 0.0.19 2017-02-06 17:14:58 -08:00
Shan Carter 0c49900eae Adding a CLI for rendering 2017-02-06 15:11:38 -08:00
Shan Carter 5dac7eed8b Fixin tree walker 2017-02-06 10:01:03 -08:00
Shan Carter e8e1a353ef Typo subs 2017-02-04 09:24:07 -08:00
Shan Carter 19da5e90c4 Polish on typo subs 2017-02-03 16:54:39 -08:00
Shan Carter 1995d75cb0 Adding columns and typo subs 2017-02-03 15:40:11 -08:00
Shan Carter 571d437fcf Fix to banner, print styles 2017-01-26 18:51:14 -08:00
Shan Carter 2197327ca6 Adding an alert banner to top when not on localhost 2017-01-26 10:55:40 -08:00
Shan Carter 7426809669 Updating styles 2017-01-25 17:32:51 -08:00
Shan Carter 00ccea8950 0.0.18 2017-01-25 16:38:51 -08:00
Shan Carter e637010296 building 2017-01-25 16:37:49 -08:00
Shan Carter e95a67b236 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-25 16:37:32 -08:00
Shan Carter 354293079a Text styles 2017-01-25 16:37:25 -08:00
Christopher Olah 4e3640f5d1 improve citation format 2017-01-25 13:33:18 -08:00
Shan Carter 0cfdef58c1 Fixing appendix padding 2017-01-25 10:39:09 -08:00
Shan Carter 8f0b24e0a1 ol fix 2017-01-24 17:46:13 -08:00
Shan Carter cde1ca1121 fixing ol padding 2017-01-24 17:42:50 -08:00
Shan Carter 47bf2ad986 alias fonts 2017-01-20 17:17:53 -08:00
Shan Carter 3c167692ae Fixing a link
hover
2017-01-20 17:01:58 -08:00
Shan Carter 495804e37d Fixing ul font family 2017-01-20 16:53:44 -08:00
Shan Carter 5c20980664 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-20 16:44:28 -08:00
Shan Carter 1a30efb26f Build 2017-01-20 16:44:25 -08:00
Christopher Olah ad87af296d improve top example in tutorial 2017-01-20 12:06:48 -08:00
Christopher Olah fbcedcf9d5 more on citations and appendix in bibliography 2017-01-20 01:25:18 -08:00
Shan Carter 33aa934b8b Saving 2017-01-19 17:00:43 -08:00
Shan Carter b278859a61 middle-outset center 2017-01-19 16:29:25 -08:00
Shan Carter f549e6e2bd middle-outset 2017-01-19 16:27:57 -08:00
Shan Carter 9e76725bc6 Support for sections 2017-01-19 16:02:03 -08:00
Shan Carter cc02e9aa20 Footnotes 2017-01-19 14:55:37 -08:00
Shan Carter 50b73d8e35 Centered side layouts 2017-01-19 14:40:40 -08:00
Shan Carter a411a2a3ed Fixing side layouts 2017-01-19 14:10:30 -08:00
Shan Carter e4bb6c0ba6 Updating 2017-01-19 12:59:40 -08:00
Shan Carter 7df82584e7 Updating code blocks 2017-01-19 12:59:14 -08:00
Christopher Olah 83c6a8c161 update crossref xml generation 2017-01-17 13:44:03 -08:00
Shan Carter e40e69733a Merging 2017-01-17 10:08:47 -08:00
Shan Carter 353f205ae7 build 2017-01-17 10:08:20 -08:00
Shan Carter 122ca1d50f Tweaks 2017-01-13 21:31:01 -08:00
Shan Carter 05d90a2b5b Style tweaks 2017-01-13 21:28:32 -08:00
Shan Carter 8f55384b9a Larger mobile font 2017-01-13 18:25:38 -08:00
Shan Carter 347f509660 bg color 2017-01-13 16:37:18 -08:00
Shan Carter 02a6b5f1f1 Footnote tweaks 2017-01-13 16:13:21 -08:00
Christopher Olah b914701d2b update dist 2017-01-13 13:47:06 -08:00
Christopher Olah 9c31a1ae49 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-13 13:46:50 -08:00
Christopher Olah 80b752ccdb update meta data generator 2017-01-13 13:46:38 -08:00
Shan Carter 9b74a4e43c Building 2017-01-13 13:36:27 -08:00
Shan Carter 02e81e2a8b Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-13 13:35:57 -08:00
Shan Carter 93e95030f4 Merge 2017-01-13 13:35:29 -08:00
Christopher Olah 45a8c03dc3 fix meta 2017-01-13 13:35:05 -08:00
Shan Carter 6ef2df375c Style tweaks 2017-01-13 13:35:02 -08:00
Christopher Olah 42fd20f2ac remove logging 2017-01-13 13:12:47 -08:00
Christopher Olah 7e03641e08 update dist 2017-01-13 13:11:17 -08:00
Christopher Olah bc04e18aba update url links for arxiv papers 2017-01-13 13:11:07 -08:00
Christopher Olah ecfe234414 new dist 2017-01-13 12:45:19 -08:00
Christopher Olah f190b3bef7 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-13 12:44:58 -08:00
Christopher Olah 8627c53506 fix bibliography citation issues 2017-01-13 12:44:47 -08:00
Shan Carter b6140bec36 Adding about link 2017-01-13 12:00:31 -08:00
Shan Carter f6c8a2a870 checkpoint 2017-01-13 10:38:18 -08:00
Shan Carter d8bc87061d CSS fixes 2017-01-11 16:38:28 -08:00
Shan Carter e107e72cd0 Merge 2017-01-11 16:03:44 -08:00
Shan Carter 44af921b8c Styling 2017-01-11 16:03:19 -08:00
Christopher Olah 3e61d836ea citation contents 2017-01-11 13:48:30 -08:00
Christopher Olah 548037bbe2 update template 2017-01-11 13:45:44 -08:00
Christopher Olah d7d256946d Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-11 13:45:23 -08:00
Christopher Olah 1844906ec4 udpate packages 2017-01-11 13:45:12 -08:00
Shan Carter beb7b6e195 build 2017-01-11 11:36:54 -08:00
Shan Carter e54311ee40 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-11 11:36:35 -08:00
Shan Carter febbb4fb5f Styles 2017-01-11 11:36:32 -08:00
Christopher Olah d70d9f35f9 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-11 11:35:24 -08:00
Christopher Olah 3dc4f84514 add footnote support 2017-01-11 11:35:12 -08:00
Shan Carter 93d61449f9 Updates 2017-01-11 11:12:04 -08:00
Shan Carter 10c436ffb2 Byline 2017-01-11 10:34:33 -08:00
Christopher Olah 9ebc8d5ea6 more work on citations 2017-01-10 18:48:47 -08:00
Christopher Olah 2ab2f0ffd5 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-10 18:04:01 -08:00
Christopher Olah 30b0fdd880 fix bibliography accent issues 2017-01-10 18:03:47 -08:00
Shan Carter a81b614e02 Better byline 2017-01-10 16:18:56 -08:00
Shan Carter 651b650d7b Merging 2017-01-10 16:06:18 -08:00
Shan Carter b389feff21 Byline 2017-01-10 16:05:51 -08:00
Christopher Olah f4cd0a580a rebuild template 2017-01-10 15:23:55 -08:00
Christopher Olah 20efb33c32 fix citation bugs 2017-01-10 15:23:45 -08:00
Christopher Olah 5f837d38b4 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-10 12:43:10 -08:00
Christopher Olah 712d859dad more work on citations 2017-01-10 12:42:59 -08:00
Shan Carter 2010c6d6be Building 2017-01-10 11:08:19 -08:00
Christopher Olah 9c40d08edd port hover box to node 2017-01-10 11:06:28 -08:00
Shan Carter 501e624d74 static js include 2017-01-10 10:15:59 -08:00
Shan Carter 5ff2ea745f 0.0.17 2017-01-10 09:38:16 -08:00
Christopher Olah 460a989897 fancy citations, without bloat 2017-01-10 02:08:28 -08:00
Christopher Olah d5c70f7c19 fully paramterize crossref xml 2017-01-09 20:46:44 -08:00
Shan Carter 66467a9e12 Spaces 2017-01-09 18:27:05 -08:00
Shan Carter 758697ab97 0.0.16 2017-01-09 18:22:44 -08:00
Shan Carter 4428ad1a5f Cleanup 2017-01-09 18:22:39 -08:00
Shan Carter c77fbbd18f 0.0.15 2017-01-09 18:11:32 -08:00
Shan Carter adcfba4627 Updating data processing 2017-01-09 18:09:59 -08:00
Shan Carter 6ef3847bf6 0.0.14 2017-01-09 17:37:13 -08:00
Shan Carter 0b68c4ea1f fix 2017-01-09 17:37:12 -08:00
Shan Carter 60cf026b88 0.0.13 2017-01-09 17:32:05 -08:00
Shan Carter b30d4084ef fix 2017-01-09 17:32:04 -08:00
Shan Carter 8aa8ef2206 0.0.12 2017-01-09 17:27:58 -08:00
Shan Carter c0824c1827 bib 2017-01-09 17:27:55 -08:00
Shan Carter 7fe35c3b88 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-09 17:24:19 -08:00
Christopher Olah b0b3265f72 Merge branch 'master' of https://github.com/distillpub/distill-template 2017-01-09 17:17:46 -08:00
Christopher Olah 971e90069e implement crossref generator 2017-01-09 17:17:30 -08:00
Shan Carter c8fa1f7eaa 0.0.11 2017-01-09 17:14:26 -08:00
Shan Carter 05179d887e Fix 2017-01-09 17:14:24 -08:00
108 changed files with 12265 additions and 9154 deletions
+15
View File
@@ -0,0 +1,15 @@
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
+22
View File
@@ -0,0 +1,22 @@
{
"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" ]
}
}
+5 -12
View File
@@ -9,18 +9,6 @@ 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
@@ -29,6 +17,7 @@ build/Release
# Dependency directories
node_modules
bower_components
jspm_packages
# Optional npm cache directory
@@ -45,3 +34,7 @@ jspm_packages
# Yarn Integrity file
.yarn-integrity
# Copied fonts
examples/fonts
dist
+23
View File
@@ -1,5 +1,28 @@
# Distill Templates
## Development
Run `yarn start` to start a watching build rollup server.
## Testing
Run `yarn test`. That's it.
## TODO:
-[ ] auto detection/adding behavior
* title
* appendix
* footnote list ?
-[x] should work without distill-appendix
-[x] YML author without ":" should work?
-[ ] throw warning on <hr>
-[ ] h numbering:
h2: position relative
a: position: absolute;
right: calc(100% + 16px);
/* text-align: right; */
/* width: 80px; */
/* font-size: 20px; */
/* font-weight: 200; */
Executable
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env node
const fs = require('fs');
const jsdom = require('jsdom').jsdom;
const serialize = require('jsdom').serializeDocument;
const program = require('commander');
const transforms = require('../dist/transforms.js');
program
.version('0.0.1')
.option('-i, --input <path>', 'path to input file.')
.parse(process.argv);
const htmlString = fs.readFileSync(program.input, 'utf8');
const data = {};
const dom = jsdom(htmlString, {features: {ProcessExternalResources: false, FetchExternalResources: false, runScripts: 'dangerously'}});
transforms.render(dom, data);
transforms.distillify(dom, data);
const transformedHtml = serialize(dom);
process.stdout.write(transformedHtml);
-78
View File
@@ -1,78 +0,0 @@
const html = `
<style>
dt-appendix {
display: block;
font-family: "Open Sans";
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: rgba(0,0,0,0.025);
padding-top: 36px;
padding-right: 24px;
padding-bottom: 60px;
padding-left: 24px;
}
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);
}
</style>
<div class="l-body">
<h3>References</h3>
<dt-bibliography></dt-bibliography>
<h3 id="citation">Errors, Reuse, and Citation</h3>
<p>If you see mistakes or want to suggest changes, please submit a pull request on <a class="github">github</a>.</p>
<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 source available on available on <a class="github">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"></pre>
<p>BibTeX citation</p>
<pre class="citation long"></pre>
</div>
`;
// distill.data().then(function(data) {
// var as = el.querySelectorAll("a.github");
// [].forEach.call(as, function(a) {
// a.setAttribute("href", data.github);
// });
// el.querySelector(".citation.short").textContent = data.concatenatedAuthors + ", " + '"' + data.title + '", Distill, ' + data.firstPublishedYear + ".";
// var bibtex = "@article{" + data.slug + ",\n";
// bibtex += " author = {" + data.bibtexAuthors + "},\n";
// bibtex += " title = {" + data.title + "},\n";
// bibtex += " journal = {Distill},\n";
// bibtex += " year = {" + data.firstPublishedYear + "},\n";
// bibtex += " note = {" + data.url + "}\n";
// bibtex += "}";
// el.querySelector(".citation.long").textContent = bibtex;
// })
export default function(dom, data) {
let el = dom.querySelector('dt-appendix')
if (el) el.innerHTML = html;
}
-38
View File
@@ -1,38 +0,0 @@
import bibtexParse from "bibtex-parse-js";
export default function(dom, data) {
let el = dom.querySelector('script[type="text/bibliography"]');
let citations = [];
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);
console.log(parsed);
if(parsed) {
parsed.forEach(e => {
bibliography[e.citationKey] = e.entryTags;
bibliography[e.citationKey].type = e.entryType;
});
}
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 bibliography)){
console.warn("No bibliography entry found for: " + key);
}
}
});
}
});
}
data.bibliography = bibliography;
data.citations = citations;
}
-111
View File
@@ -1,111 +0,0 @@
export default function(dom, data) {
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 citeTags = [].slice.apply(dom.querySelectorAll("dt-cite"));
console.log(citeTags);
citeTags.forEach(el => {
var key = el.getAttribute("key");
if (key) {
var keys = key.split(",");
console.log(keys)
var cite_string = inline_cite_short(keys);
el.innerHTML = cite_string;
}
});
let bibEl = dom.querySelector("dt-bibliography");
if (bibEl) {
let ol = dom.createElement("ol");
citations.forEach(key => {
let el = dom.createElement("li");
el.textContent = 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 bibliography_cite(ent){
if (ent){
var names = ent.author.split(" and ");
var cite = "";
let name_strings = names.map(name => {
var last = name.split(",")[0].trim();
var firsts = name.split(",")[1];
if (firsts != undefined) {
var initials = firsts.trim().split(" ").map(s => s.trim()[0]);
return last + ", " + initials.join(".")+".";
}
return last;
});
if (names.length > 1) {
cite += name_strings.slice(0, names.length-1).join(", ");
cite += " and " + name_strings[names.length-1];
} else {
cite += name_strings[0]
}
cite += ", " + ent.year + ". "
cite += ent.title + ". "
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
}
cite += ". "
return cite
} else {
return "?";
}
}
//https://scholar.google.com/scholar?q=allintitle%3ADocument+author%3Aolah
function get_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(" ")})
}
}
}
-3
View File
@@ -1,3 +0,0 @@
<svg viewBox="-607 419 64 64">
<path style="fill: none; stroke: black;stroke-width: 2px;" d="M-573.4,478.9c-8,0-14.6-6.4-14.6-14.5s14.6-25.9,14.6-40.8c0,14.9,14.6,32.8,14.6,40.8S-565.4,478.9-573.4,478.9z"/>
</svg>

Before

Width:  |  Height:  |  Size: 216 B

-36
View File
@@ -1,36 +0,0 @@
export default function(dom, data) {
data.authors = data.authors || [];
// paths
//data.distillPath = post.distillPath;
//data.githubPath = post.githubPath;
//data.url = "http://distill.pub/" + post.distillPath;
//data.githubUrl = "https://github.com/" + post.githubPath;
// Homepage
//data.homepage = !post.noHomepage;
// Dates
// TODO: fix updated date
if (data.published){//} && data.journal) {
data.volume = data.published.getFullYear() - 2015;
data.issue = data.published.getMonth() + 1;
}
/*
//let RFC = d3.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.volume = data.publishedDate.getFullYear() - 2015;
data.issue = data.publishedDate.getMonth() + 1;
}*/
}
-43
View File
@@ -1,43 +0,0 @@
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: rgba(0, 0, 0, 0.6);
}
dt-footer .logo svg {
width: 24px;
position: relative;
top: 4px;
margin-right: -2px;
}
dt-footer .logo svg path {
stroke: rgba(255, 255, 255, 0.8)!important;
stroke-width: 3px!important;
}
dt-footer .logo {
font-size: 16px;
font-weight: 300;
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
margin-right: 6px;
}
</style>
<div class="l-body">
<a href="/" class="logo">
${logo}
Distill
</a> is dedicated to clear explanations of machine learning
</div>
`;
export default function(dom, data) {
let el = dom.querySelector("dt-footer");
if(el) el.innerHTML = html;
}
-33
View File
@@ -1,33 +0,0 @@
import ymlParse from "js-yaml";
export default function(dom, data) {
let el = dom.querySelector('script[type="text/front-matter"]');
//TODO If we don't have a local element, make a request for the document.
if (el) {
let text = el.textContent;
let localData = ymlParse.safeLoad(text);
data.title = localData.title;
data.description = localData.description;
data.published = new Date(localData.published);
data.updated = new Date(localData.published || localData.updated);
data.authors = localData.authors.map((author, i) =>{
let a = {};
let name = Object.keys(author)[0];
let names = name.split(" ");
a.firstName = names.slice(0, names.length - 1).join(" ");
a.lastName = names[names.length -1];
a.personalURL = author[name];
if(localData.affiliations[i]) {
let affiliation = Object.keys(localData.affiliations[i])[0];
a.affiliation = affiliation;
a.affiliationURL = localData.affiliations[i][affiliation];
}
return a;
});
}
}
-3
View File
@@ -1,3 +0,0 @@
export default function(data) {
return "crossref";
}
-62
View File
@@ -1,62 +0,0 @@
import logo from "./distill-logo.svg";
const html = `
<style>
dt-header {
display: block;
position: relative;
height: 60px;
background-color: none;
width: 100%;
box-sizing: border-box;
z-index: 2;
color: rgba(0, 0, 0, 0.8);
}
dt-header .content {
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
height: 60px;
}
dt-header a {
font-size: 16px;
height: 60px;
line-height: 60px;
text-decoration: none;
color: rgba(0, 0, 0, 0.8);
}
dt-header svg {
width: 24px;
position: relative;
top: 4px;
margin-right: -2px;
}
dt-header svg path {
fill: none;
stroke: black;
stroke-width: 1;
stroke-linejoin: round;
}
dt-header .logo {
font-size: 16px;
font-weight: 300;
}
dt-header .nav {
float: right;
}
dt-header .nav a {
font-size: 14px;
}
</style>
<div class="content l-page">
<a href="/" class="logo">
${logo}
Distill
</a>
<div class="nav">
</div>
</div>
`
export default function(dom, data) {
dom.querySelector('dt-header').innerHTML = html;
}
-20
View File
@@ -1,20 +0,0 @@
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);
}
}
-95
View File
@@ -1,95 +0,0 @@
.l-body,
.l-page,
dt-article > * {
margin-left: 24px;
margin-right: 24px;
box-sizing: border-box;
}
@media(min-width: 768px) {
.l-body,
.l-page,
dt-article > * {
margin-left: 72px;
margin-right: 72px;
}
}
@media(min-width: 1080px) {
.l-body,
dt-article > * {
margin-left: calc(50% - 984px / 2);
width: 648px;
}
.l-body-outset,
dt-article .l-body-outset {
margin-left: calc(50% - 984px / 2 - 24px);
width: calc(648px + 48px);
}
.l-middle,
dt-article .l-middle {
width: 816px;
margin-left: calc(50% - 984px / 2);
}
.l-page,
dt-article .l-page {
width: 984px;
margin-left: auto;
margin-right: auto;
}
.l-page-outset,
dt-article .l-page-outset {
width: 1080px;
margin-left: auto;
margin-right: auto;
}
.l-screen,
dt-article .l-screen {
margin-left: auto;
margin-right: auto;
width: auto;
}
.l-screen-inset,
dt-article .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 - 960px) / 2);
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);
}
.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-page,
dt-article .side.l-page {
clear: both;
float: right;
margin-top: 0;
margin-left: 48px;
margin-right: calc((100vw - 984px) / 2);
width: calc(960px / 2 - 48px);
}
}
-6694
View File
File diff suppressed because it is too large Load Diff
-1
View File
File diff suppressed because one or more lines are too long
+188
View File
@@ -0,0 +1,188 @@
<!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&thinsp;&mdash;&thinsp;dash -- here it is.</p>
</d-abstract>
<p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p>
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for diving.</p>
<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>
+232
View File
@@ -0,0 +1,232 @@
<!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 owners possessive. Test for “quoting a passage.” And another sentence. Or two. Some flopping fins; for diving.</p>
<p>Heres a test of an inline equation <d-math>c = a^2 + b^2</d-math>. And then theres 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, heres 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>Heres 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 &lt; n:
print(a, end=' ')
a, b = b, a+b
</d-code>
<p>Thats 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>
+216 -35
View File
@@ -1,39 +1,220 @@
<!doctype html>
<meta charset="utf8">
<script src="../dist/template.js"></script>
<script type="text/front-matter">
title: Article Title
description: Description of the post
published: Jan 10, 2017
authors:
- Chris Olah: http://colah.github.io
- Shan Carter: http://shancarter.com
affiliations:
- Google Brain: http://g.co/brain
- Google Brain: http://g.co/brain
</script>
<head>
<meta charset="utf8">
<script src="../dist/template.v2.js"></script>
<dt-header></dt-header>
<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.</p>
<p>We can also cite <dt-cite key="gregor2015draw"></dt-cite> external publications.</p>
</dt-article>
<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>
<script type="text/bibliography">
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015}
}
</script>
<dt-appendix>
<h3>Contributions</h3>
<p>List of who did what</p>
</dt-appendix>
<dt-footer></dt-footer>
<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&thinsp;&mdash;&thinsp;dash -- here it is.</p>
</d-abstract>
<p>This is the first paragraph of the article. Test a long&thinsp;&mdash;&thinsp;dash -- here it is.</p>
<p>Test for owner's possessive. Test for "quoting a passage." And another sentence. Or two. Some flopping fins; for diving.</p>
<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>
<p>
Math can also be quite involved:
<d-math block>
f(x) = \int_{-\infty}^\infty\hat f(\xi)\,e^{2 \pi i \xi x}\,d\xi
</d-math>
<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>
</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></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>
<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>
<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>
+110 -33
View File
@@ -11,34 +11,34 @@
.fake-img p {
font-family: monospace;
color: white;
text-align: center;
text-align: left;
margin: 12px 0;
text-align: center;
font-size: 16px;
}
</style>
<dt-header></dt-header>
<dt-article>
<h1>How to Create a Distill Article</h1>
<h2>A collection of examples and best practices for creating interactive explanatory articles using the Distill web framework</h2>
<p>Distill ships with a CSS framework and a collection of custom web components that make building interactive academic articles easier than with raw HTML, CSS and JavaScript. This reference article details several examples and best practices for how to use both frameworks.</p>
<hr>
<h2>Getting Started</h2>
<p>Here is the smallest distill post.</p>
<p>Distill ships with a CSS framework and a collection of custom web components that make building interactive academic articles easier than with raw HTML, CSS and JavaScript. At its simplest, each distill post is just a single HTML file with one special script tag.</p>
<dt-code block language="html">
&lt;!doctype html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="../dist/template.min.js"&gt;&lt;/script&gt;
&lt;script src="http://distill.pub/template.js"&gt;&lt;/script&gt;
&lt;dt-article&gt;
&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/dt-article&gt;
</dt-code>
<p>A typical distill post will be quite a bit longer than this though. Below is a more complete example. Dont worry if some of the tags dont make sense, theyre all documented further in this post.</p>
<p>This script tag will modify your post in your browser, adding the distill styling and functionality. When we publish your article, we will bake in these transformations, but during development its handy to be able to preview it locally (It even works without a web server).</p>
<p>A typical distill post will be quite a bit longer than the one above. Below is a more complete example. Dont worry if some of the tags dont make sense, theyre all documented further in this post.</p>
<dt-code block language="html">
&lt;!doctype html&gt;
&lt;meta charset="utf-8"&gt;
&lt;script src="../dist/template.min.js"&gt;&lt;/script&gt;
&lt;script src="http://distill.pub/template.js"&gt;&lt;/script&gt;
&lt;script type="text/front-matter"&gt;
title: Article Title
@@ -60,16 +60,20 @@
&lt;p&gt;We can also cite &lt;dt-cite key="gregor2015draw"&gt;&lt;/dt-cite&gt; external publications.&lt;/p&gt;
&lt;/dt-article&gt;
&lt;dt-appendix&gt;
&lt;/dt-appendix&gt;
&lt;script type="text/bibliography"&gt;
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015}
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf}
}
&lt;/script&gt;
</dt-code>
<hr>
<!-- <hr>
<h2>Markdown</h2>
<p>Markdown is supported as an alternative to html for the <dt-code language="html">&lt;dt-article&gt;</dt-code> element. </p>
<dt-code block language="html">
@@ -85,7 +89,29 @@
&lt;/dt-article&gt;
&lt;script type="text/bibliography"&gt;&lt;/script&gt;
</dt-code>
<p>We use <a href="https://github.com/chjj/marked">marked</a> as the rendering engine, with <a href="https://help.github.com/articles/basic-writing-and-formatting-syntax/">github flavored markdown</a> and <a href="https://daringfireball.net/projects/smartypants/">smartypants</a> enabled. In development mode the markdown is translated in the client after the dom content has loaded, but when published, the translation is precompiled.</p>
<p>We use <a href="https://github.com/chjj/marked">marked</a> as the rendering engine, with <a href="https://help.github.com/articles/basic-writing-and-formatting-syntax/">github flavored markdown</a> and <a href="https://daringfireball.net/projects/smartypants/">smartypants</a> enabled. In development mode the markdown is translated in the client after the dom content has loaded, but when published, the translation is precompiled.</p> -->
<hr>
<h2>Project Structure</h2>
<p>Because all the templating is delivered via a script tag, you are generally free to develop however you are most comfortable. The only requirements are that each article must be its own Github repository. The simplest setup would be a repository that contained a single HTML file, along with any additional assets, like images or javascript files. Note, in this default setup, all files in the root of the repository will be published. Note, also, in this configuration you generally will not even need to run a static local webserver. You can just open the <dt-code>index.html</dt-code> file in your browser to preview.</p>
<dt-code block language="html">
image.jpg
index.html
script.js
</dt-code>
<p>If you have a more complicated build process, or have files you dont want published, put your output in a <dt-code>public</dt-code> folder and we will only publish its contents.</p>
<dt-code block language="html">
build/
_index.html
package.json
public/
index.html
image.jpg
</dt-code>
<hr>
<h2>Front Matter</h2>
<p>Youll need to describe some data about you post — title, description, authors, etc. For this use the <dt-code language="html">&lt;script type="text/front-matter"&gt;</dt-code> tag.</p>
@@ -109,33 +135,45 @@
<h2>Citations</h2>
<p>Bibtex is the supported way of making academic citations. You first need have a global definition of all your possible citations. For this well use the <dt-code language="html">&lt;script type="text/bibliography"&gt;</dt-code> element.</p>
<dt-code block language="html">
&lt;script type="text/bibliography""&gt;
&lt;script type="text/bibliography"&gt;
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015}
}
@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}
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf},
}
&lt;/script&gt;
</dt-code>
<p>(We strongly encourage you to populate the <dt-code>url</dt-code> bibtex field where possible so that we can provide links for citations.)</p>
<!-- <p>Like with the <dt-code language="html">&lt;script type="text/front-matter"&gt;</dt-code> element, you can alternatively reference an external file with the <dt-code>src</dt-code> attribute. If no <dt-code language="html">&lt;script type="text/bibliography"&gt;</dt-code> element is found on the page, a request will automatically be made for <dt-code>bibliography.bib</dt-code>. In production, these files will be inlined into the document.</p>
<dt-code block language="html">
&lt;script type="text/bibliography" src="bibliography.bib"&gt;&lt;/script&gt;
</dt-code> -->
<p>Citations are then used in the article body with the <dt-code language="html">&lt;dt-cite&gt;</dt-code> tag. The <dt-code>article</dt-code> attribute is a reference to the id provided in the bibiography.</p>
<p>Citations are then used in the article body with the <dt-code language="html">&lt;dt-cite&gt;</dt-code> tag. The <dt-code>key</dt-code> attribute is a reference to the id provided in the bibiography. The <dt-code>key</dt-code> attribute can take multiple ids, separated by commas.</p>
<dt-code block language="html">
&lt;dt-cite ket="gregor2015draw"&gt;&lt;/dt-cite&gt;
&lt;dt-cite key="gregor2015draw"&gt;&lt;/dt-cite&gt;
</dt-code>
<script type="text/bibliography">
@article{gregor2015draw,
title={DRAW: A recurrent neural network for image generation},
author={Gregor, Karol and Danihelka, Ivo and Graves, Alex and Rezende, Danilo Jimenez and Wierstra, Daan},
journal={arXivreprint arXiv:1502.04623},
year={2015},
url={https://arxiv.org/pdf/1502.04623.pdf},
}
</script>
<p>The citation is presented inline like this: <dt-cite key="gregor2015draw"></dt-cite> (a number that displays more information on hover). If you have an appendix, a bibliography is automatically created and populated in it.</p>
<p>Distill chose a numerical inline citation style to improve readability of citation dense articles and because many of the benefits of longer citations are obviated by dispalying more information on hover. However, we consider it good style to mention author last names if you discuss something at length and it fits into the flow well -- the authors are human and it's nice for them to have the community associate them with their work.</p>
<hr>
<h2>Footnotes</h2>
<p>Just wrap the text you would like to show up in a footnote in a <dt-code language="html">&lt;dt-fn&gt;</dt-code> tag. The number of the footnote will be automatically generated. <dt-fn>This text will be shown on hover.</dt-fn></p>
<dt-code block language="html">
&lt;dt-fn&gt;This will become a hoverable footnote.&lt;/dt-fn&gt;
</dt-code>
<dt-footnote-body ref="blah"></dt-footnote-body>
<hr>
<h2>Code Blocks</h2>
@@ -149,30 +187,69 @@
&lt;/dt-code&gt;
</dt-code>
<!-- <hr>
<h2>Footnotes</h2>
<p>This is a <dt-footnote ref="blah" /></p>
<dt-footnote-body ref="blah"></dt-footnote-body>
<!--
<hr>
<h2>Math</h2> -->
<h2>Math</h2>
-->
<hr>
<h2>Layouts</h2>
<p>The main text column is referred to as the body. It is the assumed layout of any direct descendents of the <code>dt-article</code> element.</p>
<div class="fake-img l-body"><p>.l-body</p></div>
<p>For images you want to display a little larger, try these:</p>
<div class="fake-img l-middle"><p>.l-middle</p></div>
<div class="fake-img l-page"><p>.l-page</p></div>
<p>Occasionally youll want to use the full browser width. For this, use screen. You can also inset the element a little from the edge of the browser by appending, you guessed it, <code>inset</code>.</p>
<p>All of these have an <dt-code>outset</dt-code> variant if you want to poke out from the body text a little bit. For instance:</p>
<div class="fake-img l-body-outset"><p>.l-body-outset</p></div>
<div class="fake-img l-middle-outset"><p>.l-middle-outset</p></div>
<div class="fake-img l-page-outset"><p>.l-page-outset</p></div>
<p>Occasionally youll want to use the full browser width. For this, use <dt-code>.l-screen</dt-code>. You can also inset the element a little from the edge of the browser by using the inset variant.</p>
<div class="fake-img l-screen"><p>.l-screen</p></div>
<div class="fake-img l-screen-inset"><p>.l-screen-inset</p></div>
<p>Often you want to position smaller images so as not to completely interrupt the flow of your text. Or perhaps you want to put some text in the margin as an aside or to signal that its optional content. For these cases well use the float-based <code>.side</code> layouts.</p>
<p>Often you want to position smaller images so as not to completely interrupt the flow of your text. Or perhaps you want to put some text in the margin as an aside or to signal that its optional content. For these cases well use the float-based layouts.</p>
<div class="fake-img l-body side"><p>.l-body.side</p></div>
<div class="fake-img l-middle side"><p>.l-middle.side</p></div>
<div class="fake-img l-page side"><p>.l-page.side</p></div>
<p>They are all floated to the right and anchored to the right-hand edge of the position you specify. By default, each will take up approximately half of the width of the standard layout position, but you can override the width with a more specific selector. </p>
<div class="fake-img l-gutter"><p>.l-gutter</p></div>
<p>The final layout is for marginalia, asides, and footnotes. It does not interrupt the normal flow of <code>.l-body</code> sized text except on mobile screen sizes.</p>
<p>You can also use an alternate centered layout by adding a <dt-code>centered</dt-code> class to the <dt-code>dt-article</dt-code> element.</p>
<dt-code block language="html">
&lt;dt-article class="centered"&gt;
&lt;h1&gt;Hello World&lt;/h1&gt;
&lt;/dt-article&gt;
</dt-code>
<p>You can toggle it on this article by <a onclick="document.querySelector('dt-article').classList.toggle('centered');">clicking here</a></p>
<section class="centered">
</section>
<hr>
<h2>Appendix</h2>
<p>An appendix can be added after your article, using the <dt-code language="html">&lt;dt-appendix&gt;</dt-code> tag.</p>
<dt-code block language="html">
&lt;dt-article&gt;
...
&lt;/dt-article&gt;
&lt;dt-appendix&gt;
&lt;h3&gt;Appendix Section Title&lt;/h3&gt;
&lt;p&gt;section content&lt;p&gt;
&lt;/dt-appendix&gt;
</dt-code>
<p>You may wish to include the following sections in your appendix:</p>
<ul>
<li><b>Acknowledgments</b>: This is a place to recognize people and institutions. It may also be a good place to acknowledge and cite software that makes your work possible (eg. TensorFlow, OpenAI Gym).</li>
<li><b>Author Contributions</b>: We strongly encourage you to include an author contributions statement briefly describing what each author did.</li>
</ul>
<hr>
<h2>And Youre Off</h2>
<p>That should do it. If you have any questions or bugs to file, feel free to <a href="https://github.com/distillpub/template/issues/new">open an issue on GitHub</a>.</p>
<!--
<hr>
<h2>Including External Files</h2> -->
</dt-article>
<dt-footer></dt-footer>
-62
View File
@@ -1,62 +0,0 @@
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/expand-data";
import meta from "./components/meta";
import header from "./components/header";
import appendix from "./components/appendix";
import footer from "./components/footer";
import citation from "./components/citation";
import markdown from "./components/markdown";
import code from "./components/code";
import generateCrossref from "./components/generate-crossref";
function renderImmediately(dom) {
html(dom);
styles(dom);
}
function renderOnLoad(dom, data) {
frontMatter(dom, data);
bibliography(dom, data);
expandData(dom, data);
meta(dom, data);
header(dom, data);
appendix(dom, data);
footer(dom, data);
markdown(dom, data);
code(dom, data);
citation(dom, data);
}
// If we are in a browser, render automatically.
if(window && window.document) {
let data = data || {};
renderImmediately(window.document);
window.document.addEventListener("DOMContentLoaded", (event) => {
renderOnLoad(window.document, data);
console.log("final data:");
for (var k in data) {console.log(" ", k, ": ", data[k])}
});
}
// For node
function render(dom, data) {
renderImmediately(dom);
renderOnLoad(dom, data);
}
export {render as render};
export {html as html};
export {styles as styles};
export {frontMatter as frontMatter};
export {bibliography as bibliography};
export {meta as meta};
export {header as header};
export {appendix as appendix};
export {footer as footer};
export {citation as citation};
export {markdown as markdown};
export {code as code};
export {generateCrossref as generateCrossref};
+5763
View File
File diff suppressed because it is too large Load Diff
+30 -15
View File
@@ -1,38 +1,53 @@
{
"name": "distill-template",
"version": "0.0.10",
"version": "2.0.0",
"description": "Template for creating Distill articles.",
"main": "dist/template.js",
"scripts": {
"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",
"test": "mocha",
"lint": "eslint",
"build": "rollup -c rollup.config.js"
},
"repository": {
"url": "git+https://github.com/distillpub/distill-template.git",
"type": "git"
},
"bugs": {
"url": "https://github.com/distillpub/distill-template/issues"
},
"homepage": "https://github.com/distillpub/distill-template#readme",
"devDependencies": {
"bibtex-parse-js": "^0.0.23",
"chai": "^3.5.0",
"commander": "^2.9.0",
"eslint": "^4.3.0",
"eslint-config-google": "^0.9.1",
"js-yaml": "^3.7.0",
"jsdom": "^9.9.1",
"jsdom": "^9.10.0",
"marked": "^0.3.6",
"mocha": "^3.2.0",
"prismjs": "^1.6.0",
"rollup": "^0.36.4",
"rollup-plugin-buble": "^0.14.0",
"rollup": "latest",
"rollup-plugin-babili": "^3.1.0",
"rollup-plugin-commonjs": "^7.0.0",
"rollup-plugin-livereload": "^0.3.1",
"rollup-plugin-copy": "^0.2.3",
"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"
"rollup-watch": "^2.5.0",
"webpack": "^2.2.1"
},
"dependencies": {
"@webcomponents/webcomponentsjs": "^1.0.7",
"assert": "^1.4.1",
"d3-time-format": "^2.0.3",
"intersection-observer": "^0.4.0",
"jsdom-wc": "^11.0.0-alpha-1",
"katex": "^0.7.1"
}
}
+35
View File
@@ -0,0 +1,35 @@
import resolve from 'rollup-plugin-node-resolve';
import string from 'rollup-plugin-string';
import commonjs from 'rollup-plugin-commonjs';
const componentsConfig = {
entry: 'src/components.js',
targets: [{format: 'umd', moduleName: 'dl', dest: 'dist/template.v2.js'}],
};
const transformsConfig = {
entry: 'src/transforms.js',
targets: [{format: 'umd', moduleName: 'dl', dest: 'dist/transforms.js'}],
};
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);
export default [
componentsConfig,
transformsConfig,
];
+11 -36
View File
@@ -1,39 +1,14 @@
import buble from 'rollup-plugin-buble';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import liveReload from 'rollup-plugin-livereload';
import serve from 'rollup-plugin-serve';
import uglify from 'rollup-plugin-uglify';
import string from 'rollup-plugin-string';
import configs from './rollup.config.dev';
import babili from 'rollup-plugin-babili';
const PORT = 8080;
console.log(`open http://localhost:${PORT}/`);
const [componentsConfig, transformsConfig] = configs;
export default {
entry: 'index.js',
componentsConfig.plugins.push(babili({
comments: false, // means: *remove* comments
sourceMap: true,
targets: [
{
format: 'umd',
moduleName: 'dl',
dest: `dist/template.js`,
}
],
plugins: [
resolve({
jsnext: true,
browser: true,
}),
string({
include: ["**/*.svg", "**/*.html", "**/*.css", "**/*.base64"]
}),
buble({
exclude: 'node_modules',
target: { chrome: 52, safari: 8, edge: 13, firefox: 48, }
}),
commonjs(),
// uglify(),
// liveReload(),
serve({port: PORT}),
]
};
}));
export default [
componentsConfig,
transformsConfig,
];

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

+3
View File
@@ -0,0 +1,3 @@
<svg viewBox="-607 419 64 64">
<path d="M-573.4,478.9c-8,0-14.6-6.4-14.6-14.5s14.6-25.9,14.6-40.8c0,14.9,14.6,32.8,14.6,40.8S-565.4,478.9-573.4,478.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 163 B

+44
View File
@@ -0,0 +1,44 @@
/* Static styles and other modules */
import './styles/styles';
/* Components */
import { Abstract } from './components/d-abstract';
import { Acknowledgements } from './components/d-acknowledgements';
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 { 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 { DMath } from './components/d-math';
import { References } from './components/d-references';
import { Title } from './components/d-title';
import { TOC } from './components/d-toc';
import { Figure } from './components/d-figure';
const components = [
Abstract, Acknowledgements, Appendix, Article, Bibliography,
Byline, Cite, Code, Footnote, FootnoteList, FrontMatter, DMath,
References, Title, TOC, Figure,
];
/* 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 distillComponents = [
DistillHeader, DistillAppendix, DistillFooter,
];
function defineComponents() {
const allComponents = components.concat(distillComponents);
for (const component of allComponents) {
customElements.define(component.is, component);
}
}
defineComponents();
+20
View File
@@ -0,0 +1,20 @@
import { Template } from '../mixins/template';
import { body } from '../helpers/layout';
const T = Template('d-abstract', `
<style>
:host {
display: block;
font-size: 23px;
line-height: 1.7em;
margin-bottom: 140px;
}
${body('d-abstract')}
</style>
<slot></slot>
`);
export class Abstract extends T(HTMLElement) {
}
+23
View File
@@ -0,0 +1,23 @@
import { Template } from '../mixins/template';
const T = Template('d-acknowledgements', `
<style>
::slotted(h3) {
font-size: 15px;
font-weight: 500;
margin-top: 20px;
margin-bottom: 0;
color: rgba(0,0,0,0.65);
line-height: 1em;
}
::slotted(*) a {
color: rgba(0, 0, 0, 0.6);
}
</style>
<slot></slot>
`);
export class Acknowledgements extends T(HTMLElement) {
}
+33
View File
@@ -0,0 +1,33 @@
import { Template } from '../mixins/template';
import { body } from '../helpers/layout';
const T = Template('d-appendix', `
<style>
:host {
box-sizing: border-box;
display: block;
width: 100%;
font-size: 13px;
line-height: 1.7em;
margin-bottom: 0;
border-top: 1px solid rgba(0,0,0,0.1);
color: rgba(0,0,0,0.5);
background: hsl(180, 5%, 98%);
padding-top: 36px;
padding-bottom: 48px;
}
${body('.content')}
</style>
<div class='content'>
<slot></slot>
</div>
`, true);
export class Appendix extends T(HTMLElement) {
}
+56
View File
@@ -0,0 +1,56 @@
import { Template } from '../mixins/template';
import { Controller } from '../controller';
const T = Template('d-article', `
<style></style>
`, false);
// export function addInferableTags(dom, frontMatter) {
// const title = frontMatter.title;
// if (title) {
// const titleTag = document.querySelector()
//
// }
// }
const isOnlyWhitespace = /^\s*$/;
export class Article extends T(HTMLElement) {
constructor() {
super();
new MutationObserver( (mutations) => {
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
switch (addedNode.nodeName) {
case 'HR':
console.warn('Use of <hr> tags in distill articles is discouraged as they interfere with layout! To separate sections, please just use h2 or h3 tags.');
break;
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() {
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!');
}
}
}
}
+101
View File
@@ -0,0 +1,101 @@
import { Template } from '../mixins/template';
import { parseBibtex } from '../helpers/bibtex';
import { bibliography_cite } from '../helpers/citation';
export const templateString = `
<style>
.references {
font-size: 12px;
line-height: 20px;
}
.title {
font-weight: 600;
}
ol {
padding: 0 0 0 18px;
}
li {
margin-bottom: 12px;
}
h3 {
font-size: 15px;
font-weight: 500;
margin-top: 20px;
margin-bottom: 0;
color: rgba(0,0,0,0.65);
line-height: 1em;
}
a {
color: rgba(0, 0, 0, 0.6);
}
</style>
<h3>References</h3>
<ol class='references' id='references-list' ></ol>
`;
const T = Template('d-bibliography', templateString);
export function parseBibliography(element) {
if (element.firstElementChild && element.firstElementChild.tagName === 'SCRIPT') {
const bibtex = element.firstElementChild.textContent;
const bibliography = parseBibtex(bibtex);
return bibliography;
}
}
export function renderBibliography(element, entries) {
if (entries.size) {
element.host.style.display = 'initial';
let list = element.querySelector('#references-list');
list.innerHTML = '';
for (const [key, entry] of entries) {
const listItem = document.createElement('li');
listItem.id = key;
listItem.innerHTML = bibliography_cite(entry);
list.appendChild(listItem);
}
} else {
element.host.style.display = 'none';
}
}
export class Bibliography extends T(HTMLElement) {
constructor() {
super();
// set up mutation observer
const options = {childList: true, characterData: true, subtree: true};
const observer = new MutationObserver( () => {
observer.disconnect();
this.parseIfPossible();
observer.observe(this, options);
});
this.parseIfPossible();
// ...and listen for changes
observer.observe(this, options);
}
parseIfPossible() {
if (this.firstElementChild && this.firstElementChild.tagName === 'SCRIPT') {
const newBibtex = this.firstElementChild.textContent;
if (this.bibtex !== newBibtex) {
this.bibtex = newBibtex;
const bibliography = parseBibtex(this.bibtex);
this.notify(bibliography);
}
}
}
notify(bibliography) {
const options = { detail: bibliography, bubbles: true };
const event = new CustomEvent('onBibliographyChanged', options);
this.dispatchEvent(event);
}
set entries(newEntries) {
renderBibliography(this.root, newEntries);
}
}
+158
View File
@@ -0,0 +1,158 @@
import { Template } from '../mixins/template';
import { page } from '../helpers/layout';
const T = Template('d-byline', `
<style>
:host {
box-sizing: border-box;
font-size: 13px;
line-height: 20px;
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.6);
padding-top: 20px;
padding-bottom: 20px;
}
${page('.byline')}
d-article.centered {
text-align: center;
}
a,
d-article a {
color: rgba(0, 0, 0, 0.8);
text-decoration: none;
border-bottom: none;
}
d-article a:hover {
text-decoration: underline;
border-bottom: none;
}
.authors {
text-align: left;
}
.name {
font-weight: 600;
display: inline;
text-transform: uppercase;
}
.affiliation {
display: inline;
}
.date {
display: block;
text-align: left;
margin-top: 8px;
}
.year, .month {
display: inline;
}
.citation {
display: block;
text-align: left;
}
.citation div {
display: inline;
}
@media screen and (min-width: 768px), print {
d-byline {
border-bottom: none;
}
a:hover {
color: rgba(0, 0, 0, 0.9);
}
.authors {
display: inline-block;
}
.author {
display: inline-block;
margin-right: 12px;
/*padding-left: 20px;*/
/*border-left: 1px solid #ddd;*/
}
.affiliation {
display: block;
}
.author:last-child {
margin-right: 0;
}
.name {
display: block;
}
.date {
border-left: 1px solid rgba(0, 0, 0, 0.1);
padding-left: 15px;
margin-left: 15px;
margin-top: 0;
display: inline-block;
}
.year, .month {
display: block;
}
.citation {
align-self: flex-end;
border-left: 1px solid rgba(0, 0, 0, 0.15);
padding-left: 15px;
margin-left: 15px;
display: inline-block;
}
.citation div {
display: block;
}
.byline {
display: flex;
min-height: 40px;
}
}
</style>
<div class='byline'>
</div>
`, true);
export function bylineTemplate(frontMatter) {
return `
<div class="authors">
${frontMatter.authors.map( author => `<div class="author">
${author.personalURL ?
`<a class="name" href="${author.personalURL}">${author.name}</a>`
:
`<div class="name">${author.name}</div>`
}
${author.affiliationURL ?
`<a class="affiliation" href="${author.affiliationURL}">${author.affiliation}</a>`
:
`<div class="affiliation">${author.affiliation}</div>`
}
</div>`).join('\n')}
</div>
<div class="date">
<div class="month">${frontMatter.publishedMonth}. ${frontMatter.publishedDay}</div>
<div class="year">${frontMatter.publishedYear}</div>
</div>
<a class="citation" href="#citation">
<div>Citation:</div>
<div>${frontMatter.concatenatedAuthors}, ${frontMatter.publishedYear}</div>
</a>
`;
}
export class Byline extends T(HTMLElement) {
set frontMatter(frontMatter) {
const container = this.root.querySelector('.byline');
container.innerHTML = bylineTemplate(frontMatter);
}
}
+163
View File
@@ -0,0 +1,163 @@
import { Template } from '../mixins/template';
import { hover_cite } from '../helpers/citation';
import { HoverBox } from '../helpers/hover-box';
const T = Template('d-cite', `
<style>
.citation {
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;
}
</style>
<div id="hover-box" class="dt-hover-box">
</div>
<span id="citation-" class="citation">
<slot></slot>
<span class="citation-number"></span>
</span>
`);
export function collectCitations(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 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.`)
// }
// }
}
+74
View File
@@ -0,0 +1,74 @@
import Prism from 'prismjs';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-clike';
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;
background: white;
border-left: 3px solid rgba(0, 0, 0, 0.05);
padding: 0 0 0 24px;
}
${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);
}
}
+123
View File
@@ -0,0 +1,123 @@
// 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'; }
constructor() {
super();
this._ready = false;
this._onscreen = false;
this._offscreen = true;
}
connectedCallback() {
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) {
const viewportHeight = window.innerHeight;
const margin = Math.floor(2 * viewportHeight);
Figure._marginObserver = new IntersectionObserver(
Figure.didObserveMarginIntersection, {
rootMargin: margin + 'px 0px ' + margin + 'px 0px', threshold: 0.01,
});
}
return Figure._marginObserver;
}
static didObserveMarginIntersection(entries) {
for (const entry of entries) {
const figure = entry.target;
if (entry.isIntersecting && !figure._ready) {
figure.ready();
}
}
}
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) {
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
setTimeout(() => {
if (this._ready && eventName === 'ready') {
this.ready();
}
if (this._onscreen && eventName === 'onscreen') {
this.onscreen();
}
}, 1);
}
// Custom Events
ready() {
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);
}
}
+74
View File
@@ -0,0 +1,74 @@
import { Template } from '../mixins/template';
const T = Template('d-footnote-list', `
<style>
ol {
padding: 0 0 0 18px;
}
li {
margin-bottom: 12px;
}
h3 {
font-size: 15px;
font-weight: 500;
margin-top: 20px;
margin-bottom: 0;
color: rgba(0,0,0,0.65);
line-height: 1em;
}
a {
color: rgba(0, 0, 0, 0.6);
}
a.footnote-backlink {
color: rgba(0,0,0,0.3);
padding-left: 0.5em;
}
</style>
<h3>Footnotes</h3>
<ol></ol>
`);
export class FootnoteList extends T(HTMLElement) {
connectedCallback() {
this.list = this.root.querySelector('ol');
// footnotes list is initially hidden
this.root.host.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.host.style.display = 'initial';
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.shadowRoot.host.style.display = 'none';
}
}
}
+63
View File
@@ -0,0 +1,63 @@
import { Template } from '../mixins/template.js';
import { HoverBox } from '../helpers/hover-box';
// import { Store } from './store';
const T = Template('d-footnote', `
<style>
d-math[block] {
display: block;
}
</style>
<div id="hover-box" class="dt-hover-box">
<slot id="slot"></slot>
</div>
<sup><span id="fn-" data-hover-ref="" style="cursor:pointer"></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');
// 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;
+40
View File
@@ -0,0 +1,40 @@
import ymlParse from 'js-yaml';
export function parseFrontmatter(element) {
const scriptTag = element.querySelector('script');
if (scriptTag) {
const yml = scriptTag.textContent;
const data = ymlParse.safeLoad(yml);
return data;
} 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};
const observer = new MutationObserver( (entries) => {
for (const entry of entries) {
if (entry.target.nodeName === 'SCRIPT') {
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);
}
}
+60
View File
@@ -0,0 +1,60 @@
/*global katex */
import { Mutating } from '../mixins/mutating.js';
import { Template } from '../mixins/template.js';
const katexJSURL = 'https://distill.pub/third-party/katex/katex.min.js';
const katexCSSTag = '<link rel="stylesheet" href="https://distill.pub/third-party/katex/katex.min.css" crossorigin="anonymous">';
const T = Template('d-math', `
<style>
d-math[block] {
display: block;
}
</style>
${katexCSSTag}
<span id="katex-container"></span>
`);
// DMath, not Math, because that's a JS built-in
export class DMath extends Mutating(T(HTMLElement)) {
static katexLoadedCallback() {
const mathTags = document.querySelectorAll('d-math');
for (const mathTag of mathTags) {
mathTag.renderContent();
}
}
connectedCallback() {
if (!DMath.katexAdded) {
// 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);
// css tag can use this convenience function
document.head.insertAdjacentHTML('beforeend', katexCSSTag);
DMath.katexAdded = true;
}
}
renderContent() {
if (typeof katex !== 'undefined') {
const options = { displayMode: this.hasAttribute('block') };
const container = this.root.querySelector('#katex-container');
katex.render(this.textContent, container, options);
}
}
}
DMath.katexAdded = false;
window.DMath = DMath; // TODO: check if this can be removed, or if we should expose a distill global
+13
View File
@@ -0,0 +1,13 @@
import { Template } from '../mixins/template';
const T = Template('d-references', `
<style>
d-references {
display: block;
}
</style>
`, false);
export class References extends T(HTMLElement) {
}
+62
View File
@@ -0,0 +1,62 @@
import { Template } from '../mixins/template';
import { page } from '../helpers/layout';
const T = Template('d-title', `
<style>
:host {
box-sizing: border-box;
display: block;
width: 100%;
margin-bottom: 64px;
}
::slotted(h1) {
padding-top: 16px;
padding-bottom: 16px;
margin: 0;
line-height: 1.3;
font-size: 32px;
font-weight: 700;
}
::slotted(h2) {
border-bottom: none !important;
}
@media screen and (min-width: 768px), print {
::slotted(h1) {
font-size: 42px;
padding-bottom: 32px;
}
}
@media(min-width: 1024px) {
::slotted(h1) {
padding-top: 64px;
padding-bottom: 32px;
font-size: 48px;
}
}
@media(min-width: 1280px) {
::slotted(h1) {
padding-top: 96px;
padding-bottom: 32px;
font-size: 56px;
}
}
d-byline {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
${page('::slotted(h1), ::slotted(h2)')}
</style>
<slot></slot>
`);
export class Title extends T(HTMLElement) {
}
+13
View File
@@ -0,0 +1,13 @@
import {Template} from '../mixins/template';
const T = Template('d-toc', `
<style>
d-toc {
display: block;
}
</style>
`, false);
export class TOC extends T(HTMLElement) {
}
+144
View File
@@ -0,0 +1,144 @@
import { FrontMatter } from './front-matter';
import { collectCitations } from './components/d-cite';
import { parseFrontmatter } from './components/d-front-matter';
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 = collectCitations();
frontMatter.citationsCollected = true;
for (const waitingCallback of Controller.waitingOn.citations.slice()) {
waitingCallback();
}
// update bibliography
const bibliographyTag = document.querySelector('d-bibliography');
const bibliographyEntries = new Map(frontMatter.citations.map( citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
}));
bibliographyTag.entries = 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) {
const bibliographyTag = event.target;
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;
}
const entries = new Map(frontMatter.citations.map( citationKey => {
return [citationKey, frontMatter.bibliography.get(citationKey)];
}));
bibliographyTag.entries = 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;
frontMatter.mergeFromYMLFrontmatter(data);
const appendix = document.querySelector('distill-appendix');
if (appendix) {
appendix.frontMatter = frontMatter;
}
const byline = document.querySelector('d-byline');
if (byline) {
byline.frontMatter = frontMatter;
}
},
DOMContentLoaded() {
// console.debug('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 = collectCitations();
frontMatter.citationsCollected = true;
for (const waitingCallback of Controller.waitingOn.citations.slice()) {
waitingCallback();
}
const footnotesList = document.querySelector('d-footnote-list');
if (footnotesList) {
const footnotes = document.querySelectorAll('d-footnote');
footnotesList.footnotes = footnotes;
}
}
}, // listeners
}; // Controller
@@ -0,0 +1,64 @@
import { serializeFrontmatterToBibtex } from '../helpers/bibtex';
const styles = `
<style>
distill-appendix h3 {
font-size: 15px;
font-weight: 500;
margin-top: 20px;
margin-bottom: 0;
color: rgba(0,0,0,0.65);
line-height: 1em;
}
distill-appendix a {
color: rgba(0, 0, 0, 0.6);
}
distill-appendix ol,
distill-appendix ul {
padding-left: 24px;
}
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;
}
</style>
`;
export function appendixTemplate(frontMatter) {
return `
${styles}
<h3 id="updates-and-corrections">Updates and Corrections</h3>
<p><a href="">View all changes</a> to this article since it was first published. If you see mistakes or want to suggest changes, please <a href="${frontMatter.githubUrl + '/issues/new'}">create an issue on GitHub</a>. </p>
<h3 id="reuse">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> 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 dont fall under this license and can be recognized by a note in their caption: “Figure from …”.</p>
<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>
`;
}
export class DistillAppendix extends HTMLElement {
static get is() { return 'distill-appendix'; }
set frontMatter(frontMatter) {
this.innerHTML = appendixTemplate(frontMatter);
}
}
+53
View File
@@ -0,0 +1,53 @@
import { Template } from '../mixins/template';
import logo from '../assets/distill-logo.svg';
const T = Template('distill-footer', `
<style>
:host {
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(180, 5%, 15%); /*hsl(200, 60%, 15%);*/
text-align: left;
}
.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: margin-left / body;
}
</style>
<div class='container'>
<a href="/" class="logo">
${logo}
Distill
</a> is dedicated to clear explanations of machine learning
</div>
`);
export class DistillFooter extends T(HTMLElement) {
}
+110
View File
@@ -0,0 +1,110 @@
import { Template } from '../mixins/template';
import logo from '../assets/distill-logo.svg';
const T = Template('distill-header', `
<style>
:host {
box-sizing: border-box;
display: block;
top: 0;
left: 0;
width: 100%;
height: 60px;
background-color: transparent;
z-index: ${1e6};
color: rgba(0, 0, 0, 0.8);
/*border-bottom: 1px solid rgba(0, 0, 0, 0.08);*/
/*box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);*/
}
.content {
height: 70px;
}
a {
font-size: 16px;
height: 60px;
line-height: 60px;
text-decoration: none;
color: rgba(255, 255, 255, 0.8);
padding: 22px 0;
}
a:hover {
color: rgba(255, 255, 255, 1);
}
svg {
background-color: hsl(0, 0%, 15%);;
padding: 8px;
border-radius: 12px;
width: 24px;
position: relative;
top: 16px;
left: 16px;
margin-right: 2px;
}
@media(min-width: 768px) {
svg {
top: 40px;
left: 40px;
}
}
@media(min-width: 1080px) {
:host {
height: 70px;
}
a {
height: 70px;
line-height: 70px;
padding: 28px 0;
}
.logo {
}
}
svg path {
fill: white;
stroke: rgba(255, 255, 255, 1.0);
stroke-width: 3px;
}
.logo {
font-size: 17px;
font-weight: 200;
}
.nav {
float: right;
font-weight: 300;
}
.nav a {
font-size: 12px;
margin-left: 24px;
text-transform: uppercase;
}
.name {
opacity: 0.0;
transition: opacity 0.5s
}
a:hover .name {
opacity: 1.0;
}
</style>
<div class="content l-page">
<a href="/" class="logo">
${logo}
</a>
<span class='name'>
Distill
</span>
</div>
`);
// <div class="nav">
// <a href="/faq">About</a>
// <a href="https://github.com/distillpub">GitHub</a>
// <!-- https://twitter.com/distillpub -->
// </div>
export class DistillHeader extends T(HTMLElement) {
}
@@ -0,0 +1,14 @@
export default function(dom) {
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);
}
}
+8
View File
@@ -0,0 +1,8 @@
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);
}
}
+8
View File
@@ -0,0 +1,8 @@
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);
}
}
+10
View File
@@ -0,0 +1,10 @@
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;
}
data.bibliography = parseBibliography(bibliographyTag);
}
+5
View File
@@ -0,0 +1,5 @@
import { collectCitations } from '../components/d-cite';
export default function(dom, data) {
data.citations = collectCitations(dom);
}
+11
View File
@@ -0,0 +1,11 @@
import { parseFrontmatter } from '../components/d-front-matter';
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);
Object.assign(data, extractedData);
}
+244
View File
@@ -0,0 +1,244 @@
import {timeFormat} from 'd3-time-format';
const zeroPad = n => n < 10 ? '0' + n : n;
const RFC = timeFormat('%a, %d %b %Y %H:%M:%S %Z');
const months = ['Jan', 'Feb', 'March', 'April', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
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"
}
// "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 class FrontMatter {
constructor() {
this.title = ''; // "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.publishedDate = new Date();
//
// 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',
}
// 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
mergeFromYMLFrontmatter(data) {
this.title = data.title;
this.publishedDate = new Date(data.published);
this.description = data.description;
const zipped = data.authors.map( (author, index) => [author, data.affiliations[index]]);
this.authors = zipped.map( ([authorEntry, affiliationEntry]) => {
const author = new Author();
// try to get name and personal url
switch (typeof authorEntry) {
case 'object':
author.name = Object.keys(authorEntry)[0];
author.personalURL = authorEntry[author.name];
break;
case 'string':
author.name = authorEntry;
break;
default:
throw new Error('Invalid type in frontmatter author field: ' + authorEntry);
}
// try to get affiliation name and affiliation url
switch (typeof affiliationEntry) {
case 'object':
author.affiliation = Object.keys(affiliationEntry)[0];
author.affiliationURL = affiliationEntry[author.affiliation];
break;
case 'string':
author.affiliation = affiliationEntry;
break;
default:
throw new Error('Invalid type in frontmatter affiliation field: ' + affiliationEntry);
}
return author;
});
}
//
// 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() {
return 'https://github.com/' + this.githubPath;
}
// 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());
}
// '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];
}));
}
}
+33
View File
@@ -0,0 +1,33 @@
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] = 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}}
}`;
}
+165
View File
@@ -0,0 +1,165 @@
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 ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
}
}
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 = '<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 '?';
}
}
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(' ')});
}
}
+108
View File
@@ -0,0 +1,108 @@
function make_hover_css(pos) {
const pretty = window.innerWidth > 600;
const padding = pretty? 18 : 12;
const outer_padding = pretty ? 18 : 0;
const bbox = document.querySelector('body').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(250);
});
// 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(250);
});
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(position);
this.div.setAttribute('style', css );
}
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);
}
}
+33
View File
@@ -0,0 +1,33 @@
// 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: margin-left / body;
}
`;
}
export function page(selector) {
return `${selector} {
grid-column: margin-left / page;
}
`;
}
export function screen(selector) {
return `${selector} {
grid-column: start / end;
}
`;
}
+38
View File
@@ -0,0 +1,38 @@
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
+85
View File
@@ -0,0 +1,85 @@
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;
};
};
+56
View File
@@ -0,0 +1,56 @@
/*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);
}
};
};
};
+201
View File
@@ -0,0 +1,201 @@
d-article {
color: rgba(0, 0, 0, 0.8);
padding-top: 0;
padding-bottom: 72px;
overflow: hidden;
font-size: 14px;
line-height: 1.6em;
/*border-top: 1px solid rgba(0, 0, 0, 0.2);*/
}
@media(min-width: 768px) {
d-article {
font-size: 16px;
}
}
@media(min-width: 1024px) {
d-article {
font-size: 18px;
}
}
/* H2 */
d-article h2 {
font-weight: 600;
font-size: 26px;
line-height: 1.25em;
margin-top: 16px;
margin-bottom: 24px;
padding-bottom: 24px;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
@media(min-width: 1024px) {
d-article h2 {
margin-top: 2em;
font-size: 32px;
}
}
d-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;
}
d-article h1 + h2 {
margin-top: 12px;
font-size: 32px;
}
}
/* H3 */
d-article h3 {
font-weight: 600;
font-size: 20px;
line-height: 1.4em;
margin-top: 36px;
margin-bottom: 18px;
}
d-article h1 + h3 {
margin-top: 48px;
}
@media(min-width: 1024px) {
d-article h3 {
font-size: 26px;
}
}
/* 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 {
margin-bottom: 24px;
}
d-article p b,
d-article ul b,
d-article ol b {
-webkit-font-smoothing: antialiased;
}
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 {
border: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.2);
margin-top: 60px;
margin-bottom: 60px;
}
d-article section {
margin-top: 60px;
margin-bottom: 60px;
}
/* Figure */
d-article figure {
position: relative;
margin-top: 30px;
margin-bottom: 30px;
}
@media(min-width: 1024px) {
d-article figure {
margin-top: 48px;
margin-bottom: 48px;
}
}
d-article figure img {
width: 100%;
}
d-article figure svg text,
d-article figure svg tspan {
}
d-article figure figcaption {
color: rgba(0, 0, 0, 0.6);
font-size: 12px;
line-height: 1.5em;
}
@media(min-width: 1024px) {
d-article figure figcaption {
font-size: 13px;
}
}
d-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;
}
d-article figure figcaption a {
color: rgba(0, 0, 0, 0.6);
}
/*d-article figure figcaption::before {
position: relative;
display: block;
top: -20px;
content: "";
width: 25px;
border-top: 1px solid rgba(0, 0, 0, 0.3);
}*/
d-article span.equation-mimic {
font-family: georgia;
font-size: 115%;
font-style: italic;
}
d-article figure figcaption b {
font-weight: 600;
color: rgba(0, 0, 0, 1.0);
}
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;
}
+46
View File
@@ -0,0 +1,46 @@
html {
font-size: 20px;
line-height: 1rem;
font-family: "Libre Franklin", "Helvetica Neue", sans-serif;
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%;
}
+331
View File
@@ -0,0 +1,331 @@
@supports not (display: grid) {
d-article,
d-title,
d-byline,
d-appendix,
distill-footer {
display: block;
padding: 8px;
}
}
d-article,
d-title,
d-byline,
d-appendix,
distill-footer {
display: grid;
justify-items: stretch;
grid-template-columns: [start] 8px [margin-left-outset] 8px [margin-left] 1fr [body] 0px [page] 8px [body-outset] 0px [page-outset] 8px [end];
}
@media(min-width: 768px) {
d-article,
d-title,
d-byline,
d-appendix,
distill-footer {
grid-template-columns: [start] 32px [margin-left-outset] 32px [margin-left] 3fr [body] 32px [body-outset] 1fr [page] 32px [page-outset] 32px [end];
}
}
@media(min-width: 1024px) {
d-article,
d-title,
d-byline,
d-appendix,
distill-footer {
grid-template-columns: [start] 1fr [margin-left-outset] 32px [margin-left] 672px [body] 32px [body-outset] 224px [page] 32px [page-outset] 1fr [end];
}
}
d-appendix,
d-article > d-title,
d-article > d-title > d-byline,
d-article > distill-footer {
grid-column: start / end;
}
.l-body,
d-article > * {
grid-column: margin-left / body;
}
.l-page,
d-figure {
grid-column: margin-left / page;
}
.l-body-outset {
grid-column: margin-left-outset / body-outset;
}
.l-page-outset {
grid-column: margin-left-outset / page-outset;
}
.l-screen {
grid-column: start / end;
}
.l-screen-inset {
grid-column: start / end;
padding-left: 16px;
padding-left: 16px;
}
/* Aside */
aside {
grid-column: margin-left / body;
}
@media(min-width: 768px) {
aside {
grid-column: body-outset / page;
font-size: 14px;
line-height: 1.3;
}
}
/*
.l-body,
.l-page,
.l-middle,
d-article > div,
d-article > p,
d-article > h1,
d-article > h2,
d-article > h3,
d-article > h4,
d-article > figure,
d-article > ul,
d-article > d-abstract,
d-article > d-code,
d-article > d-math,
d-article > table,
d-article section > div,
d-article section > p,
d-article section > h1,
d-article section > h2,
d-article section > h3,
d-article section > h4,
d-article section > figure,
d-article section > ul,
d-article section > d-abstract,
d-article section > d-code,
d-article section > d-math,
d-article section > table {
width: calc(100% - 32px);
margin-left: 16px;
margin-right: 16px;
box-sizing: border-box;
}
.l-body-outset,
.l-page-outset,
.l-middle-outset {
width: calc(100% - 16px);
margin-left: 8px;
margin-right: 8px;
}
.l-screen {
margin-left: 0px;
margin-right: 0px;
width: 100%;
background-color: #F8F8FC;
border-top: 1px solid #E8E8EC;
border-bottom: 1px solid #E8E8EC;
}
@media(min-width: 768px) {
.l-body,
d-article > div,
d-article > p,
d-article > h1,
d-article > h2,
d-article > h3,
d-article > h4,
d-article > figure,
d-article > ul,
d-article > d-abstract,
d-article > d-code,
d-article > d-math,
d-article > d-math,
d-article section > div,
d-article section > p,
d-article section > h1,
d-article section > h2,
d-article section > h3,
d-article section > h4,
d-article section > figure,
d-article section > ul,
d-article section > d-abstract,
d-article section > d-code,
d-article section > d-math,
d-article section > table {
margin-left: 64px;
width: calc((100% - 2 * 64px - 3 * 16px)/4*3 + 2*16px );
}
.l-body-outset {
margin-left: 32px;
width: calc((100% - 2 * 64px - 3 * 16px)/4*3 + 2*16px + 64px );;
}
.l-middle,
.l-middle-outset,
.l-page {
margin-left: 64px;
margin-right: 64px;
width: calc(100% - 2*64px);
}
.l-page-outset {
margin-left: 32px;
margin-right: 32px;
width: calc(100% - 64px);
}
.margin {
font-size: 14px;
line-height: normal;
clear: both;
float: right;
margin-top: 0;
margin-left: 0;
margin-right: 64px;
width: calc((100% - 2 * 64px - 3 * 16px)/4);
}
}
@media(min-width: 1024px) {
.l-body,
d-article > div,
d-article > p,
d-article > h2,
d-article > h3,
d-article > h4,
d-article > figure,
d-article > ul,
d-article > d-abstract,
d-article > d-code,
d-article > d-math,
d-article > table,
d-article section > div,
d-article section > p,
d-article section > h2,
d-article section > h3,
d-article section > h4,
d-article section > figure,
d-article section > ul,
d-article section > d-abstract,
d-article section > d-code,
d-article section > d-math,
d-article section > table {
margin-left: calc(50% - (1024px - 2*64px) / 2);
width: 668px;
}
.l-body-outset {
margin-left: calc((50% - (1024px - 2*64px) / 2) - 32px);
width: calc(668px + 64px)
}
.l-middle,
.l-middle-outset,
.l-page {
margin-left: calc(50% - (1024px - 2*64px) / 2);
width: calc(100% - 2* (50% - (1024px - 2*64px) / 2));
}
.l-page-outset {
margin-left: calc((50% - (1024px - 2*64px) / 2) - 32px);
width: calc(100% - 2* (50% - (1024px - 2*64px) / 2) + 64px);
}
.margin {
font-size: 14px;
line-height: normal;
clear: both;
float: right;
margin-top: 0;
margin-left: 0;
margin-right: calc(50% - (1024px - 2*64px) / 2);
width: 206px;
}
/* Side */
/*
.side.l-body,
d-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,
d-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,
d-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,
d-article .side.l-middle-outset {
clear: both;
float: right;
width: 456px;
margin-left: 48px;
margin-right: calc((100vw - 984px) / 2 + 168px);
}
.side.l-page,
d-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,
d-article .side.l-page-outset {
clear: both;
float: right;
width: 624px;
margin-right: calc((100vw - 984px) / 2);
}
}*/
/* 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;
}
+30
View File
@@ -0,0 +1,30 @@
@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 {
visibility: hidden;
}
d-footer {
display: none!important;
}
}
+9
View File
@@ -0,0 +1,9 @@
import base from './styles-base.css';
import layout from './styles-layout.css';
import article from './styles-article.css';
import print from './styles-print.css';
let s = document.createElement('style');
s.textContent = base + layout + print + article;
document.querySelector('head').appendChild(s);
export default s;
+53
View File
@@ -0,0 +1,53 @@
/* eslint-env node, mocha */
/* Extractors */
import ExtractFrontmatter from './extractors/front-matter';
import ExtractBibliography from './extractors/bibliography';
import ExtractCitations from './extractors/citations';
const extractors = [
ExtractFrontmatter,
ExtractBibliography,
ExtractCitations,
];
/* Transforms */
import HTML from './transforms/html';
import Polyfills from './transforms/polyfills';
import Meta from './transforms/meta';
import Typeset from './transforms/typeset';
// import Bibliography from './transforms/bibliography';
const transforms = [
HTML, Polyfills, Meta, Typeset//, Bibliography
];
/* 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 = [
DistillHeader, DistillAppendix, DistillFooter,
];
/* Exported functions */
export function render(dom, data) {
// first, we collect static data from the dom
for (const extract of extractors) {
extract(dom, data);
}
// secondly we use it to transform parts of the dom
for (const transform of transforms) {
transform(dom, data);
}
// the function calling us can now use the transformed dom and filled data object
}
export function distillify(dom, data) {
// thirdly, we optionally use these additional transforms when publishing on the Distill website
for (const transform of distillTransforms) {
transform(dom, data);
}
}
+23
View File
@@ -0,0 +1,23 @@
const html = `
<style>
dt-banner {
background: #FFF59D;
display: block;
text-align: center;
color: black;
height: 70px;
line-height: 70px;
}
</style>
<div>This article is a draft, awaiting review for publication in Distill</div>
`;
export default function(dom, data) {
let banner = dom.createElement('dt-banner');
banner.innerHTML = html;
let b = dom.querySelector('body');
b.insertBefore(banner, b.firstChild);
banner.addEventListener('click', function() {
banner.style.display = 'none';
});
}
+27
View File
@@ -0,0 +1,27 @@
import { renderBibliography, templateString } 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 bibliographyEntries = new Map(data.citations.map( citationKey => {
const entry = data.bibliography.get(citationKey);
return [citationKey, entry];
}));
const prerenderedBibliography = dom.createElement('d-bibliography-prerendered');
const template = dom.createElement('template');
template.innerHTML = templateString;
const clone = dom.importNode(template.content, true);
prerenderedBibliography.innerHTML = template.content;
renderBibliography(prerenderedBibliography, bibliographyEntries, dom);
bibliographyTag.parentElement.insertBefore(bibliographyTag, prerenderedBibliography);
bibliographyTag.parentElement.removeChild(bibliographyTag);
}
+155
View File
@@ -0,0 +1,155 @@
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;
min-height: 90px;
}
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>
<div class="date">
<div class="month">{{publishedMonth}}. {{publishedDay}}</div>
<div class="year">{{publishedYear}}</div>
</div>
<a class="citation" href="#citation">
<div>Citation:</div>
<div>{{concatenatedAuthors}}, {{publishedYear}}</div>
</a>
</div>
`;
export default function(dom, data) {
let el = dom.querySelector('dt-byline');
if (el) {
el.innerHTML = html + mustache.render(template, data);
}
}
+234
View File
@@ -0,0 +1,234 @@
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 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]);
});
cite_hover_str = cite_hover_str.replace(/"/g, '&#39;');
var orig_string = el.innerHTML;
if (orig_string != '') orig_string += ' ';
el.innerHTML = `<span id="citation-${n}" data-hover="${cite_hover_str}">${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 ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
}
}
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(' ')});
}
}
}
+10 -10
View File
@@ -1,19 +1,19 @@
import Prism from "prismjs";
import Prism from 'prismjs';
export default function(dom, data) {
let codeElements = [].slice.call(dom.querySelectorAll("dt-code"));
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") === "") {
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/, "");
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();
let p = dom.createElement("pre");
let p = dom.createElement('pre');
p.appendChild(c);
el.appendChild(p);
} else {
@@ -21,7 +21,7 @@ export default function(dom, data) {
}
let highlighted = content;
if (Prism.languages[language]) {
c.setAttribute("class", "language-" + language);
c.setAttribute('class', 'language-' + language);
highlighted = Prism.highlight(content, Prism.languages[language]);
}
c.innerHTML = highlighted;
+25
View File
@@ -0,0 +1,25 @@
export default function(dom, data) {
var fnTags = [].slice.apply(dom.querySelectorAll('dt-fn'));
var fnContent = [];
fnTags.forEach((el,n) => {
var content = el.innerHTML;
fnContent.push(content);
n = (n+1)+'';
var key = 'fn-'+n;
var escaped_content = content.replace(/"/g, '&#39;');
el.innerHTML = `<sup><span id="${key}" data-hover="${escaped_content}" 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);
}
}
+41
View File
@@ -0,0 +1,41 @@
import ymlParse from 'js-yaml';
export default function(dom, data) {
let localData = {};
let el = dom.querySelector('script[type="text/front-matter"]');
if (el) {
let text = el.textContent;
localData = ymlParse.safeLoad(text);
}
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') {
name = author;
} else {
a.personalURL = author[name];
}
let names = name.split(' ');
a.name = name;
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];
} else {
a.affiliationURL = localData.affiliations[i][affiliation];
}
a.affiliation = affiliation;
}
return a;
});
}
+167
View File
@@ -0,0 +1,167 @@
//import xml from "xml";
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;
// 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',
}},
{ head: [
{doi_batch_id: batch_id},
{timestamp: batch_timestamp},
{depositor: [
{depositor_name: data.journal.publisherName},
{email_address: data.journal.publisherEmail},
]},
{registrant: data.journal.publisherName},
]},
{body: [
{journal: [
{journal_metadata: [
{full_title: data.journal.full_title || data.journal.title},
{abbrev_title: data.journal.abbrev_title || data.journal.title || data.journal.full_title},
{issn: data.journal.issn},
{doi_data: [
{doi: data.journal.doi},
{resource: data.journal.url},
]},
]},
{journal_issue: [
{publication_date: [
{month: date.getMonth()+1},
{year: date.getFullYear()},
]},
{journal_volume: [
{volume: data.volume},
]},
{issue: data.issue},
]},
{journal_article: [
{titles: [
{title: data.title},
]},
{ contributors:
data.authors.map((author, ind) => (
{person_name: [
{ _attr: {
contributor_role: 'author',
sequence: (ind == 0)? 'first' : 'additional'
}},
{given_name: author.firstName},
{surname: author.lastName},
{affiliation: author.affiliation}
// TODO: ORCID?
]}
))
},
{publication_date: [
{month: date.getMonth()+1},
{day: date.getDate()},
{year: date.getFullYear()}
]},
{ publisher_item: [
{item_number: data.doi}
]},
{doi_data: [
{doi: data.doi},
//{timestamp: ""},
{resource: data.url},
]},
{citation_list:
data.citations.map(key =>
citation_xml(key, data.bibliography[key]))
}
]},
]},
]},
]};
return xml(crf_data);
}
function citation_xml(key, ent){
if (ent == undefined) return {};
var info = [];
info.push({_attr: {key: key}});
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)
info.push({journal_title: ent.journal});
if ('booktitle' in ent)
info.push({volume_title: ent.booktitle});
if ('volume' in ent)
info.push({volume: ent.volume});
if ('issue' in ent)
info.push({issue: ent.issue});
if ('doi' in ent)
info.push({doi: ent.doi});
return {citation: info};
}
function xml(obj) {
//console.log(typeof(obj), obj)
if (typeof obj === 'string') 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');
let name = keys[0];
var full_content = obj[name];
var attr = {};
if (Array.isArray(full_content)){
var content = [];
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'];
} else {
//console.log(Object.keys(obj)[0])
content.push(obj);
}
}
} else {
content = full_content;
}
if (content == undefined){
content = 'undefined';
}
let attr_string = '';
for (var k in attr) {
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');
var result = `<${name}${attr_string}>\n${content}\n</${name}>`;
} else {
content = xml(content);
var result = `<${name}${attr_string}>${content}</${name}>`;
}
return result;
}
+33
View File
@@ -0,0 +1,33 @@
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] = 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}}
}`;
}
+165
View File
@@ -0,0 +1,165 @@
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 ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
}
}
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 = '<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 '?';
}
}
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(' ')});
}
}
+108
View File
@@ -0,0 +1,108 @@
function make_hover_css(pos) {
const pretty = window.innerWidth > 600;
const padding = pretty? 18 : 12;
const outer_padding = pretty ? 18 : 0;
const bbox = document.querySelector('body').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(250);
});
// 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(250);
});
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(position);
this.div.setAttribute('style', css );
}
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);
}
}
+33
View File
@@ -0,0 +1,33 @@
// 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: margin-left / body;
}
`;
}
export function page(selector) {
return `${selector} {
grid-column: margin-left / page;
}
`;
}
export function screen(selector) {
return `${selector} {
grid-column: start / end;
}
`;
}
+33
View File
@@ -0,0 +1,33 @@
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] = 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}}
}`;
}
+165
View File
@@ -0,0 +1,165 @@
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 ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
}
}
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 = '<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 '?';
}
}
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(' ')});
}
}
+108
View File
@@ -0,0 +1,108 @@
function make_hover_css(pos) {
const pretty = window.innerWidth > 600;
const padding = pretty? 18 : 12;
const outer_padding = pretty ? 18 : 0;
const bbox = document.querySelector('body').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(250);
});
// 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(250);
});
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(position);
this.div.setAttribute('style', css );
}
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);
}
}
+33
View File
@@ -0,0 +1,33 @@
// 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: margin-left / body;
}
`;
}
export function page(selector) {
return `${selector} {
grid-column: margin-left / page;
}
`;
}
export function screen(selector) {
return `${selector} {
grid-column: start / end;
}
`;
}
+33
View File
@@ -0,0 +1,33 @@
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] = 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}}
}`;
}
+165
View File
@@ -0,0 +1,165 @@
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 ` &ensp;<a href="${url}">[${label||'link'}]</a>`;
}/* else if ("doi" in ent){
return ` &ensp;<a href="https://doi.org/${ent.doi}" >[DOI]</a>`;
}*/ else {
return '';
}
}
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 = '<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 '?';
}
}
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(' ')});
}
}
+108
View File
@@ -0,0 +1,108 @@
function make_hover_css(pos) {
const pretty = window.innerWidth > 600;
const padding = pretty? 18 : 12;
const outer_padding = pretty ? 18 : 0;
const bbox = document.querySelector('body').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(250);
});
// 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(250);
});
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(position);
this.div.setAttribute('style', css );
}
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);
}
}
+33
View File
@@ -0,0 +1,33 @@
// 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: margin-left / body;
}
`;
}
export function page(selector) {
return `${selector} {
grid-column: margin-left / page;
}
`;
}
export function screen(selector) {
return `${selector} {
grid-column: start / end;
}
`;
}
+7
View File
@@ -0,0 +1,7 @@
import code from './hover-box.txt';
export default function(dom) {
let s = dom.createElement('script');
s.textContent = code;
dom.querySelector('body').appendChild(s);
}
+108
View File
@@ -0,0 +1,108 @@
// DistillHoverBox
//=====================================
function DistillHoverBox(key, pos){
if (!(key in DistillHoverBox.contentMap)){
console.error("No DistillHoverBox content registered for key", key);
}
if (key in DistillHoverBox.liveBoxes) {
console.error("There already exists a DistillHoverBox for key", key);
} else {
for (var k in DistillHoverBox.liveBoxes)
DistillHoverBox.liveBoxes[k].remove();
DistillHoverBox.liveBoxes[key] = this;
}
this.key = key;
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;
var str = `<div style="position: absolute;
background-color: #FFF;
white-s
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}" >
${DistillHoverBox.contentMap[key]}
</div>`;
this.div = appendBody(str);
DistillHoverBox.bind (this.div, key);
}
DistillHoverBox.prototype.remove = function remove(){
if (this.div) this.div.remove();
if (this.timeout) clearTimeout(this.timeout);
delete DistillHoverBox.liveBoxes[this.key];
}
DistillHoverBox.prototype.stopTimeout = function stopTimeout() {
if (this.timeout) clearTimeout(this.timeout);
}
DistillHoverBox.prototype.extendTimeout = function extendTimeout(T) {
//console.log("extend", T)
var this_ = this;
this.stopTimeout();
this.timeout = setTimeout(() => this_.remove(), T);
}
DistillHoverBox.liveBoxes = {};
DistillHoverBox.contentMap = {};
DistillHoverBox.bind = function bind(node, key) {
if (typeof node == "string"){
node = document.querySelector(node);
}
node.addEventListener("mouseover", () => {
var bbox = node.getBoundingClientRect();
if (!(key in DistillHoverBox.liveBoxes)){
new DistillHoverBox(key, [bbox.right, bbox.bottom]);
}
DistillHoverBox.liveBoxes[key].stopTimeout();
});
node.addEventListener("mouseout", () => {
if (key in DistillHoverBox.liveBoxes){
DistillHoverBox.liveBoxes[key].extendTimeout(250);
}
});
}
function appendBody(str){
var node = nodeFromString(str);
var body = document.querySelector("body");
body.appendChild(node);
return node;
}
function nodeFromString(str) {
var div = document.createElement("div");
div.innerHTML = str;
return div.firstChild;
}
var hover_es = document.querySelectorAll("span[data-hover]");
hover_es = [].slice.apply(hover_es);
hover_es.forEach((e,n) => {
var key = "hover-"+n;
var content = e.getAttribute("data-hover");
DistillHoverBox.contentMap[key] = content;
DistillHoverBox.bind(e, key);
});
+24
View File
@@ -0,0 +1,24 @@
export default function(dom) {
const head = dom.querySelector('head');
// set language to 'en'
if (!dom.querySelector('html').getAttribute('lang')) {
dom.querySelector('html').setAttribute('lang', 'en');
}
// set charset to 'utf-8'
if (!dom.querySelector('meta[charset]')) {
const meta = dom.createElement('meta');
meta.setAttribute('charset', 'utf-8');
head.appendChild(meta);
}
// set viewport
if (!dom.querySelector('meta[name=viewport]')) {
const 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);
+46 -44
View File
@@ -1,12 +1,12 @@
import favicon from './distill-favicon.base64';
import favicon from '../assets/distill-favicon.base64';
export default function(dom, data) {
let head = dom.querySelector("head");
let head = dom.querySelector('head');
let appendHead = html => appendHtml(head, html);
function meta(name, content) {
if (content)
appendHead(`<meta name="${name}" content="${content}" >`);
appendHead(` <meta name="${name}" content="${content}" >\n`);
}
appendHead(`
@@ -19,12 +19,12 @@ export default function(dom, data) {
appendHead(`
<!-- https://schema.org/Article -->
<meta property="article:published" itemprop="datePublished" content="${data.published}" />
<meta property="article:modified" itemprop="dateModified" content="${data.updated}" />
<meta property="article:published" itemprop="datePublished" content="${data.publishedYear}-${data.publishedMonthPadded}-${data.publishedDayPadded}" />
<meta property="article:modified" itemprop="dateModified" content="${data.updatedDate}" />
`);
data.authors.forEach((a) => {
appendHtml(head, `
<meta property="article:author" content="${a.firstName} ${a.lastName}" />`)
<meta property="article:author" content="${a.firstName} ${a.lastName}" />`);
});
appendHead(`
@@ -33,7 +33,7 @@ export default function(dom, data) {
<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.url}/thumbnail.png"/>
<meta property="og:image" content="${data.url}/thumbnail.jpg"/>
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="Distill" />
`);
@@ -44,66 +44,68 @@ export default function(dom, data) {
<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.url}/thumbnail.png">
<meta name="twitter:image" content="${data.url}/thumbnail.jpg">
<meta name="twitter:image:width" content="560">
<meta name="twitter:image:height" content="295">
`);
appendHead(`
<!-- https://scholar.google.com/intl/en/scholar/inclusion.html#indexing -->
`);
// 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);
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.name);
meta("citation_journal_abbrev", journal.nameAbbrev);
meta("citation_issn", journal.issn);
meta("citation_publisher", journal.publisher);
let journal = data.journal || {};
meta('citation_journal_title', journal.name);
meta('citation_journal_abbrev', journal.nameAbbrev);
meta('citation_issn', journal.issn);
meta('citation_publisher', journal.publisher);
if (data.published){
let zeroPad = (n) => { return n < 10 ? "0" + n : n; };
let publishedYear = data.published.getFullYear();
let publishedMonthPadded = zeroPad(data.published.getMonth() + 1);
let publishedDayPadded = zeroPad(data.published.getDate());
meta("citation_publication_date", `${publishedYear}/${publishedMonthPadded}/${publishedDayPadded}`);
}
if (data.publishedDate){
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);
});
(data.authors || []).forEach((a) => {
meta('citation_author', `${a.lastName}, ${a.firstName}`);
meta('citation_author_institution', a.affiliation);
});
if (data.citations) {
data.citations.forEach(key =>
meta("citation_reference", citation_meta_content(data.bibliography[key]) )
);
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){
var content = `citation_title=${ref.title};`;
ref.author.split(" and ").forEach(author => {
ref.author.split(' and ').forEach(author => {
content += `citation_author=${author.trim()};`;
});
if ("journal" in ref){
if ('journal' in ref){
content += `citation_journal_title=${ref.journal};`;
}
if ("volume" in ref) {
content += `citation_volume=${ref.volume};`;
if ('volume' in ref) {
content += `citation_volume=${ref.volume};`;
}
if ("issue" in ref || "number" in ref){
content += `citation_number=${ref.issue || ref.number};`;
if ('issue' in ref || 'number' in ref){
content += `citation_number=${ref.issue || ref.number};`;
}
/*content += `citation_first_page=${};`;
content += `citation_publication_date=${};`;*/
+52
View File
@@ -0,0 +1,52 @@
const webcomponentPath = 'https://distill.pub/third-party/polyfills/webcomponents-lite.js';
const intersectionObserverPath = 'https://distill.pub/third-party/polyfills/intersection-observer.js';
const template = `
if ('IntersectionObserver' in window &&
'IntersectionObserverEntry' in window &&
'intersectionRatio' in IntersectionObserverEntry.prototype) {
// Platform supports IntersectionObserver natively! :-)
if (!('isIntersecting' in IntersectionObserverEntry.prototype)) {
Object.defineProperty(IntersectionObserverEntry.prototype,
'isIntersecting', {
get: function () {
return this.intersectionRatio > 0;
}
});
}
} else {
// Platform does not support webcomponents--loading polyfills synchronously.
const scriptTag = document.createElement('script');
scriptTag.src = '${intersectionObserverPath}';
scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
}
if ('registerElement' in document &&
'import' in document.createElement('link') &&
'content' in document.createElement('template')) {
// Platform supports webcomponents natively! :-)
} else {
// Platform does not support webcomponents--loading polyfills synchronously.
const scriptTag = document.createElement('script');
scriptTag.src = '${webcomponentPath}';
scriptTag.async = false;
document.currentScript.parentNode.insertBefore(scriptTag, document.currentScript.nextSibling);
}
`;
export default function render(dom) {
// create polyfill script tag
const polyfillScriptTag = dom.createElement('script');
polyfillScriptTag.innerHTML = template;
polyfillScriptTag.id = 'polyfills';
// insert at appropriate position--before any other script tag
const head = dom.querySelector('head');
const firstScriptTag = dom.querySelector('script');
if (firstScriptTag) {
head.insertBefore(polyfillScriptTag, firstScriptTag);
} else {
head.appendChild(polyfillScriptTag);
}
}

Some files were not shown because too many files have changed in this diff Show More